; 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)))
-)
+ (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))))
--- /dev/null
+# 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
*.a
*.cache
-*.html
*.la
*.lo
*.log
/systemd-remount-api-vfs
/systemd-remount-fs
/systemd-reply-password
-/systemd-resolve-host
+/systemd-resolve
/systemd-resolved
/systemd-rfkill
/systemd-run
/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-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-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
" '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
- 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, ~140ch should be enough really.
+ 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.
--- /dev/null
+# 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!
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_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_name.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_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/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/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_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_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_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_name.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_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_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_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_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_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_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_name.3: man/sd_event_set_name.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_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_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_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_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_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_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_name.html: man/sd_event_set_name.html
+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
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_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_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_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)
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-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/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
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_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_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/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/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_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_name.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_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_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/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 \
LIBUDEV_REVISION=4
LIBUDEV_AGE=6
-LIBSYSTEMD_CURRENT=13
+LIBSYSTEMD_CURRENT=14
LIBSYSTEMD_REVISION=0
-LIBSYSTEMD_AGE=13
+LIBSYSTEMD_AGE=14
# The following four libraries only exist for compatibility reasons,
# their version info should not be bumped anymore
manual_tests =
TEST_EXTENSIONS = .py
PY_LOG_COMPILER = $(PYTHON)
+DISABLE_HARD_ERRORS = yes
if ENABLE_TESTS
noinst_PROGRAMS = $(manual_tests) $(tests)
TESTS = $(tests)
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 =
CLEANFILES = $(BUILT_SOURCES) \
$(pkgconfigdata_DATA) \
$(pkgconfiglib_DATA) \
+ $(nodist_bashcompletion_data) \
+ $(nodist_zshcompletion_data) \
$(in_files:.in=) $(in_in_files:.in.in=) \
$(m4_files:.m4=)
systemd-system-update-generator \
systemd-debug-generator
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA = \
+dist_bashcompletion_data = \
shell-completion/bash/busctl \
shell-completion/bash/journalctl \
shell-completion/bash/systemd-analyze \
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 = \
+nodist_bashcompletion_data = \
shell-completion/bash/systemctl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA = \
+dist_zshcompletion_data = \
shell-completion/zsh/_busctl \
shell-completion/zsh/_journalctl \
shell-completion/zsh/_udevadm \
shell-completion/zsh/_systemd-delta \
shell-completion/zsh/_systemd
-nodist_zshcompletion_DATA = \
+nodist_zshcompletion_data = \
shell-completion/zsh/_systemctl
-endif
EXTRA_DIST += \
shell-completion/bash/systemctl.in \
shell-completion/zsh/_systemctl.in
-CLEANFILES += \
- $(nodist_bashcompletion_DATA) \
- $(nodist_zshcompletion_DATA)
-
dist_sysctl_DATA = \
sysctl.d/50-default.conf
README.md \
autogen.sh \
.dir-locals.el \
+ .editorconfig \
.vimrc \
.ycm_extra_conf.py \
.travis.yml \
noinst_DATA += \
$(HTML_FILES) \
- $(HTML_ALIAS)
+ $(HTML_ALIAS) \
+ docs/html/man
+endif
CLEANFILES += \
$(man_MANS) \
$(HTML_FILES) \
- $(HTML_ALIAS)
+ $(HTML_ALIAS) \
+ docs/html/man
docs/html/man:
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_LN)$(LN_S) -f ../../man $@
-noinst_DATA += \
- docs/html/man
-
-CLEANFILES += \
- docs/html/man
-
-if HAVE_PYTHON
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
man/systemd.index.xml \
man/systemd.directives.xml
-EXTRA_DIST += \
- tools/make-man-rules.py
-
-endif
-
-endif
-
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
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/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/copy.h \
src/basic/alloc-util.h \
src/basic/alloc-util.c \
- src/basic/formats-util.h
+ src/basic/formats-util.h \
+ src/basic/nss-util.h
nodist_libbasic_la_SOURCES = \
src/basic/errno-from-name.h \
src/shared/base-filesystem.h \
src/shared/uid-range.c \
src/shared/uid-range.h \
- src/shared/nss-util.h \
src/shared/install.c \
src/shared/install.h \
src/shared/install-printf.c \
src/shared/machine-image.c \
src/shared/machine-image.h \
src/shared/machine-pool.c \
- src/shared/machine-pool.h
+ src/shared/machine-pool.h \
+ src/shared/resolve-util.c \
+ src/shared/resolve-util.h
if HAVE_UTMP
libshared_la_SOURCES += \
test-ipcrm \
test-btrfs \
test-acd \
- test-ipv4ll-manual
+ test-ipv4ll-manual \
+ test-ask-password-api
if HAVE_LIBIPTC
manual_tests += \
test-copy \
test-cap-list \
test-sigbus \
+ test-rbtree \
test-verbs \
test-af-list \
test-arphrd-list \
test-dns-domain \
- test-install-root
+ 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 \
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_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_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
systemd-tmpfiles-setup-dev.service \
systemd-tmpfiles-setup.service
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_systemd-tmpfiles
-endif
TIMERS_TARGET_WANTS += \
systemd-tmpfiles-clean.timer
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
# ------------------------------------------------------------------------------
bin_PROGRAMS += \
bootctl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/bootctl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_bootctl
endif
-endif
# ------------------------------------------------------------------------------
if HAVE_GNUEFI
EXTRA_DIST += $(systemd_boot_sources) $(systemd_boot_headers)
-if ENABLE_EFI
-if HAVE_GNUEFI
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)
-CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(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/
endif
endif
+CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot)
+
# ------------------------------------------------------------------------------
stub_headers = \
src/boot/efi/util.h \
$(stub_headers) \
test/splash.bmp
-if ENABLE_EFI
-if HAVE_GNUEFI
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)
-CLEANFILES += $(stub_objects) $(stub_solib) $(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/
$(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: test-efi-disk.img
$(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-efi-disk.img
-endif
-endif
EXTRA_DIST += test/test-efi-create-disk.sh
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/libsystemd/sd-bus/bus-dump.h \
src/libsystemd/sd-utf8/sd-utf8.c \
src/libsystemd/sd-event/sd-event.c \
- src/libsystemd/sd-event/event-util.h \
src/libsystemd/sd-netlink/sd-netlink.c \
src/libsystemd/sd-netlink/netlink-internal.h \
src/libsystemd/sd-netlink/netlink-message.c \
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 \
- src/libsystemd/sd-resolve/resolve-util.h
+ src/libsystemd/sd-resolve/sd-resolve.c
libsystemd_internal_la_LIBADD = \
libbasic.la \
src/libsystemd-network/lldp-port.c \
src/libsystemd-network/lldp-internal.h \
src/libsystemd-network/lldp-internal.c \
- src/libsystemd-network/lldp-util.h \
src/libsystemd-network/sd-lldp.c
libsystemd_network_la_LIBADD = \
hwdb/sdio.ids
# ------------------------------------------------------------------------------
+if ENABLE_TESTS
TESTS += \
test/udev-test.pl
test/sysv-generator-test.py
endif
endif
+endif
manual_tests += \
test-libudev \
$(BLKID_LIBS) \
$(KMOD_LIBS)
+if ENABLE_TESTS
check_DATA += \
test/sys
+endif
# packed sysfs test tree
test/sys:
systemd_journal_remote_LDADD += \
$(MICROHTTPD_LIBS)
-if ENABLE_SYSUSERS
-dist_sysusers_DATA += \
- sysusers.d/systemd-remote.conf
-endif
-
if ENABLE_TMPFILES
dist_tmpfiles_DATA += \
tmpfiles.d/systemd-remote.conf
src/journal/journalctl.c
journalctl_LDADD = \
- libshared.la
+ libshared.la \
+ libudev-core.la
if HAVE_QRENCODE
journalctl_SOURCES += \
# ------------------------------------------------------------------------------
if ENABLE_COREDUMP
systemd_coredump_SOURCES = \
- src/journal/coredump.c \
- src/journal/coredump-vacuum.c \
- src/journal/coredump-vacuum.h
+ 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/journal/stacktrace.c \
- src/journal/stacktrace.h
+ 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/journal/coredump.conf
+ src/coredump/coredump.conf
coredumpctl_SOURCES = \
- src/journal/coredumpctl.c
+ src/coredump/coredumpctl.c
coredumpctl_LDADD = \
libshared.la
test-coredump-vacuum
test_coredump_vacuum_SOURCES = \
- src/journal/test-coredump-vacuum.c \
- src/journal/coredump-vacuum.c \
- src/journal/coredump-vacuum.h
+ src/coredump/test-coredump-vacuum.c \
+ src/coredump/coredump-vacuum.c \
+ src/coredump/coredump-vacuum.h
test_coredump_vacuum_LDADD = \
libshared.la
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/coredumpctl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_coredumpctl
-endif
nodist_sysctl_DATA = \
sysctl.d/50-coredump.conf
endif
EXTRA_DIST += \
- sysctl.d/50-coredump.conf.in
+ sysctl.d/50-coredump.conf.in \
+ units/systemd-coredump@.service.in
# ------------------------------------------------------------------------------
if ENABLE_BINFMT
bin_PROGRAMS += \
hostnamectl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/hostnamectl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_hostnamectl
endif
-endif
polkitpolicy_in_files += \
src/hostname/org.freedesktop.hostname1.policy.in
bin_PROGRAMS += \
localectl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/localectl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_localectl
endif
-endif
.PHONY: update-kbd-model-map
bin_PROGRAMS += \
timedatectl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/timedatectl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_timedatectl
endif
-endif
polkitpolicy_in_files += \
src/timedate/org.freedesktop.timedate1.policy.in
nodist_systemd_timesyncd_SOURCES = \
src/timesync/timesyncd-gperf.c
-gperf_gperf_sources += \
- src/timesync/timesyncd-gperf.gperf
-
systemd_timesyncd_LDADD = \
libsystemd-network.la \
libshared.la
GENERAL_ALIASES += \
$(systemunitdir)/systemd-timesyncd.service $(pkgsysconfdir)/system/sysinit.target.wants/systemd-timesyncd.service
-EXTRA_DIST += \
- units/systemd-timesyncd.service.in
-
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
-endif
# ------------------------------------------------------------------------------
if HAVE_MYHOSTNAME
-Wl,--version-script=$(top_srcdir)/src/nss-myhostname/nss-myhostname.sym
libnss_myhostname_la_LIBADD = \
- libshared.la
+ libsystemd-internal.la
lib_LTLIBRARIES += \
libnss_myhostname.la
rootbin_PROGRAMS += \
machinectl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
- shell-completion/bash/machinectl
-endif
-
test_machine_tables_SOURCES = \
src/machine/test-machine-tables.c
polkitpolicy_files += \
src/machine/org.freedesktop.machine1.policy
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_bashcompletion_data += \
+ shell-completion/bash/machinectl
+
+dist_zshcompletion_data += \
shell-completion/zsh/_machinectl \
shell-completion/zsh/_sd_machines
-endif
SYSTEM_UNIT_ALIASES += \
systemd-machined.service dbus-org.freedesktop.machine1.service
-Wl,--version-script=$(top_srcdir)/src/nss-mymachines/nss-mymachines.sym
libnss_mymachines_la_LIBADD = \
- libshared.la
+ libsystemd-internal.la
lib_LTLIBRARIES += \
libnss_mymachines.la
src/import/pull-raw.h \
src/import/pull-tar.c \
src/import/pull-tar.h \
- src/import/pull-dkr.c \
- src/import/pull-dkr.h \
src/import/pull-job.c \
src/import/pull-job.h \
src/import/pull-common.c \
src/import/org.freedesktop.import1.policy.in
EXTRA_DIST += \
- units/systemd-importd.service.in \
- src/resolve/resolved.conf.in
+ 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-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
src/resolve/dns_type-to-name.h \
src/resolve/resolved-gperf.c
-gperf_gperf_sources += \
- src/resolve/resolved-gperf.gperf
-
-gperf_txt_sources += \
- src/resolve/dns_type-list.txt
-
systemd_resolved_LDADD = \
libsystemd-network.la \
libshared.la
nodist_pkgsysconf_DATA += \
src/resolve/resolved.conf
-tests += \
- test-dns-domain
-
libnss_resolve_la_SOURCES = \
src/nss-resolve/nss-resolve.sym \
src/nss-resolve/nss-resolve.c
-Wl,--version-script=$(top_srcdir)/src/nss-resolve/nss-resolve.sym
libnss_resolve_la_LIBADD = \
- libshared.la \
+ libsystemd-internal.la \
-ldl
lib_LTLIBRARIES += \
libnss_resolve.la
-systemd_resolve_host_SOURCES = \
- src/resolve-host/resolve-host.c \
+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/dns-type.c \
src/resolve/dns-type.h
-nodist_systemd_resolve_host_SOURCES = \
+nodist_systemd_resolve_SOURCES = \
src/resolve/dns_type-from-name.h \
src/resolve/dns_type-to-name.h
-systemd_resolve_host_LDADD = \
+systemd_resolve_LDADD = \
libshared.la
-rootlibexec_PROGRAMS += \
- systemd-resolve-host
+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
+ units/systemd-resolved.service.m4.in \
+ src/resolve/resolved.conf.in
# ------------------------------------------------------------------------------
if ENABLE_NETWORKD
libshared.la \
libsystemd-network.la
+dist_bashcompletion_data += \
+ shell-completion/bash/networkctl
+
test_network_SOURCES = \
src/network/test-network.c
BUSNAMES_TARGET_WANTS += \
org.freedesktop.network1.busname
+endif
+
gperf_gperf_sources += \
src/network/networkd-network-gperf.gperf \
src/network/networkd-netdev-gperf.gperf
-endif
EXTRA_DIST += \
units/systemd-networkd.service.m4.in \
- units/systemd-networkd-wait-online.service.in
+ units/systemd-networkd-wait-online.service.in \
+ test/networkd-test.py
# ------------------------------------------------------------------------------
if ENABLE_LOGIND
rootbin_PROGRAMS += \
loginctl
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
shell-completion/bash/loginctl
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
shell-completion/zsh/_loginctl \
shell-completion/zsh/_systemd-inhibit
-endif
systemd_inhibit_SOURCES = \
src/login/inhibit.c
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 += \
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GPERF)$(GPERF) < $< > $@
-src/%: src/%.m4
+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
+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
+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
+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
+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 < $< > $@
$(polkitpolicy_in_in_files)
# ------------------------------------------------------------------------------
-if ENABLE_MANPAGES
man/custom-entities.ent: configure.ac
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)(echo '<?xml version="1.0" encoding="utf-8" ?>' && \
--stringparam systemd.version $(VERSION) \
--path '$(builddir)/man:$(srcdir)/man'
+XSLT = $(if $(XSLTPROC), $(XSLTPROC), xsltproc)
XSLTPROC_PROCESS_MAN = \
- $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $<
+ $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $<
XSLTPROC_PROCESS_HTML = \
- $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-html.xsl $<
+ $(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)
$(AM_V_LN)$(LN_S) -f $(notdir $<) $@
endef
-endif
-
EXTRA_DIST += \
man/custom-html.xsl \
man/custom-man.xsl
--disable-split-usr
endif
-#
-# Require python when making dist
-#
-.PHONY: dist-check-python dist-check-compat-libs dist-check-help
-dist-check-python:
-if !HAVE_PYTHON
- @echo "*** python and python-lxml module must be installed and enabled in order to make dist"
- @false
-endif
-
-dist-check-compat-libs:
-if !ENABLE_COMPAT_LIBS
- @echo "*** compat-libs must be enabled in order to make dist"
- @false
-endif
+.PHONY: dist-check-help
dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS)
for i in $(abspath $^); do \
exit 1; \
fi; done
-dist: dist-check-python dist-check-compat-libs
-
.PHONY: hwdb-update
hwdb-update:
( cd $(top_srcdir)/hwdb && \
doc-sync: all
rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/
-.PHONY: gardel
-gardel:
- scp man/*.html gardel:public/systemd-man/
-
-.PHONY: lennart-fedora
-lennart-fedora:
- cp -v systemd-$(VERSION).tar.xz /home/lennart/git.fedora/systemd/
-
.PHONY: install-tree
install-tree: all
rm -rf $(abs_srcdir)/install-tree
tree $(abs_srcdir)/install-tree
# Let's run all tests of the test suite, but under valgrind. Let's
-# exclude the one perl script we have in there
+# exclude perl/python/shell scripts we have in there
.PHONY: valgrind-tests
valgrind-tests: $(TESTS)
- $(AM_V_GEN)for f in $(filter-out %.pl, $^); do \
+ $(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; \
+ $(LIBTOOL) --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \
x="\n\n"; \
done
systemd 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
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
MAILING LIST:
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
- http://lists.freedesktop.org/mailman/listinfo/systemd-commits
IRC:
#systemd on irc.freenode.org
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:
needs to look like, and provide an implementation at the marked places.
WARNINGS:
- systemd will freeze execution during boot if /etc/mtab exists
- but is not a symlink to /proc/mounts. Please ensure that
- /etc/mtab is a proper symlink.
-
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
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
+ <chris@kinvolk.io> for more information.
## 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)
+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).
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
* consider throwing a warning if a service declares it wants to be "Before=" a .device unit.
-* "systemctl edit" should know a mode to create a new unit file
-
* 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.
* man: document that unless you use StandardError=null the shell >/dev/stderr won't work in shell scripts in services
-* "systemctl daemon-reload" should result in /etc/systemd/system.conf being reloaded by systemd
-
* install: include generator dirs in unit file search paths
-* invent a better systemd-run scheme for naming scopes, that works with remoting
-
* rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring
to unicode chars, to make things more expressive.
* Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
-* core/cgroup: support net_cls modules, and support automatically allocating class ids, then add support for making firewall changes depending on it, to implement a per-service firewall
+* implement a per-service firewall based on net_cls
* Port various tools to make use of verbs.[ch], where applicable
* maybe provide an API to allow migration of foreign PIDs into existing scopes.
-* maybe support a new very "soft" reboot mode, that simply kills all processes, disassembles everything, flushes /run and sysvipc, and then reexecs systemd again
-
* man: maybe use the word "inspect" rather than "introspect"?
* systemctl: if some operation fails, show log output?
- 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 and resolved when we cannot reach a server
+* exponential backoff in timesyncd when we cannot reach a server
-* timesyncd + resolved: add ugly bus calls to set NTP and DNS servers per-interface, for usage by NM
+* 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
(throughout the codebase, not only PID1)
* resolved:
- - put networkd events and rtnl events at a higher priority, so that
- we always process them before we process client requests
- - DNSSEC
- - add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)?
- - DNS
- - search paths
- mDNS/DNS-SD
+ - service registration
+ - service/domain/types browsing
- avahi compat
- DNS-SD service registration from socket units
- - edns0
- - dname: Not necessary for plain DNS as synthesized cname is handed out instead if we do not
- announce dname support. However, for DNSSEC it is necessary as the synthesized cname
- will not be signed.
- - cname on PTR (?)
- 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
* generator that automatically discovers btrfs subvolumes, identifies their purpose based on some xattr on them.
-* timer units: actually add extra delays to timer units with high AccuracySec values, don't start them already when we are awake...
-
* 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
- generate a failure of a default event loop is executed out-of-thread
- maybe add support for inotify events
-* in the final killing spree, detect processes from the root directory, and
- complain loudly if they have argv[0][0] == '@' set.
- https://bugzilla.redhat.com/show_bug.cgi?id=961044
-
* investigate endianness issues of UUID vs. GUID
* dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we
- journal-or-kmsg is currently broken? See reverted
commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8.
- man: document that corrupted journal files is nothing to act on
- - systemd-journal-upload (or a new, related tool): allow pushing out
- journal messages onto the network in BSD syslog protocol,
- continuously. Default to some link-local IP mcast group, to make this
- useful as a one-stop debugging tool.
- 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
removed or added to an existing machine
- "machinectl migrate" or similar to copy a container from or to a
difference host, via ssh
- - man: document how update dkr images works with machinectl
- http://lists.freedesktop.org/archives/systemd-devel/2015-February/028630.html
- 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
shell in it, and marks it read-only after use
* importd:
- - dkr: support tarsum checksum verification, if it becomes reality one day...
- - dkr: convert json bits to nspawn configuration
- generate a nice warning if mkfs.btrfs is missing
* cryptsetup:
* coredump:
- save coredump in Windows/Mozilla minidump format
- move PID 1 segfaults to /var/lib/systemd/coredump?
- - make the handler check /proc/$PID/rlimits for RLIMIT_CORE,
- and supress coredump if turned off. Then change RLIMIT_CORE to
- infinity by default for all services. This then allows per-service
- control of coredumping.
* support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
- 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
- - make timer units go away after they elapsed
- 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
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
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.
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+
+# 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.
# This file is part of systemd.
#
# Copyright 2012 Lennart Poettering
-# Copyright 2013 Sergey Ptashnick
+# 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
Процесс, отвечающий за журналирование системных событий, завершил работу и
закрыл все свои файлы.
+# 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: Часть сообщений от службы пропущена
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 был отозван. Необходимо настроить новый
+открытый ключ, либо обновить систему, чтобы получить обновленный открытый ключ.
--- /dev/null
+@@
+expression e, fmt;
+expression list vaargs;
+@@
+- snprintf(e, sizeof(e), fmt, vaargs);
++ xsprintf(e, fmt, vaargs);
AC_PREREQ([2.64])
AC_INIT([systemd],
- [228],
+ [229],
[http://github.com/systemd/systemd/issues],
[systemd],
[http://www.freedesktop.org/wiki/Software/systemd])
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, LO_FLAGS_PARTSCAN],
+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 <sys/types.h>
#include <unistd.h>
# ------------------------------------------------------------------------------
have_bzip2=no
-AC_ARG_ENABLE(bzip2, AS_HELP_STRING([--enable-bzip2], [Disable optional BZIP2 support]))
+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])
esac],
[have_smack=auto])
-if test "x${have_smack}" = xauto; then
+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],
[AC_DEFINE_UNQUOTED(SMACK_DEFAULT_PROCESS_LABEL, ["$withval"], [Default SMACK label for executed processes])],
[])
-if test "x${have_smack}" = xyes ; then
- AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
-fi
-
-AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"])
-
# ------------------------------------------------------------------------------
AC_ARG_ENABLE([gcrypt],
AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
if test "x${have_gcrypt}" != xno ; then
m4_define([AM_PATH_LIBGCRYPT_FAIL],
- [{ test "x$have_gcrypt" != xyes || AC_MSG_ERROR([*** GCRYPT headers not found.]); }]
+ [{ 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],
[AM_PATH_LIBGCRYPT_FAIL]
)
- if test "x$have_gcrypt" = xyes ; then
- GCRYPT_LIBS="$LIBGCRYPT_LIBS"
- GCRYPT_CFLAGS="$LIBGCRYPT_CFLAGS"
+ 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=
fi
AM_CONDITIONAL(HAVE_QRENCODE, [test "$have_qrencode" = "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], 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_gnutls=no
AC_ARG_ENABLE(gnutls, AS_HELP_STRING([--disable-gnutls], [disable gnutls support]))
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], have_libcurl=no)
+ [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]))
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"])
AC_SUBST([EFI_MACHINE_TYPE_NAME])
have_gnuefi=no
-AC_ARG_ENABLE(gnuefi, AS_HELP_STRING([--enable-gnuefi], [Disable optional gnuefi support]))
+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_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
- AC_PATH_PROG([XSLTPROC], [xsltproc])
AS_IF([test -z "$XSLTPROC"],
AC_MSG_ERROR([*** xsltproc is required for man pages]))
])
enable_split_usr=no
])])
-AC_ARG_WITH([dkr-index-url],
- [AS_HELP_STRING([--dkr-index-url=URL], [Specify the default index URL to use for image downloads])],
- [DEFAULT_DKR_INDEX_URL="\"$withval\""],
- [DEFAULT_DKR_INDEX_URL="NULL"])
-
-AC_DEFINE_UNQUOTED(DEFAULT_DKR_INDEX_URL, [$DEFAULT_DKR_INDEX_URL], [Default index URL to use for image downloads])
-AC_SUBST(DEFAULT_DKR_INDEX_URL)
-
AS_IF([test "x${enable_split_usr}" = "xyes"], [
AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr])
])
Maximum System UID: ${SYSTEM_UID_MAX}
Maximum System GID: ${SYSTEM_GID_MAX}
Certificate root: ${CERTIFICATEROOT}
- Default dkr Index ${DEFAULT_DKR_INDEX_URL}
CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
OUI:001BC5090*
ID_OUI_FROM_DATABASE=Seven Solutions S.L
-OUI:001BC5087*
- ID_OUI_FROM_DATABASE=Onnet Technologies And Innovations
-
OUI:001BC507D*
ID_OUI_FROM_DATABASE=Greatcom AG
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:70B3D51F4*
ID_OUI_FROM_DATABASE=Hangzhou Woosiyuan Communication Co.,Ltd.
-OUI:70B3D5B7E*
- ID_OUI_FROM_DATABASE=Elbit Systems of America - FMF Operations
-
OUI:70B3D5092*
ID_OUI_FROM_DATABASE=inomed Medizintechnik GmbH
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:70B3D5F2A*
ID_OUI_FROM_DATABASE=WIBOND Informationssysteme GmbH
-OUI:70B3D5C24*
- ID_OUI_FROM_DATABASE=Elbit Systems of America
-
OUI:70B3D52A5*
ID_OUI_FROM_DATABASE=Taitotekniikka
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:70B3D5A0B*
ID_OUI_FROM_DATABASE=ambiHome GmbH
-OUI:70B3D58B1*
- ID_OUI_FROM_DATABASE=M-Tech Innovations Ltd
-
OUI:70B3D5204*
ID_OUI_FROM_DATABASE=TWC
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:70B3D5308*
ID_OUI_FROM_DATABASE=DSD MICROTECHNOLOGY,INC.
-OUI:70B3D5184*
- ID_OUI_FROM_DATABASE=XV360 Optical Information Systems Ltd.
-
OUI:70B3D56D3*
ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
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: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: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: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:2C265FB*
ID_OUI_FROM_DATABASE=Rexgen Inc.
-OUI:2C265FC*
- ID_OUI_FROM_DATABASE=AATON DIGITAL
-
OUI:2C265F6*
ID_OUI_FROM_DATABASE=Appostar Technology 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: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:88CBA5*
ID_OUI_FROM_DATABASE=Suzhou Torchstar Intelligent Technology Co.,Ltd
-OUI:A47B2C*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:184F32*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:7CA237*
ID_OUI_FROM_DATABASE=King Slide Technology CO., LTD.
-OUI:B0E2E5*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:300EE3*
ID_OUI_FROM_DATABASE=Aquantia Corporation
OUI:B0ECE1*
ID_OUI_FROM_DATABASE=Private
-OUI:AC9B0A*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
OUI:407FE0*
ID_OUI_FROM_DATABASE=Glory Star Technics (ShenZhen) Limited
OUI:88C9D0*
ID_OUI_FROM_DATABASE=LG Electronics
-OUI:BC6B4D*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:3428F0*
ID_OUI_FROM_DATABASE=ATN International Limited
OUI:6C0273*
ID_OUI_FROM_DATABASE=Shenzhen Jin Yun Video Equipment Co., Ltd.
-OUI:600292*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:2CFAA2*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
OUI:3CCD5A*
ID_OUI_FROM_DATABASE=Technische Alternative GmbH
-OUI:B0754D*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:604826*
ID_OUI_FROM_DATABASE=Newbridge Technologies Int. Ltd.
OUI:54EE75*
ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
-OUI:202564*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:60812B*
ID_OUI_FROM_DATABASE=Custom Control Concepts
OUI:FC4AE9*
ID_OUI_FROM_DATABASE=Castlenet Technology Inc.
-OUI:BC8D0E*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:34E42A*
ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc.
OUI:107BEF*
ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
-OUI:84262B*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:8CCDA2*
ID_OUI_FROM_DATABASE=ACTP, Inc.
OUI:AC6BAC*
ID_OUI_FROM_DATABASE=Jenny Science AG
-OUI:0C54A5*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:707C18*
ID_OUI_FROM_DATABASE=ADATA Technology Co., Ltd
OUI:041A04*
ID_OUI_FROM_DATABASE=WaveIP
-OUI:94E98C*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:50206B*
ID_OUI_FROM_DATABASE=Emerson Climate Technologies Transportation Solutions
OUI:404A18*
ID_OUI_FROM_DATABASE=Addrek Smart Solutions
-OUI:E48184*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:C4C0AE*
ID_OUI_FROM_DATABASE=MIDORI ELECTRONIC CO., LTD.
OUI:08EF3B*
ID_OUI_FROM_DATABASE=MCS Logic Inc.
-OUI:98B039*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:806C8B*
ID_OUI_FROM_DATABASE=KAESER KOMPRESSOREN AG
OUI:E8D4E0*
ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd.
-OUI:54BEF7*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:3889DC*
ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V.
OUI:14D76E*
ID_OUI_FROM_DATABASE=CONCH ELECTRONIC Co.,Ltd
-OUI:1078D2*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
-
OUI:CC6B98*
ID_OUI_FROM_DATABASE=Minetec Wireless Technologies
OUI:2CCD27*
ID_OUI_FROM_DATABASE=Precor Inc
-OUI:AC44F2*
- ID_OUI_FROM_DATABASE=Revolabs Inc
-
OUI:6C5E7A*
ID_OUI_FROM_DATABASE=Ubiquitous Internet Telecom Co., Ltd
OUI:002473*
ID_OUI_FROM_DATABASE=3COM EUROPE LTD
-OUI:002465*
- ID_OUI_FROM_DATABASE=Elentec
-
OUI:002460*
ID_OUI_FROM_DATABASE=Giaval Science Development Co. Ltd.
OUI:001F26*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001F1F*
- ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
-
OUI:001F1A*
ID_OUI_FROM_DATABASE=Prominvest
OUI:001E96*
ID_OUI_FROM_DATABASE=Sepura Plc
-OUI:001E90*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co
-
OUI:001E8B*
ID_OUI_FROM_DATABASE=Infra Access Korea Co., Ltd.
OUI:001F0F*
ID_OUI_FROM_DATABASE=Select Engineered Systems
-OUI:001F09*
- ID_OUI_FROM_DATABASE=JASTEC CO., LTD.
-
OUI:001EFD*
ID_OUI_FROM_DATABASE=Microbit 2.0 AB
OUI:001E34*
ID_OUI_FROM_DATABASE=CryptoMetrics
-OUI:001E33*
- ID_OUI_FROM_DATABASE=Inventec Corporation
-
OUI:001E2D*
ID_OUI_FROM_DATABASE=STIM
OUI:001CDC*
ID_OUI_FROM_DATABASE=Custom Computer Services, Inc.
-OUI:001CD7*
- ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
-
OUI:001CD0*
ID_OUI_FROM_DATABASE=Circleone Co.,Ltd.
OUI:001A33*
ID_OUI_FROM_DATABASE=ASI Communications, Inc.
-OUI:001A29*
- ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics, Inc
-
OUI:001A1D*
ID_OUI_FROM_DATABASE=PChome Online Inc.
OUI:00170B*
ID_OUI_FROM_DATABASE=Contela, Inc.
-OUI:001706*
- ID_OUI_FROM_DATABASE=Techfaith Wireless Communication Technology Limited.
-
-OUI:0016FA*
- ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
-
OUI:0016FF*
ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp
OUI:0016E7*
ID_OUI_FROM_DATABASE=Dynamix Promotions Limited
-OUI:0016EC*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
OUI:0016DB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
OUI:001454*
ID_OUI_FROM_DATABASE=Symwave
-OUI:00144F*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:001443*
ID_OUI_FROM_DATABASE=Consultronics Europe Ltd
OUI:00118F*
ID_OUI_FROM_DATABASE=EUTECH INSTRUMENTS PTE. LTD.
-OUI:001188*
- ID_OUI_FROM_DATABASE=Enterasys
-
OUI:001183*
ID_OUI_FROM_DATABASE=Datalogic ADC, Inc.
OUI:000D8E*
ID_OUI_FROM_DATABASE=Koden Electronics Co., Ltd.
-OUI:000D87*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
OUI:000D84*
ID_OUI_FROM_DATABASE=Makus Inc.
OUI:000AE4*
ID_OUI_FROM_DATABASE=Wistron Corp.
-OUI:000AE6*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
OUI:000A0E*
ID_OUI_FROM_DATABASE=Invivo Research Inc.
OUI:00901A*
ID_OUI_FROM_DATABASE=UNISPHERE SOLUTIONS
-OUI:0090AE*
- ID_OUI_FROM_DATABASE=ITALTEL S.p.A.
-
OUI:009082*
ID_OUI_FROM_DATABASE=FORCE INSTITUTE
OUI:001057*
ID_OUI_FROM_DATABASE=Rebel.com, Inc.
-OUI:0010E0*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:0010BC*
ID_OUI_FROM_DATABASE=Aastra Telecom
OUI:00A0EA*
ID_OUI_FROM_DATABASE=ETHERCOM CORP.
-OUI:00A0B8*
- ID_OUI_FROM_DATABASE=SYMBIOS LOGIC INC.
-
OUI:00A02E*
ID_OUI_FROM_DATABASE=BRAND COMMUNICATIONS, LTD.
OUI:ACE010*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-OUI:000BA2*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
OUI:EC086B*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:2421AB*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
-OUI:001FA7*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
-OUI:A8E3EE*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
OUI:6C23B9*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
OUI:00EB2D*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
-OUI:709E29*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:FC0FE6*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
OUI:B00594*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
OUI:0015D0*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:001315*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
OUI:0013A9*
ID_OUI_FROM_DATABASE=Sony Corporation
OUI:5C9656*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
-OUI:0881F4*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:A8D0E5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:648788*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:28C0DA*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:80711F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:00239C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001DB5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:7C4CA5*
ID_OUI_FROM_DATABASE=BSkyB Ltd
OUI:001F32*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-OUI:D8FB5E*
- ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
-
OUI:544408*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:0017B0*
+OUI:D8FB5E*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
+OUI:1886AC*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001BEE*
+OUI:0021FE*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:1886AC*
+OUI:001DFD*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:0021FE*
+OUI:001EA3*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
OUI:002266*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:DCB3B4*
- ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd.
+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:F4F5A5*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:3CC243*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:DCB3B4*
+ ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd.
-OUI:0015A0*
+OUI:001D98*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001A16*
+OUI:00119F*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:0022FC*
+OUI:0015A0*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:002548*
+OUI:001A16*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001DFD*
+OUI:0022FC*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001EA3*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:3CC243*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:001D98*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:18A6F7*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:00119F*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+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:68F956*
ID_OUI_FROM_DATABASE=Objetivos y Servicio de Valor Añadido
-OUI:C07CD1*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:58B633*
ID_OUI_FROM_DATABASE=Ruckus Wireless
OUI:A47B85*
ID_OUI_FROM_DATABASE=ULTIMEDIA Co Ltd,
-OUI:A8D828*
- ID_OUI_FROM_DATABASE=Bayer HealthCare
-
OUI:CC37AB*
ID_OUI_FROM_DATABASE=Edgecore Networks Corportation
OUI:546172*
ID_OUI_FROM_DATABASE=ZODIAC AEROSPACE SAS
-OUI:AC620D*
- ID_OUI_FROM_DATABASE=Jabil Circuit (Wuxi) Co. LTD
-
OUI:54CD10*
ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd.
OUI:683C7D*
ID_OUI_FROM_DATABASE=Magic Intelligence Technology Limited
-OUI:18A3E8*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:60128B*
ID_OUI_FROM_DATABASE=CANON INC.
OUI:C4913A*
ID_OUI_FROM_DATABASE=Shenzhen Sanland Electronic Co., ltd.
-OUI:60B617*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:A46032*
ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
OUI:F80DEA*
ID_OUI_FROM_DATABASE=ZyCast Technology Inc.
-OUI:7C0507*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:1800DB*
ID_OUI_FROM_DATABASE=Fitbit Inc.
OUI:74FE48*
ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD.
-OUI:7054D2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:D0B498*
ID_OUI_FROM_DATABASE=Robert Bosch LLC Automotive Electronics
OUI:645FFF*
ID_OUI_FROM_DATABASE=Nicolet Neuro
-OUI:741E93*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:2829D9*
ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd
OUI:289EDF*
ID_OUI_FROM_DATABASE=Danfoss Turbocor Compressors, Inc
-OUI:E840F2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:50053D*
ID_OUI_FROM_DATABASE=CyWee Group Ltd
OUI:504A5E*
ID_OUI_FROM_DATABASE=Masimo Corporation
-OUI:4CC94F*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:38BF33*
ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications
OUI:68D925*
ID_OUI_FROM_DATABASE=ProSys Development Services
-OUI:2C2D48*
- ID_OUI_FROM_DATABASE=bct electronic GesmbH
-
OUI:B41DEF*
ID_OUI_FROM_DATABASE=Internet Laboratories, Inc.
OUI:28D1AF*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:3482DE*
- ID_OUI_FROM_DATABASE=Kayo Technology, Inc.
-
OUI:68BC0C*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:0007AB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:48F7F1*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:D453AF*
ID_OUI_FROM_DATABASE=VIGO System S.A.
OUI:447E95*
ID_OUI_FROM_DATABASE=Alpha and Omega, Inc
-OUI:50C971*
- ID_OUI_FROM_DATABASE=GN Netcom A/S
-
OUI:E8B748*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:C8AACC*
ID_OUI_FROM_DATABASE=Private
-OUI:008CFA*
- ID_OUI_FROM_DATABASE=Inventec Corporation
-
OUI:003D41*
ID_OUI_FROM_DATABASE=Hatteland Computer AS
OUI:0025B0*
ID_OUI_FROM_DATABASE=Schmartz Inc
-OUI:002552*
- ID_OUI_FROM_DATABASE=VXI CORPORATION
-
OUI:002546*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:0022B6*
ID_OUI_FROM_DATABASE=Superflow Technologies Group
-OUI:0022B1*
- ID_OUI_FROM_DATABASE=Elbit Systems
-
OUI:0022A3*
ID_OUI_FROM_DATABASE=California Eastern Laboratories
OUI:001E99*
ID_OUI_FROM_DATABASE=Vantanol Industrial Corporation
-OUI:001F45*
- ID_OUI_FROM_DATABASE=Enterasys
-
OUI:001F36*
ID_OUI_FROM_DATABASE=Bellwin Information Co. Ltd.,
OUI:001D7E*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-OUI:001D82*
- ID_OUI_FROM_DATABASE=GN A/S (GN Netcom A/S)
-
OUI:001D7D*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:00162C*
ID_OUI_FROM_DATABASE=Xanboo
-OUI:001625*
- ID_OUI_FROM_DATABASE=Impinj, Inc.
-
OUI:001627*
ID_OUI_FROM_DATABASE=embedded-logic DESIGN AND MORE GmbH
OUI:001323*
ID_OUI_FROM_DATABASE=Cap Co., Ltd.
-OUI:001317*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
OUI:00130B*
ID_OUI_FROM_DATABASE=Mextal B.V.
OUI:000CBC*
ID_OUI_FROM_DATABASE=Iscutum
-OUI:000CC1*
- ID_OUI_FROM_DATABASE=Cooper Industries Inc.
-
OUI:000CA3*
ID_OUI_FROM_DATABASE=Rancho Technology, Inc.
OUI:0008BF*
ID_OUI_FROM_DATABASE=Aptus Elektronik AB
-OUI:0008B9*
- ID_OUI_FROM_DATABASE=KAON MEDIA Co., Ltd.
-
OUI:0008B3*
ID_OUI_FROM_DATABASE=Fastwel
OUI:000658*
ID_OUI_FROM_DATABASE=Helmut Fischer GmbH Institut für Elektronik und Messtechnik
-OUI:00065F*
- ID_OUI_FROM_DATABASE=ECI Telecom - NGTS Ltd.
-
OUI:000646*
ID_OUI_FROM_DATABASE=ShenZhen XunBao Network Technology Co Ltd
OUI:00501B*
ID_OUI_FROM_DATABASE=ABL CANADA, INC.
-OUI:005058*
- ID_OUI_FROM_DATABASE=VegaStream Group Limted
-
OUI:005036*
ID_OUI_FROM_DATABASE=NETCAM, LTD.
OUI:009051*
ID_OUI_FROM_DATABASE=ULTIMATE TECHNOLOGY CORP.
-OUI:0090F9*
- ID_OUI_FROM_DATABASE=LEITCH
-
OUI:0090FF*
ID_OUI_FROM_DATABASE=TELLUS TECHNOLOGY INC.
OUI:0090CC*
ID_OUI_FROM_DATABASE=Planex Communications
-OUI:0090FA*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
OUI:009004*
ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
OUI:00E06D*
ID_OUI_FROM_DATABASE=COMPUWARE CORPORATION
-OUI:00E0E6*
- ID_OUI_FROM_DATABASE=INCAA DATACOM B.V.
-
OUI:00E074*
ID_OUI_FROM_DATABASE=TIERNAN COMMUNICATIONS, INC.
OUI:00A07B*
ID_OUI_FROM_DATABASE=DAWN COMPUTER INCORPORATION
-OUI:00A0DE*
- ID_OUI_FROM_DATABASE=YAMAHA CORPORATION
-
OUI:00A05C*
ID_OUI_FROM_DATABASE=INVENTORY CONVERSION, INC./
OUI:00A062*
ID_OUI_FROM_DATABASE=AES PRODATA
-OUI:00A0F4*
- ID_OUI_FROM_DATABASE=GE
-
OUI:00A008*
ID_OUI_FROM_DATABASE=NETCORP
OUI:00001F*
ID_OUI_FROM_DATABASE=Telco Systems, Inc.
-OUI:0000B4*
- ID_OUI_FROM_DATABASE=EDIMAX COMPUTER COMPANY
-
OUI:000058*
ID_OUI_FROM_DATABASE=RACORE COMPUTER PRODUCTS INC.
OUI:3010B3*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-OUI:00005F*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
-OUI:0008F6*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
OUI:001802*
ID_OUI_FROM_DATABASE=Alpha Networks Inc.
OUI:74A528*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:3C8AB0*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:4C9614*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:88E0F3*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:2C2172*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:7819F7*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:5C5EAB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:009069*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:B0C69A*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:88A25E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001BC0*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:30A220*
ID_OUI_FROM_DATABASE=ARG Telecom
-OUI:F4B52F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:783E53*
ID_OUI_FROM_DATABASE=BSkyB Ltd
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:D08CB5*
ID_OUI_FROM_DATABASE=Texas Instruments
-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:0030C5*
+ ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC.
-OUI:B0B448*
- ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:00FEC8*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:F08261*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:BC5436*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:D084B0*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:0CC731*
+ ID_OUI_FROM_DATABASE=Currant, Inc.
-OUI:00FEC8*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00142F*
+ ID_OUI_FROM_DATABASE=Savvius
-OUI:0030C5*
- ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC.
+OUI:70CA4D*
+ ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd.
-OUI:EC2280*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:DCC0EB*
+ ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE
OUI:047863*
ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd.
OUI:24DA11*
ID_OUI_FROM_DATABASE=NO NDA Inc
-OUI:70CA4D*
- ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd.
+OUI:BCD1D3*
+ ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
-OUI:DCC0EB*
- ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE
+OUI:BC4434*
+ ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
-OUI:001735*
- ID_OUI_FROM_DATABASE=Intel Wireless Network Group
+OUI:0041D2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:9CDFB1*
- ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD
+OUI:4CFB45*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:5CF938*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A4BA76*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:3871DE*
ID_OUI_FROM_DATABASE=Apple, 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:2CDDA3*
ID_OUI_FROM_DATABASE=Point Grey Research Inc.
OUI:F88FCA*
ID_OUI_FROM_DATABASE=Google, Inc.
-OUI:BCD1D3*
- ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:14D64D*
+ ID_OUI_FROM_DATABASE=D-Link International
-OUI:BC4434*
- ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:C8BE19*
+ ID_OUI_FROM_DATABASE=D-Link International
-OUI:0041D2*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:BCF685*
+ ID_OUI_FROM_DATABASE=D-Link International
-OUI:4CFB45*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:CCB255*
+ ID_OUI_FROM_DATABASE=D-Link International
-OUI:A4BA76*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:84C9B2*
+ ID_OUI_FROM_DATABASE=D-Link International
-OUI:003676*
- ID_OUI_FROM_DATABASE=Pace plc
+OUI:EC2280*
+ ID_OUI_FROM_DATABASE=D-Link International
OUI:78E3B5*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:0C47C9*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
-OUI:0017E6*
+OUI:001831*
ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:0017E8*
+OUI:0023D4*
ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:9059AF*
+OUI:3C2DB7*
ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:E0C79D*
+OUI:40984E*
ID_OUI_FROM_DATABASE=Texas Instruments
-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:3C7DB1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:CCB255*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:505663*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:84C9B2*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:B0B448*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:DCD321*
- ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:0017E6*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:CC4EEC*
- ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:0017E8*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:88C255*
+OUI:9059AF*
ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:DC330D*
- ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd
+OUI:E0C79D*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:0080E1*
- ID_OUI_FROM_DATABASE=STMicroelectronics SRL
+OUI:003676*
+ ID_OUI_FROM_DATABASE=Pace plc
OUI:58DC6D*
ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc.
OUI:78F882*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
-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:C8CBB8*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:3C4A92*
ID_OUI_FROM_DATABASE=Hewlett Packard
-OUI:780AC7*
- ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd.
+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:001E0B*
ID_OUI_FROM_DATABASE=Hewlett Packard
-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:C005C2*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:6455B1*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
OUI:0002B3*
ID_OUI_FROM_DATABASE=Intel Corporation
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:A01D48*
ID_OUI_FROM_DATABASE=Hewlett Packard
-OUI:001DD3*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+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:3CDFA9*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:94B2CC*
- ID_OUI_FROM_DATABASE=PIONEER CORPORATION
-
-OUI:887F03*
- ID_OUI_FROM_DATABASE=Comper Technology Investment Limited
-
-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:C005C2*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:002719*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:6455B1*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:40169F*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:DCD321*
+ ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
-OUI:940C6D*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:CC4EEC*
+ ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
-OUI:74EA3A*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:88C255*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:90F652*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:DC330D*
+ ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd
-OUI:10FEED*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:94B2CC*
+ ID_OUI_FROM_DATABASE=PIONEER CORPORATION
-OUI:C46E1F*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:887F03*
+ ID_OUI_FROM_DATABASE=Comper Technology Investment Limited
OUI:50FA84*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:F02765*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
-OUI:507224*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-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:88308A*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
-OUI:048A15*
- ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:44A7CF*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:44322A*
ID_OUI_FROM_DATABASE=Avaya Inc
OUI:104780*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:88308A*
- ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:30D17E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:44A7CF*
- ID_OUI_FROM_DATABASE=Murata Manufacturing 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:00664B*
ID_OUI_FROM_DATABASE=HUAWEI 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*
+OUI:7C6097*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:F48E92*
+OUI:60DE44*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:40CBA8*
+OUI:3400A3*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:087A4C*
+OUI:643E8C*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:D46E5C*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0012D1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:2469A5*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:70FF76*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:C8D15E*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:B4994C*
+ ID_OUI_FROM_DATABASE=Texas Instruments
-OUI:F83DFF*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:507224*
+ ID_OUI_FROM_DATABASE=Texas Instruments
OUI:308730*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:6CA849*
ID_OUI_FROM_DATABASE=Avaya Inc
-OUI:30D17E*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:9C28EF*
- 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:00C610*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:70DEE2*
- ID_OUI_FROM_DATABASE=Apple, 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:048A15*
+ ID_OUI_FROM_DATABASE=Avaya Inc
-OUI:C8334B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:D4970B*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
-OUI:B8F6B1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F48B32*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
-OUI:C09F42*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:20A783*
+ ID_OUI_FROM_DATABASE=miControl GmbH
-OUI:189EFC*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:005053*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:6C3E6D*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:00500F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:0016FE*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
+OUI:0050A2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:0498F3*
ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
OUI:E4AA5D*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:000389*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
-OUI:0CE0E4*
- ID_OUI_FROM_DATABASE=PLANTRONICS, 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:00E08F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
OUI:203A07*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:70105C*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:7CFADF*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C067AF*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:101C0C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:001124*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:64E950*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001D4F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:B0AA77*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001E52*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:78BAF9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001F5B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0016B6*
+ ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-OUI:001FF3*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0018F8*
+ ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-OUI:0021E9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:00252E*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
-OUI:00236C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A4A24A*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
-OUI:002500*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:602AD0*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
-OUI:60FB42*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:001BFB*
+ ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
-OUI:14DAE9*
- ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:0016FE*
+ ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
OUI:3C08F6*
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:406C8F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:C067AF*
+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:64E950*
+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*
OUI:00248C*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
-OUI:0050A2*
- ID_OUI_FROM_DATABASE=Cisco Systems, 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:14DAE9*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
-OUI:00100B*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:182032*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:00100D*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:6CC26B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:001014*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:1040F3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:649ABE*
+OUI:FC253F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:94E96A*
+OUI:183451*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:AC293A*
+OUI:C0847A*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:10417F*
+OUI:64200C*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:7014A6*
+OUI:74E1B6*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:A8667F*
+OUI:0C771A*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:D02598*
+OUI:00F4B9*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:CC29F5*
+OUI:C8334B*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:802994*
- ID_OUI_FROM_DATABASE=Technicolor CH USA
+OUI:B8F6B1*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:6C709F*
+OUI:C09F42*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:0C3E9F*
+OUI:189EFC*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:34E2FD*
+OUI:6C3E6D*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:609217*
+OUI:8C2DAA*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:8863DF*
+OUI:444C0C*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:80E650*
+OUI:84FCFE*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:006171*
+OUI:E48B7F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:90FD61*
+OUI:94E96A*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:5C97F3*
+OUI:AC293A*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:6C4008*
+OUI:10417F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:24A074*
+OUI:7014A6*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:F02475*
+OUI:A8667F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:20A2E4*
+OUI:D02598*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:5CF5DA*
+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:28E14C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:54E43A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
OUI:C8E0EB*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:848E0C*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:8C2DAA*
+OUI:6C709F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:444C0C*
+OUI:0C3E9F*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:84FCFE*
+OUI:34E2FD*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:E48B7F*
+OUI:609217*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:5C969D*
+OUI:8863DF*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:A8FAD8*
+OUI:80E650*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:949426*
+OUI:006171*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:E0F5C6*
+OUI:90FD61*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:AC6462*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:5C97F3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:C08488*
- ID_OUI_FROM_DATABASE=Finis Inc
+OUI:6C4008*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:68E8EB*
- ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd
+OUI:24A074*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:20C3A4*
- ID_OUI_FROM_DATABASE=RetailNext
+OUI:F02475*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:780541*
- ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd
+OUI:20A2E4*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:C02DEE*
- ID_OUI_FROM_DATABASE=Cuff
+OUI:5CF5DA*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:54A3FA*
- ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd
+OUI:649ABE*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:30F772*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:5C969D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:9023EC*
- ID_OUI_FROM_DATABASE=Availink, Inc.
+OUI:A8FAD8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:7467F7*
- ID_OUI_FROM_DATABASE=Zebra Technologoes
+OUI:949426*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:3891D5*
- ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+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:381C23*
ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD
-OUI:E03676*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES 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:24DA9B*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
-OUI:3052CB*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:7467F7*
+ ID_OUI_FROM_DATABASE=Zebra Technologoes
-OUI:DCFE07*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+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:50A9DE*
ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD
-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:C02DEE*
+ ID_OUI_FROM_DATABASE=Cuff
-OUI:B844D9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:54A3FA*
+ ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd
-OUI:DC2B2A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:30F772*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
-OUI:8C10D4*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:9023EC*
+ ID_OUI_FROM_DATABASE=Availink, Inc.
OUI:203D66*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
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:BC5FF6*
- ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+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: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:D8EFCD*
ID_OUI_FROM_DATABASE=Nokia
-OUI:D404CD*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:EC0133*
- ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC.
+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:E8BDD1*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-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:307CB2*
ID_OUI_FROM_DATABASE=ANOV FRANCE
-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:FCE33C*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
OUI:BC6A2F*
ID_OUI_FROM_DATABASE=Henge Docks LLC
OUI:1CF03E*
ID_OUI_FROM_DATABASE=Wearhaus Inc.
-OUI:DCDB70*
- ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH
-
-OUI:C47D46*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:BCF811*
+ ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd
-OUI:68EDA4*
- ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd
+OUI:A8827F*
+ ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd
-OUI:B899B0*
- ID_OUI_FROM_DATABASE=Cohere Technologies
+OUI:609C9F*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-OUI:2CC5D3*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:249EAB*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:80C5E6*
- ID_OUI_FROM_DATABASE=Microsoft Corporation
+OUI:DC56E6*
+ ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD
-OUI:D85DEF*
- ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH
+OUI:5CA178*
+ ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk)
-OUI:10DF8B*
- ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd
+OUI:A0B437*
+ ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSEMS
-OUI:00A784*
- ID_OUI_FROM_DATABASE=ITX security
+OUI:B89ACD*
+ ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD
OUI:800184*
ID_OUI_FROM_DATABASE=HTC Corporation
OUI:B46D35*
ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd
-OUI:B89ACD*
- ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD
+OUI:FCE33C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-OUI:241C04*
- ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD.
+OUI:68EDA4*
+ ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd
-OUI:F8CFC5*
- ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:B899B0*
+ ID_OUI_FROM_DATABASE=Cohere Technologies
-OUI:BCF811*
- ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd
+OUI:2CC5D3*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
-OUI:A8827F*
- ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd
+OUI:80C5E6*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
-OUI:609C9F*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+OUI:D85DEF*
+ ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH
-OUI:900A39*
- ID_OUI_FROM_DATABASE=Wiio, Inc.
+OUI:10DF8B*
+ ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd
-OUI:C4693E*
- ID_OUI_FROM_DATABASE=Turbulence Design Inc.
+OUI:00A784*
+ ID_OUI_FROM_DATABASE=ITX security
-OUI:1C8341*
- ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd
+OUI:3481F4*
+ ID_OUI_FROM_DATABASE=SST Taiwan Ltd.
-OUI:4011DC*
- ID_OUI_FROM_DATABASE=Sonance
+OUI:F4B8A7*
+ ID_OUI_FROM_DATABASE=zte corporation
-OUI:249EAB*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:58F102*
+ ID_OUI_FROM_DATABASE=BLU Products Inc.
-OUI:DC56E6*
- ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD
+OUI:B869C2*
+ ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
-OUI:5CA178*
- ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk)
+OUI:2CC548*
+ ID_OUI_FROM_DATABASE=IAdea Corporation
-OUI:A0B437*
- ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSEMS
+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: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:F41563*
ID_OUI_FROM_DATABASE=F5 Networks, Inc.
-OUI:C4EA1D*
- ID_OUI_FROM_DATABASE=Technicolor
-
-OUI:20E407*
- ID_OUI_FROM_DATABASE=Spark srl
-
-OUI:887384*
- ID_OUI_FROM_DATABASE=Toshiba
-
-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:4011DC*
+ ID_OUI_FROM_DATABASE=Sonance
OUI:749CE3*
ID_OUI_FROM_DATABASE=Art2Wave Canada Inc.
OUI:3C8C40*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
-OUI:0071C2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:D45556*
ID_OUI_FROM_DATABASE=Fiber Mountain Inc.
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: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:60F189*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
-OUI:74A34A*
- ID_OUI_FROM_DATABASE=ZIMI CORPORATION
-
-OUI:98F5A9*
- ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD.
+OUI:241C04*
+ ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD.
-OUI:D89341*
- ID_OUI_FROM_DATABASE=General Electric Global Research
+OUI:F8CFC5*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
-OUI:F4645D*
- ID_OUI_FROM_DATABASE=Toshiba
+OUI:7C11CD*
+ ID_OUI_FROM_DATABASE=QianTang Technology
-OUI:30D587*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:0492EE*
+ ID_OUI_FROM_DATABASE=iway AG
OUI:B04519*
ID_OUI_FROM_DATABASE=TCT mobile ltd
OUI:844464*
ID_OUI_FROM_DATABASE=ServerU Inc
-OUI:589B0B*
- ID_OUI_FROM_DATABASE=Shineway Technologies, 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:3C2C94*
ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd)
-OUI:78312B*
- ID_OUI_FROM_DATABASE=zte corporation
-
-OUI:C035C5*
- ID_OUI_FROM_DATABASE=Prosoft Systems LTD
-
-OUI:F8B2F3*
- ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD
-
-OUI:1C7D22*
- ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd.
-
-OUI:ACD1B8*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
-
-OUI:7C11CD*
- ID_OUI_FROM_DATABASE=QianTang Technology
-
-OUI:0492EE*
- ID_OUI_FROM_DATABASE=iway AG
-
OUI:48A9D2*
ID_OUI_FROM_DATABASE=Wistron Neweb Corp.
OUI:F02A23*
ID_OUI_FROM_DATABASE=Creative Next Design
-OUI:8C9109*
- ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd.
+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:B4A828*
ID_OUI_FROM_DATABASE=Shenzhen Concox Information Technology Co., Ltd
-OUI:A41242*
- ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
-
-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:F409D8*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
+OUI:50F43C*
+ ID_OUI_FROM_DATABASE=Leeo Inc
OUI:FCDBB3*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:E00DB9*
ID_OUI_FROM_DATABASE=Private
-OUI:108A1B*
- ID_OUI_FROM_DATABASE=RAONIX Inc.
+OUI:A41242*
+ ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
OUI:8CF813*
ID_OUI_FROM_DATABASE=ORANGE POLSKA
OUI:D01242*
ID_OUI_FROM_DATABASE=BIOS Corporation
-OUI:50F43C*
- ID_OUI_FROM_DATABASE=Leeo Inc
-
-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:D062A0*
- ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd.
-
-OUI:CC10A3*
- ID_OUI_FROM_DATABASE=Beijing Nan Bao Technology Co., Ltd.
+OUI:6CBFB5*
+ ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd
OUI:2CA30E*
ID_OUI_FROM_DATABASE=POWER DRAGON DEVELOPMENT LIMITED
OUI:F82441*
ID_OUI_FROM_DATABASE=Yeelink
-OUI:6CBFB5*
- ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd
+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:80F8EB*
ID_OUI_FROM_DATABASE=RayTight
-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:F409D8*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
-OUI:CC3F1D*
- ID_OUI_FROM_DATABASE=Intesis Software SL
+OUI:C035C5*
+ ID_OUI_FROM_DATABASE=Prosoft Systems LTD
-OUI:902181*
- ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd
+OUI:F8B2F3*
+ ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD
-OUI:600417*
- ID_OUI_FROM_DATABASE=POSBANK 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:488244*
ID_OUI_FROM_DATABASE=Life Fitness / Div. of Brunswick
-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:D85DFB*
+ ID_OUI_FROM_DATABASE=Private
-OUI:D4B43E*
- ID_OUI_FROM_DATABASE=Messcomp Datentechnik GmbH
+OUI:7CC4EF*
+ ID_OUI_FROM_DATABASE=Devialet
OUI:A8E539*
ID_OUI_FROM_DATABASE=Moimstone 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:7CE524*
- ID_OUI_FROM_DATABASE=Quirky, Inc.
-
-OUI:D85DFB*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:7CC4EF*
- ID_OUI_FROM_DATABASE=Devialet
-
OUI:94AEE3*
ID_OUI_FROM_DATABASE=Belden Hirschmann Industries (Suzhou) Ltd.
OUI:0C8C8F*
ID_OUI_FROM_DATABASE=Kamo Technology Limited
-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:3CD9CE*
ID_OUI_FROM_DATABASE=Eclipse WiFi
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:A8A668*
ID_OUI_FROM_DATABASE=zte corporation
-OUI:60E327*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:A8F7E0*
+ ID_OUI_FROM_DATABASE=PLANET Technology Corporation
-OUI:E4D332*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:2C5BE1*
+ ID_OUI_FROM_DATABASE=Centripetal Networks, Inc
-OUI:A0DA92*
- ID_OUI_FROM_DATABASE=Nanjing Glarun Atten Technology Co. Ltd.
+OUI:D87EB1*
+ ID_OUI_FROM_DATABASE=x.o.ware, inc.
-OUI:6828BA*
- ID_OUI_FROM_DATABASE=Dejai
+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: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:085700*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
OUI:888914*
ID_OUI_FROM_DATABASE=All Components Incorporated
OUI:748F1B*
ID_OUI_FROM_DATABASE=MasterImage 3D
-OUI:F03A4B*
- ID_OUI_FROM_DATABASE=Bloombase, Inc.
+OUI:684898*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:E4121D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:B48547*
ID_OUI_FROM_DATABASE=Amptown System Company GmbH
-OUI:3C25D7*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:085700*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:1889DF*
- ID_OUI_FROM_DATABASE=CerebrEX Inc.
+OUI:60E327*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:30A8DB*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+OUI:E4D332*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:CC9F35*
- ID_OUI_FROM_DATABASE=Transbit Sp. z o.o.
+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:2C073C*
ID_OUI_FROM_DATABASE=DEVLINE LIMITED
-OUI:7CE4AA*
- ID_OUI_FROM_DATABASE=Private
+OUI:F015A0*
+ ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd.
-OUI:1820A6*
- ID_OUI_FROM_DATABASE=Sage Co., Ltd.
+OUI:ECF72B*
+ ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD.
-OUI:BCF61C*
- ID_OUI_FROM_DATABASE=Geomodeling Wuxi Technology Co. Ltd.
+OUI:D8B6D6*
+ ID_OUI_FROM_DATABASE=Blu Tether Limited
-OUI:083F3E*
- ID_OUI_FROM_DATABASE=WSH GmbH
+OUI:847207*
+ ID_OUI_FROM_DATABASE=I&C Technology
-OUI:6C09D6*
- ID_OUI_FROM_DATABASE=Digiquest Electronics LTD
+OUI:3C25D7*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:684898*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+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:8CDE99*
ID_OUI_FROM_DATABASE=Comlab Inc.
-OUI:1088CE*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:085AE0*
+ ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd.
-OUI:FCF647*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.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:80D433*
ID_OUI_FROM_DATABASE=LzLabs GmbH
-OUI:085AE0*
- ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd.
+OUI:687CC8*
+ ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L.
-OUI:BCEE7B*
- ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:38BF2F*
+ ID_OUI_FROM_DATABASE=Espec Corp.
-OUI:8C3AE3*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:182012*
+ ID_OUI_FROM_DATABASE=Aztech Associates Inc.
-OUI:FC09D8*
- ID_OUI_FROM_DATABASE=ACTEON Group
+OUI:34BE00*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:0C1262*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:343111*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:687CC8*
- ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L.
+OUI:0CBD51*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
-OUI:F015A0*
- ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd.
+OUI:C0F991*
+ ID_OUI_FROM_DATABASE=GME Standard Communications P/L
-OUI:ECF72B*
- ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD.
+OUI:14EDA5*
+ ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme
-OUI:D8B6D6*
- ID_OUI_FROM_DATABASE=Blu Tether Limited
+OUI:E056F4*
+ ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc.
-OUI:847207*
- ID_OUI_FROM_DATABASE=I&C Technology
+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:BC9889*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:2C553C*
ID_OUI_FROM_DATABASE=Gainspeed, Inc.
OUI:50B888*
ID_OUI_FROM_DATABASE=wi2be Tecnologia S/A
-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:844F03*
ID_OUI_FROM_DATABASE=Ablelink Electronics Ltd
OUI:68692E*
ID_OUI_FROM_DATABASE=Zycoo Co.,Ltd
-OUI:A875E2*
- ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
-
-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:385AA8*
- ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co.
-
-OUI:FC3FAB*
- ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd
-
-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:1C63B7*
+ ID_OUI_FROM_DATABASE=OpenProducts 237 AB
-OUI:A88D7B*
- ID_OUI_FROM_DATABASE=SunDroid Global limited.
+OUI:A0A23C*
+ ID_OUI_FROM_DATABASE=GPMS
OUI:A03B1B*
ID_OUI_FROM_DATABASE=Inspire Tech
OUI:0CCB8D*
ID_OUI_FROM_DATABASE=ASCO Numatics GmbH
-OUI:2847AA*
+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*
OUI:FCB0C4*
ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd
-OUI:1C63B7*
- ID_OUI_FROM_DATABASE=OpenProducts 237 AB
+OUI:9CBB98*
+ ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD
-OUI:A0A23C*
- ID_OUI_FROM_DATABASE=GPMS
+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:A0E5E9*
ID_OUI_FROM_DATABASE=enimai Inc
-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:B462AD*
- ID_OUI_FROM_DATABASE=raytest GmbH
+OUI:A88D7B*
+ ID_OUI_FROM_DATABASE=SunDroid Global limited.
OUI:6064A1*
ID_OUI_FROM_DATABASE=RADiflow Ltd.
OUI:AC5036*
ID_OUI_FROM_DATABASE=Pi-Coral Inc
-OUI:FC019E*
- ID_OUI_FROM_DATABASE=VIEVU
-
-OUI:34AA8B*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:BCEE7B*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
-OUI:F45F69*
- ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company
+OUI:8C3AE3*
+ ID_OUI_FROM_DATABASE=LG Electronics
-OUI:F4A294*
- ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED
+OUI:FC09D8*
+ ID_OUI_FROM_DATABASE=ACTEON Group
-OUI:2CCD69*
- ID_OUI_FROM_DATABASE=Aqavi.com
+OUI:0C1262*
+ ID_OUI_FROM_DATABASE=zte corporation
-OUI:947C3E*
- ID_OUI_FROM_DATABASE=Polewall Norge AS
+OUI:A875E2*
+ ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
OUI:E0D1E6*
ID_OUI_FROM_DATABASE=Aliph dba Jawbone
OUI:A0C6EC*
ID_OUI_FROM_DATABASE=ShenZhen ANYK Technology Co.,LTD
-OUI:C80258*
- ID_OUI_FROM_DATABASE=ITW GSE ApS
+OUI:6405BE*
+ ID_OUI_FROM_DATABASE=NEW LIGHT LED
-OUI:1001CA*
- ID_OUI_FROM_DATABASE=Ashley Butterworth
+OUI:F8FF5F*
+ ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd
-OUI:246AAB*
- ID_OUI_FROM_DATABASE=IT-IS International
+OUI:DCC422*
+ ID_OUI_FROM_DATABASE=Systembase Limited
-OUI:28F532*
- ID_OUI_FROM_DATABASE=ADD-Engineering BV
+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:00B78D*
ID_OUI_FROM_DATABASE=Nanjing Shining Electric Automation Co., Ltd
-OUI:68E166*
- ID_OUI_FROM_DATABASE=Private
+OUI:882364*
+ ID_OUI_FROM_DATABASE=Watchnet DVR Inc
-OUI:60FEF9*
- ID_OUI_FROM_DATABASE=Thomas & Betts
+OUI:A05B21*
+ ID_OUI_FROM_DATABASE=ENVINET GmbH
-OUI:78FE41*
- ID_OUI_FROM_DATABASE=Socus networks
+OUI:50B8A2*
+ ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
-OUI:083571*
- ID_OUI_FROM_DATABASE=CASwell INC.
+OUI:A41566*
+ ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
-OUI:DCF755*
- ID_OUI_FROM_DATABASE=SITRONIK
+OUI:B04C05*
+ ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH
-OUI:E42D02*
- ID_OUI_FROM_DATABASE=TCT Mobile Limited
+OUI:A0EC80*
+ ID_OUI_FROM_DATABASE=zte corporation
-OUI:ACCA8E*
- ID_OUI_FROM_DATABASE=ODA Technologies
+OUI:9046B7*
+ ID_OUI_FROM_DATABASE=Vadaro Pte Ltd
-OUI:6405BE*
- ID_OUI_FROM_DATABASE=NEW LIGHT LED
+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:28D93E*
ID_OUI_FROM_DATABASE=Telecor Inc.
-OUI:882364*
- ID_OUI_FROM_DATABASE=Watchnet DVR Inc
-
-OUI:A05B21*
- ID_OUI_FROM_DATABASE=ENVINET GmbH
+OUI:C80258*
+ ID_OUI_FROM_DATABASE=ITW GSE ApS
-OUI:50B8A2*
- ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
+OUI:1001CA*
+ ID_OUI_FROM_DATABASE=Ashley Butterworth
-OUI:A41566*
- ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
+OUI:246AAB*
+ ID_OUI_FROM_DATABASE=IT-IS International
-OUI:B04C05*
- ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH
+OUI:28F532*
+ ID_OUI_FROM_DATABASE=ADD-Engineering BV
-OUI:A0EC80*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:78FE41*
+ ID_OUI_FROM_DATABASE=Socus networks
-OUI:9046B7*
- ID_OUI_FROM_DATABASE=Vadaro Pte Ltd
+OUI:083571*
+ ID_OUI_FROM_DATABASE=CASwell INC.
-OUI:1C08C1*
- ID_OUI_FROM_DATABASE=Lg Innotek
+OUI:DCF755*
+ ID_OUI_FROM_DATABASE=SITRONIK
-OUI:201D03*
- ID_OUI_FROM_DATABASE=Elatec GmbH
+OUI:E42D02*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
-OUI:C06C6D*
- ID_OUI_FROM_DATABASE=MagneMotion, Inc.
+OUI:ACCA8E*
+ ID_OUI_FROM_DATABASE=ODA Technologies
OUI:74CA25*
ID_OUI_FROM_DATABASE=Calxeda, Inc.
OUI:CCBD35*
ID_OUI_FROM_DATABASE=Steinel GmbH
-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:68DB67*
- ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd
-
-OUI:BC261D*
- ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY
-
-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:D0EB03*
- ID_OUI_FROM_DATABASE=Zhehua technology limited
-
-OUI:A0861D*
- ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd
-
OUI:9498A2*
ID_OUI_FROM_DATABASE=Shanghai LISTEN TECH.LTD
OUI:6472D8*
ID_OUI_FROM_DATABASE=GooWi Technology Co.,Limited
-OUI:84ACA4*
- ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd
+OUI:3C081E*
+ ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd
-OUI:3C6FF7*
- ID_OUI_FROM_DATABASE=EnTek Systems, Inc.
+OUI:7CA15D*
+ ID_OUI_FROM_DATABASE=GN ReSound A/S
-OUI:B838CA*
- ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD
+OUI:B4DD15*
+ ID_OUI_FROM_DATABASE=ControlThings Oy Ab
-OUI:380FE4*
- ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy
+OUI:F8FEA8*
+ ID_OUI_FROM_DATABASE=Technico Japan Corporation
-OUI:847A88*
- ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:A8154D*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:0808C2*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:D05099*
+ ID_OUI_FROM_DATABASE=ASRock Incorporation
-OUI:5461EA*
- ID_OUI_FROM_DATABASE=Zaplox AB
+OUI:78A106*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:78324F*
- ID_OUI_FROM_DATABASE=Millennium Group, Inc.
+OUI:A49EDB*
+ ID_OUI_FROM_DATABASE=AutoCrib, Inc.
-OUI:F05DC8*
- ID_OUI_FROM_DATABASE=Duracell Powermat
+OUI:282CB2*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:48F925*
- ID_OUI_FROM_DATABASE=Maestronic
+OUI:D43A65*
+ ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd.
-OUI:C0885B*
- ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
+OUI:D0EB03*
+ ID_OUI_FROM_DATABASE=Zhehua technology limited
-OUI:64C667*
- ID_OUI_FROM_DATABASE=Barnes&Noble
+OUI:A0861D*
+ ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd
-OUI:C47DCC*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:888964*
+ ID_OUI_FROM_DATABASE=GSI Electronics Inc.
-OUI:64535D*
- ID_OUI_FROM_DATABASE=Frauscher Sensortechnik
+OUI:4C82CF*
+ ID_OUI_FROM_DATABASE=Echostar Technologies
-OUI:105F06*
- ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+OUI:9CA577*
+ ID_OUI_FROM_DATABASE=Osorno Enterprises Inc.
-OUI:841715*
- ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd.
+OUI:C0C3B6*
+ ID_OUI_FROM_DATABASE=Automatic Systems
-OUI:087999*
- ID_OUI_FROM_DATABASE=AIM GmbH
+OUI:A8294C*
+ ID_OUI_FROM_DATABASE=Precision Optical Transceivers, Inc.
-OUI:84C2E4*
- ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd.
+OUI:3C86A8*
+ ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD
-OUI:C0B8B1*
- ID_OUI_FROM_DATABASE=BitBox Ltd
+OUI:FCDD55*
+ ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd
-OUI:0C722C*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:CC0DEC*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
-OUI:B01408*
- ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO.
+OUI:68B094*
+ ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD
-OUI:F8FEA8*
- ID_OUI_FROM_DATABASE=Technico Japan Corporation
+OUI:40E730*
+ ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc.
-OUI:A8154D*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:F05DC8*
+ ID_OUI_FROM_DATABASE=Duracell Powermat
-OUI:D05099*
- ID_OUI_FROM_DATABASE=ASRock Incorporation
+OUI:6C8686*
+ ID_OUI_FROM_DATABASE=Technonia
-OUI:78A106*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:4432C8*
+ ID_OUI_FROM_DATABASE=Technicolor USA Inc.
-OUI:A49EDB*
- ID_OUI_FROM_DATABASE=AutoCrib, Inc.
+OUI:78521A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:282CB2*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:68DB67*
+ ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd
-OUI:D43A65*
- ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd.
+OUI:BC261D*
+ ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY
OUI:10B9FE*
ID_OUI_FROM_DATABASE=Lika srl
OUI:104D77*
ID_OUI_FROM_DATABASE=Innovative Computer Engineering
-OUI:3C081E*
- ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd
+OUI:788DF7*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
-OUI:7CA15D*
- ID_OUI_FROM_DATABASE=GN ReSound A/S
+OUI:6CECA1*
+ ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD.
-OUI:B4DD15*
- ID_OUI_FROM_DATABASE=ControlThings Oy Ab
+OUI:D862DB*
+ ID_OUI_FROM_DATABASE=Eno Inc.
-OUI:3C86A8*
- ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD
+OUI:A8D236*
+ ID_OUI_FROM_DATABASE=Lightware Visual Engineering
-OUI:FCDD55*
- ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd
+OUI:48F925*
+ ID_OUI_FROM_DATABASE=Maestronic
-OUI:CC0DEC*
- ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:C0885B*
+ ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
-OUI:68B094*
- ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD
+OUI:64C667*
+ ID_OUI_FROM_DATABASE=Barnes&Noble
-OUI:40E730*
- ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc.
+OUI:C47DCC*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Inc
-OUI:A8D236*
- ID_OUI_FROM_DATABASE=Lightware Visual Engineering
+OUI:64535D*
+ ID_OUI_FROM_DATABASE=Frauscher Sensortechnik
-OUI:6C8686*
- ID_OUI_FROM_DATABASE=Technonia
+OUI:105F06*
+ ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
-OUI:4432C8*
- ID_OUI_FROM_DATABASE=Technicolor USA Inc.
+OUI:00B56D*
+ ID_OUI_FROM_DATABASE=David Electronics Co., LTD.
-OUI:78521A*
- ID_OUI_FROM_DATABASE=Samsung 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:9C541C*
- ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd
-
-OUI:90187C*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
-
-OUI:FC1F19*
- ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD.
-
OUI:E496AE*
ID_OUI_FROM_DATABASE=ALTOGRAPHICS Inc.
OUI:D40057*
ID_OUI_FROM_DATABASE=MC Technologies GmbH
-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:AC5D10*
- ID_OUI_FROM_DATABASE=Pace Americas
-
-OUI:88F490*
- ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd
-
-OUI:E8A364*
- ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio
-
-OUI:D0D6CC*
- ID_OUI_FROM_DATABASE=Wintop
-
-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:04F8C2*
- ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc.
-
-OUI:0C93FB*
- ID_OUI_FROM_DATABASE=BNS Solutions
-
-OUI:38B5BD*
- ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger
-
OUI:B85AF7*
ID_OUI_FROM_DATABASE=Ouya, Inc
OUI:F8D7BF*
ID_OUI_FROM_DATABASE=REV Ritter GmbH
-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:AC5D10*
+ ID_OUI_FROM_DATABASE=Pace Americas
-OUI:CC593E*
- ID_OUI_FROM_DATABASE=TOUMAZ LTD
+OUI:88F490*
+ ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd
OUI:AC8D14*
ID_OUI_FROM_DATABASE=Smartrove Inc
OUI:141BF0*
ID_OUI_FROM_DATABASE=Intellimedia Systems Ltd
-OUI:E45614*
- ID_OUI_FROM_DATABASE=Suttle Apparatus
+OUI:101D51*
+ ID_OUI_FROM_DATABASE=ON-Q LLC dba ON-Q Mesh Networks
-OUI:842BBC*
- ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH
+OUI:34C99D*
+ ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD.
-OUI:E856D6*
- ID_OUI_FROM_DATABASE=NCTech Ltd
+OUI:8C4AEE*
+ ID_OUI_FROM_DATABASE=GIGA TMS INC
-OUI:4088E0*
- ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch
+OUI:F46DE2*
+ ID_OUI_FROM_DATABASE=zte corporation
-OUI:1CF4CA*
- ID_OUI_FROM_DATABASE=Private
+OUI:B838CA*
+ ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD
-OUI:F490EA*
- ID_OUI_FROM_DATABASE=Deciso B.V.
+OUI:380FE4*
+ ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy
-OUI:942197*
- ID_OUI_FROM_DATABASE=Stalmart Technology Limited
+OUI:847A88*
+ ID_OUI_FROM_DATABASE=HTC Corporation
-OUI:AC9403*
- ID_OUI_FROM_DATABASE=Envision Peripherals Inc
+OUI:0808C2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
-OUI:A865B2*
- ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED
+OUI:5461EA*
+ ID_OUI_FROM_DATABASE=Zaplox AB
-OUI:60B982*
- ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A.
+OUI:78324F*
+ ID_OUI_FROM_DATABASE=Millennium Group, Inc.
-OUI:B46238*
- ID_OUI_FROM_DATABASE=Exablox
+OUI:38B5BD*
+ ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger
-OUI:40704A*
- ID_OUI_FROM_DATABASE=Power Idea Technology Limited
-
-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:547398*
- ID_OUI_FROM_DATABASE=Toyo Electronics Corporation
+OUI:841715*
+ ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd.
-OUI:4C72B9*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+OUI:087999*
+ ID_OUI_FROM_DATABASE=AIM GmbH
-OUI:E0AAB0*
- ID_OUI_FROM_DATABASE=GENERAL VISION ELECTRONICS CO. LTD.
+OUI:84C2E4*
+ ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd.
-OUI:68B43A*
- ID_OUI_FROM_DATABASE=WaterFurnace International, Inc.
+OUI:C0B8B1*
+ ID_OUI_FROM_DATABASE=BitBox Ltd
-OUI:543968*
- ID_OUI_FROM_DATABASE=Edgewater Networks Inc
+OUI:0C722C*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-OUI:C041F6*
- ID_OUI_FROM_DATABASE=LG Electronics Inc
+OUI:B01408*
+ ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO.
-OUI:985E1B*
- ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd.
+OUI:84ACA4*
+ ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd
-OUI:B8B7D7*
- ID_OUI_FROM_DATABASE=2GIG Technologies
+OUI:3C6FF7*
+ ID_OUI_FROM_DATABASE=EnTek Systems, Inc.
-OUI:1048B1*
- ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited
+OUI:48B8DE*
+ ID_OUI_FROM_DATABASE=HOMEWINS TECHNOLOGY CO.,LTD.
-OUI:005D03*
- ID_OUI_FROM_DATABASE=Xilinx, Inc
+OUI:20D5BF*
+ ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd
-OUI:24EE3A*
- ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd
+OUI:6CD032*
+ ID_OUI_FROM_DATABASE=LG Electronics
-OUI:F82285*
- ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD.
+OUI:1065CF*
+ ID_OUI_FROM_DATABASE=IQSIM
-OUI:8482F4*
- ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd
+OUI:B877C3*
+ ID_OUI_FROM_DATABASE=Decagon Devices, Inc.
-OUI:0CC47E*
- ID_OUI_FROM_DATABASE=EUCAST Co., Ltd.
+OUI:849DC5*
+ ID_OUI_FROM_DATABASE=Centera Photonics Inc.
-OUI:CCE798*
- ID_OUI_FROM_DATABASE=My Social Stuff
+OUI:580943*
+ ID_OUI_FROM_DATABASE=Private
-OUI:50724D*
- ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH
+OUI:547FA8*
+ ID_OUI_FROM_DATABASE=TELCO systems, s.r.o.
-OUI:B898B0*
- ID_OUI_FROM_DATABASE=Atlona Inc.
+OUI:5474E6*
+ ID_OUI_FROM_DATABASE=Webtech Wireless
-OUI:1C66AA*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:E8A364*
+ ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio
-OUI:2C625A*
- ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd
+OUI:D0D6CC*
+ ID_OUI_FROM_DATABASE=Wintop
-OUI:2074CF*
- ID_OUI_FROM_DATABASE=Shenzhen Voxtech Co.,Ltd
+OUI:FC1F19*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD.
-OUI:ACBD0B*
- ID_OUI_FROM_DATABASE=IMAC CO.,LTD
+OUI:9C541C*
+ ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd
-OUI:D8D27C*
- ID_OUI_FROM_DATABASE=JEMA ENERGY, SA
+OUI:90187C*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
OUI:10F3DB*
ID_OUI_FROM_DATABASE=Gridco Systems, Inc.
OUI:044A50*
ID_OUI_FROM_DATABASE=Ramaxel Technology (Shenzhen) limited company
-OUI:E42F26*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
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:70B599*
ID_OUI_FROM_DATABASE=Embedded Technologies s.r.o.
-OUI:EC4C4D*
- ID_OUI_FROM_DATABASE=ZAO NPK RoTeK
+OUI:547398*
+ ID_OUI_FROM_DATABASE=Toyo Electronics Corporation
-OUI:E8D483*
- ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH
+OUI:E0AAB0*
+ ID_OUI_FROM_DATABASE=GENERAL VISION ELECTRONICS CO. LTD.
-OUI:089E01*
- ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
+OUI:68B43A*
+ ID_OUI_FROM_DATABASE=WaterFurnace International, Inc.
-OUI:ACD9D6*
- ID_OUI_FROM_DATABASE=tci GmbH
+OUI:543968*
+ ID_OUI_FROM_DATABASE=Edgewater Networks Inc
-OUI:7493A4*
- ID_OUI_FROM_DATABASE=Zebra Technologies Corp.
+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:647657*
- ID_OUI_FROM_DATABASE=Innovative Security Designs
-
-OUI:60455E*
- ID_OUI_FROM_DATABASE=Liptel s.r.o.
+OUI:24EE3A*
+ ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd
-OUI:944A09*
- ID_OUI_FROM_DATABASE=BitWise Controls
+OUI:F82285*
+ ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD.
-OUI:E8102E*
- ID_OUI_FROM_DATABASE=Really Simple Software, Inc
+OUI:8482F4*
+ ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd
-OUI:D48CB5*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0CC47E*
+ ID_OUI_FROM_DATABASE=EUCAST Co., Ltd.
-OUI:24A43C*
- ID_OUI_FROM_DATABASE=Ubiquiti Networks, INC
+OUI:CCE798*
+ ID_OUI_FROM_DATABASE=My Social Stuff
-OUI:D41E35*
- ID_OUI_FROM_DATABASE=TOHO Electronics INC.
+OUI:50724D*
+ ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH
-OUI:700BC0*
- ID_OUI_FROM_DATABASE=Dewav Technology Company
+OUI:B898B0*
+ ID_OUI_FROM_DATABASE=Atlona Inc.
-OUI:58C38B*
+OUI:1C66AA*
ID_OUI_FROM_DATABASE=Samsung Electronics
-OUI:2CD444*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:2C625A*
+ ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd
-OUI:EC1A59*
- ID_OUI_FROM_DATABASE=Belkin International Inc.
+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:58BFEA*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:7C386C*
- ID_OUI_FROM_DATABASE=Real Time Logic
+OUI:E856D6*
+ ID_OUI_FROM_DATABASE=NCTech Ltd
-OUI:D8AF3B*
- ID_OUI_FROM_DATABASE=Hangzhou Bigbright Integrated communications system Co.,Ltd
+OUI:4088E0*
+ ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch
-OUI:78D34F*
- ID_OUI_FROM_DATABASE=Pace-O-Matic, Inc.
+OUI:1CF4CA*
+ ID_OUI_FROM_DATABASE=Private
-OUI:D857EF*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:EC4C4D*
+ ID_OUI_FROM_DATABASE=ZAO NPK RoTeK
-OUI:784405*
- ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD.
+OUI:E8D483*
+ ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH
-OUI:C03F2A*
- ID_OUI_FROM_DATABASE=Biscotti, Inc.
+OUI:089E01*
+ ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
-OUI:5001BB*
+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:F0FDA0*
- ID_OUI_FROM_DATABASE=Acurix Networks LP
+OUI:2CD444*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
-OUI:44B382*
- ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology
+OUI:EC1A59*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
-OUI:344B3D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:04F8C2*
+ ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc.
-OUI:D80DE3*
- ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS
+OUI:0C93FB*
+ ID_OUI_FROM_DATABASE=BNS Solutions
-OUI:1CE165*
- ID_OUI_FROM_DATABASE=Marshal Corporation
+OUI:E45614*
+ ID_OUI_FROM_DATABASE=Suttle Apparatus
-OUI:0CC0C0*
- ID_OUI_FROM_DATABASE=MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO
+OUI:784405*
+ ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD.
-OUI:AC40EA*
- ID_OUI_FROM_DATABASE=C&T Solution Inc.
+OUI:C03F2A*
+ ID_OUI_FROM_DATABASE=Biscotti, Inc.
-OUI:BC8B55*
- ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic
+OUI:5001BB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
-OUI:D8EB97*
- ID_OUI_FROM_DATABASE=TRENDnet, Inc.
+OUI:A40BED*
+ ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd
-OUI:202598*
- ID_OUI_FROM_DATABASE=Teleview
+OUI:0CD996*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:844915*
- ID_OUI_FROM_DATABASE=vArmour Networks, Inc.
+OUI:D82DE1*
+ ID_OUI_FROM_DATABASE=Tricascade Inc.
-OUI:A04CC1*
- ID_OUI_FROM_DATABASE=Helixtech Corp.
+OUI:C438D3*
+ ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD
-OUI:1CB243*
- ID_OUI_FROM_DATABASE=TDC A/S
+OUI:842BBC*
+ ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH
-OUI:1C51B5*
- ID_OUI_FROM_DATABASE=Techaya LTD
+OUI:B8B7D7*
+ ID_OUI_FROM_DATABASE=2GIG Technologies
-OUI:80DB31*
- ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd.
+OUI:1048B1*
+ ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited
-OUI:AC0142*
- ID_OUI_FROM_DATABASE=Uriel Technologies SIA
+OUI:005D03*
+ ID_OUI_FROM_DATABASE=Xilinx, Inc
-OUI:A007B6*
- ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc.
+OUI:20FABB*
+ ID_OUI_FROM_DATABASE=Cambridge Executive Limited
-OUI:542A9C*
- ID_OUI_FROM_DATABASE=LSY Defense, LLC.
+OUI:1C0B52*
+ ID_OUI_FROM_DATABASE=EPICOM S.A
-OUI:D487D8*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:747E2D*
+ ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD.
-OUI:F89955*
- ID_OUI_FROM_DATABASE=Fortress Technology Inc
+OUI:E80C75*
+ ID_OUI_FROM_DATABASE=Syncbak, Inc.
-OUI:B827EB*
- ID_OUI_FROM_DATABASE=Raspberry Pi Foundation
+OUI:BC8B55*
+ ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic
-OUI:E88DF5*
- ID_OUI_FROM_DATABASE=ZNYX Networks, Inc.
+OUI:D8EB97*
+ ID_OUI_FROM_DATABASE=TRENDnet, Inc.
-OUI:48EA63*
- ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd.
+OUI:202598*
+ ID_OUI_FROM_DATABASE=Teleview
-OUI:0CE5D3*
- ID_OUI_FROM_DATABASE=DH electronics GmbH
+OUI:44B382*
+ ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology
-OUI:C47130*
- ID_OUI_FROM_DATABASE=Fon Technology S.L.
+OUI:D80DE3*
+ ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS
-OUI:90CF7D*
- ID_OUI_FROM_DATABASE=Qingdao Hisense Electric Co.,Ltd.
+OUI:1CE165*
+ ID_OUI_FROM_DATABASE=Marshal Corporation
-OUI:48D7FF*
- ID_OUI_FROM_DATABASE=BLANKOM Antennentechnik GmbH
+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:6CA96F*
ID_OUI_FROM_DATABASE=TransPacket AS
-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:E42C56*
- ID_OUI_FROM_DATABASE=Lilee Systems, Ltd.
+OUI:AC0142*
+ ID_OUI_FROM_DATABASE=Uriel Technologies SIA
-OUI:50008C*
- ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited
+OUI:A007B6*
+ ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc.
-OUI:DCA8CF*
- ID_OUI_FROM_DATABASE=New Spin Golf, LLC.
+OUI:542A9C*
+ ID_OUI_FROM_DATABASE=LSY Defense, LLC.
-OUI:34BA9A*
- ID_OUI_FROM_DATABASE=Asiatelco Technologies Co.
+OUI:D487D8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
-OUI:642DB7*
- ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS
+OUI:F89955*
+ ID_OUI_FROM_DATABASE=Fortress Technology Inc
OUI:008DDA*
ID_OUI_FROM_DATABASE=Link One Co., Ltd.
OUI:882012*
ID_OUI_FROM_DATABASE=LMI Technologies
-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: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:800A06*
+ ID_OUI_FROM_DATABASE=COMTEC co.,ltd
-OUI:B8DAF7*
- ID_OUI_FROM_DATABASE=Advanced Photonics, Inc.
+OUI:B827EB*
+ ID_OUI_FROM_DATABASE=Raspberry Pi Foundation
-OUI:2C36A0*
- ID_OUI_FROM_DATABASE=Capisco Limited
+OUI:E88DF5*
+ ID_OUI_FROM_DATABASE=ZNYX Networks, Inc.
-OUI:800A06*
- ID_OUI_FROM_DATABASE=COMTEC co.,ltd
+OUI:48EA63*
+ ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd.
-OUI:20FABB*
- ID_OUI_FROM_DATABASE=Cambridge Executive Limited
+OUI:0CE5D3*
+ ID_OUI_FROM_DATABASE=DH electronics GmbH
-OUI:1C0B52*
- ID_OUI_FROM_DATABASE=EPICOM S.A
+OUI:C47130*
+ ID_OUI_FROM_DATABASE=Fon Technology S.L.
-OUI:747E2D*
- ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD.
+OUI:90CF7D*
+ ID_OUI_FROM_DATABASE=Qingdao Hisense Electric Co.,Ltd.
-OUI:E80C75*
- ID_OUI_FROM_DATABASE=Syncbak, Inc.
+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:8C604F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F490EA*
+ ID_OUI_FROM_DATABASE=Deciso B.V.
-OUI:74FF7D*
- ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC
+OUI:942197*
+ ID_OUI_FROM_DATABASE=Stalmart Technology Limited
-OUI:380A94*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:AC9403*
+ ID_OUI_FROM_DATABASE=Envision Peripherals Inc
-OUI:2CC260*
- ID_OUI_FROM_DATABASE=Ravello Systems
+OUI:A865B2*
+ ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED
-OUI:30B216*
- ID_OUI_FROM_DATABASE=Hytec Geraetebau GmbH
+OUI:60B982*
+ ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A.
-OUI:34FC6F*
- ID_OUI_FROM_DATABASE=ALCEA
+OUI:B46238*
+ ID_OUI_FROM_DATABASE=Exablox
-OUI:C0B357*
- ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd.
+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:C80718*
ID_OUI_FROM_DATABASE=TDSi
-OUI:B4944E*
- ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd.
+OUI:48ED80*
+ ID_OUI_FROM_DATABASE=daesung eltec
-OUI:345B11*
- ID_OUI_FROM_DATABASE=EVI HEAT AB
+OUI:A086EC*
+ ID_OUI_FROM_DATABASE=SAEHAN HITEC Co., Ltd
-OUI:988BAD*
- ID_OUI_FROM_DATABASE=Corintech Ltd.
+OUI:BC4B79*
+ ID_OUI_FROM_DATABASE=SensingTek
-OUI:4050E0*
- ID_OUI_FROM_DATABASE=Milton Security Group LLC
+OUI:2818FD*
+ ID_OUI_FROM_DATABASE=Aditya Infotech Ltd.
-OUI:C87CBC*
- ID_OUI_FROM_DATABASE=Valink Co., Ltd.
+OUI:9003B7*
+ ID_OUI_FROM_DATABASE=PARROT
-OUI:409FC7*
- ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd.
+OUI:844915*
+ ID_OUI_FROM_DATABASE=vArmour Networks, Inc.
-OUI:D4E33F*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
+OUI:A04CC1*
+ ID_OUI_FROM_DATABASE=Helixtech Corp.
-OUI:C87D77*
- ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd
+OUI:1CB243*
+ ID_OUI_FROM_DATABASE=TDC A/S
-OUI:A078BA*
- ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
+OUI:1C51B5*
+ ID_OUI_FROM_DATABASE=Techaya LTD
-OUI:D4507A*
- ID_OUI_FROM_DATABASE=CEIVA Logic, Inc
+OUI:80DB31*
+ ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd.
-OUI:184617*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:8C604F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:9CC7D1*
- ID_OUI_FROM_DATABASE=SHARP Corporation
+OUI:74FF7D*
+ ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC
-OUI:AC9CE4*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+OUI:380A94*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:00B9F6*
- ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd
+OUI:2CC260*
+ ID_OUI_FROM_DATABASE=Ravello Systems
-OUI:9C5C8D*
- ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA
+OUI:30B216*
+ ID_OUI_FROM_DATABASE=Hytec Geraetebau GmbH
-OUI:E01E07*
- ID_OUI_FROM_DATABASE=Anite Telecoms US. Inc
+OUI:34FC6F*
+ ID_OUI_FROM_DATABASE=ALCEA
-OUI:B06CBF*
- ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH
+OUI:C0B357*
+ ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd.
-OUI:20AA4B*
- ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
+OUI:642DB7*
+ ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS
-OUI:080D84*
- ID_OUI_FROM_DATABASE=GECO, Inc.
+OUI:A898C6*
+ ID_OUI_FROM_DATABASE=Shinbo Co., Ltd.
-OUI:88E712*
- ID_OUI_FROM_DATABASE=Whirlpool Corporation
+OUI:006BA0*
+ ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD
-OUI:644BF0*
- ID_OUI_FROM_DATABASE=CalDigit, Inc
+OUI:502690*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
-OUI:2838CF*
- ID_OUI_FROM_DATABASE=Gen2wave
+OUI:B4211D*
+ ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd
-OUI:50FC30*
- ID_OUI_FROM_DATABASE=Treehouse Labs
+OUI:E039D7*
+ ID_OUI_FROM_DATABASE=Plexxi, Inc.
-OUI:70704C*
- ID_OUI_FROM_DATABASE=Purple Communications, Inc
+OUI:FC946C*
+ ID_OUI_FROM_DATABASE=UBIVELOX
-OUI:F47ACC*
- ID_OUI_FROM_DATABASE=SolidFire, Inc.
+OUI:B4944E*
+ ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd.
-OUI:24BC82*
- ID_OUI_FROM_DATABASE=Dali Wireless, Inc.
+OUI:345B11*
+ ID_OUI_FROM_DATABASE=EVI HEAT AB
-OUI:F80CF3*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:988BAD*
+ ID_OUI_FROM_DATABASE=Corintech Ltd.
-OUI:64C5AA*
- ID_OUI_FROM_DATABASE=South African Broadcasting Corporation
+OUI:4050E0*
+ ID_OUI_FROM_DATABASE=Milton Security Group LLC
-OUI:64ED62*
- ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd
+OUI:E42C56*
+ ID_OUI_FROM_DATABASE=Lilee Systems, Ltd.
-OUI:C4237A*
- ID_OUI_FROM_DATABASE=WhizNets Inc.
+OUI:50008C*
+ ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited
-OUI:8430E5*
- ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC
+OUI:DCA8CF*
+ ID_OUI_FROM_DATABASE=New Spin Golf, LLC.
-OUI:2C002C*
- ID_OUI_FROM_DATABASE=UNOWHY
+OUI:34BA9A*
+ ID_OUI_FROM_DATABASE=Asiatelco Technologies Co.
-OUI:0481AE*
- ID_OUI_FROM_DATABASE=Clack Corporation
+OUI:D443A8*
+ ID_OUI_FROM_DATABASE=Changzhou Haojie Electric Co., Ltd.
-OUI:C09132*
- ID_OUI_FROM_DATABASE=Patriot Memory
+OUI:BCB852*
+ ID_OUI_FROM_DATABASE=Cybera, Inc.
-OUI:A898C6*
- ID_OUI_FROM_DATABASE=Shinbo Co., Ltd.
+OUI:70D6B6*
+ ID_OUI_FROM_DATABASE=Metrum Technologies
-OUI:006BA0*
- ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD
+OUI:28D576*
+ ID_OUI_FROM_DATABASE=Premier Wireless, Inc.
-OUI:502690*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:C87CBC*
+ ID_OUI_FROM_DATABASE=Valink Co., Ltd.
-OUI:B4211D*
- ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd
+OUI:409FC7*
+ ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd.
-OUI:E039D7*
- ID_OUI_FROM_DATABASE=Plexxi, Inc.
+OUI:C87D77*
+ ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd
-OUI:FC946C*
- ID_OUI_FROM_DATABASE=UBIVELOX
+OUI:A078BA*
+ ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
-OUI:38DE60*
- ID_OUI_FROM_DATABASE=Mohlenhoff GmbH
+OUI:20BBC6*
+ ID_OUI_FROM_DATABASE=Jabil Circuit Hungary Ltd.
-OUI:2839E7*
- ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd.
+OUI:2C9717*
+ ID_OUI_FROM_DATABASE=I.C.Y. B.V.
-OUI:28D997*
- ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd.
+OUI:64E84F*
+ ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd
-OUI:886B76*
- ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD
+OUI:6CE907*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:A0CF5B*
+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:18C451*
- ID_OUI_FROM_DATABASE=Tucson Embedded Systems
+OUI:5CEB4E*
+ ID_OUI_FROM_DATABASE=R. STAHL HMI Systems GmbH
-OUI:582EFE*
- ID_OUI_FROM_DATABASE=Lighting Science Group
+OUI:B8DAF7*
+ ID_OUI_FROM_DATABASE=Advanced Photonics, Inc.
-OUI:D826B9*
- ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S &T Co., Ltd.
+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:50F61A*
ID_OUI_FROM_DATABASE=Kunshan JADE Technologies 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:941D1C*
ID_OUI_FROM_DATABASE=TLab West Systems AB
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:807693*
ID_OUI_FROM_DATABASE=Newag SA
-OUI:FC1794*
- ID_OUI_FROM_DATABASE=InterCreative Co., Ltd
+OUI:2C002C*
+ ID_OUI_FROM_DATABASE=UNOWHY
-OUI:181420*
- ID_OUI_FROM_DATABASE=TEB SAS
+OUI:0481AE*
+ ID_OUI_FROM_DATABASE=Clack Corporation
-OUI:D03110*
- ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd
+OUI:C09132*
+ ID_OUI_FROM_DATABASE=Patriot Memory
OUI:AC81F3*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:1071F9*
ID_OUI_FROM_DATABASE=Cloud Telecomputers, LLC
-OUI:C47B2F*
- ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd.
-
-OUI:18F650*
- ID_OUI_FROM_DATABASE=Multimedia Pacific Limited
+OUI:B8B42E*
+ ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen
-OUI:704AAE*
- ID_OUI_FROM_DATABASE=Xstream Flow (Pty) Ltd
+OUI:A84041*
+ ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited
-OUI:9C934E*
- ID_OUI_FROM_DATABASE=Xerox Corporation
+OUI:DCF05D*
+ ID_OUI_FROM_DATABASE=Letta Teknoloji
-OUI:3C26D5*
- ID_OUI_FROM_DATABASE=Sotera Wireless
+OUI:D05A0F*
+ ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD
OUI:FC2E2D*
ID_OUI_FROM_DATABASE=Lorom Industrial Co.LTD.
OUI:70B921*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-OUI:948FEE*
- ID_OUI_FROM_DATABASE=Hughes Telematics, Inc.
-
-OUI:E8C320*
- ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
+OUI:C47B2F*
+ ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd.
-OUI:D8973B*
- ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
+OUI:18F650*
+ ID_OUI_FROM_DATABASE=Multimedia Pacific Limited
-OUI:008D4E*
- ID_OUI_FROM_DATABASE=CJSC NII STT
+OUI:38DE60*
+ ID_OUI_FROM_DATABASE=Mohlenhoff GmbH
-OUI:10C586*
- ID_OUI_FROM_DATABASE=BIO SOUND LAB CO., LTD.
+OUI:2839E7*
+ ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd.
-OUI:E8BA70*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:28D997*
+ ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd.
-OUI:6473E2*
- ID_OUI_FROM_DATABASE=Arbiter Systems, Inc.
+OUI:886B76*
+ ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD
-OUI:00A1DE*
- ID_OUI_FROM_DATABASE=ShenZhen ShiHua Technology CO.,LTD
+OUI:A0CF5B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:04E1C8*
- ID_OUI_FROM_DATABASE=IMS Soluções em Energia Ltda.
+OUI:18C451*
+ ID_OUI_FROM_DATABASE=Tucson Embedded Systems
-OUI:E4DD79*
- ID_OUI_FROM_DATABASE=En-Vision America, Inc.
+OUI:582EFE*
+ ID_OUI_FROM_DATABASE=Lighting Science Group
-OUI:60190C*
- ID_OUI_FROM_DATABASE=RRAMAC
+OUI:D4507A*
+ ID_OUI_FROM_DATABASE=CEIVA Logic, Inc
-OUI:34A709*
- ID_OUI_FROM_DATABASE=Trevil srl
+OUI:184617*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
-OUI:F80332*
- ID_OUI_FROM_DATABASE=Khomp
+OUI:9CC7D1*
+ ID_OUI_FROM_DATABASE=SHARP Corporation
-OUI:C40F09*
- ID_OUI_FROM_DATABASE=Hermes electronic GmbH
+OUI:AC9CE4*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
-OUI:908D1D*
- ID_OUI_FROM_DATABASE=GH Technologies
+OUI:00B9F6*
+ ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd
-OUI:CCB55A*
- ID_OUI_FROM_DATABASE=Fraunhofer ITWM
+OUI:9C5C8D*
+ ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA
-OUI:587521*
- ID_OUI_FROM_DATABASE=CJSC RTSoft
+OUI:E01E07*
+ ID_OUI_FROM_DATABASE=Anite Telecoms US. Inc
OUI:64D989*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
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:FCE892*
ID_OUI_FROM_DATABASE=Hangzhou Lancable Technology Co.,Ltd
-OUI:B8B42E*
- ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen
+OUI:FC1794*
+ ID_OUI_FROM_DATABASE=InterCreative Co., Ltd
-OUI:A84041*
- ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited
+OUI:181420*
+ ID_OUI_FROM_DATABASE=TEB SAS
-OUI:686E23*
- ID_OUI_FROM_DATABASE=Wi3 Inc.
+OUI:D03110*
+ ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd
-OUI:DCF05D*
- ID_OUI_FROM_DATABASE=Letta Teknoloji
+OUI:48C862*
+ ID_OUI_FROM_DATABASE=Simo Wireless,Inc.
-OUI:D05A0F*
- ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD
+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:900D66*
ID_OUI_FROM_DATABASE=Digimore Electronics Co., Ltd
-OUI:980C82*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
-
-OUI:48C862*
- ID_OUI_FROM_DATABASE=Simo Wireless,Inc.
-
-OUI:0CF3EE*
- ID_OUI_FROM_DATABASE=EM Microelectronic
-
-OUI:F0C27C*
- ID_OUI_FROM_DATABASE=Mianyang Netop Telecom Equipment Co.,Ltd.
-
OUI:BC35E5*
ID_OUI_FROM_DATABASE=Hydro Systems Company
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:50FAAB*
ID_OUI_FROM_DATABASE=L-tek d.o.o.
-OUI:547F54*
- ID_OUI_FROM_DATABASE=INGENICO
-
OUI:A8E018*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:A8FCB7*
ID_OUI_FROM_DATABASE=Consolidated Resource Imaging
-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:6400F1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:CCF67A*
- ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
+OUI:04C5A4*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:200A5E*
- ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing co.,LTD
+OUI:E4DD79*
+ ID_OUI_FROM_DATABASE=En-Vision America, Inc.
-OUI:747818*
- ID_OUI_FROM_DATABASE=ServiceAssure
+OUI:60190C*
+ ID_OUI_FROM_DATABASE=RRAMAC
-OUI:00BB8E*
- ID_OUI_FROM_DATABASE=HME Co., Ltd.
+OUI:34A709*
+ ID_OUI_FROM_DATABASE=Trevil srl
-OUI:C0A26D*
- ID_OUI_FROM_DATABASE=Abbott Point of Care
+OUI:F80332*
+ ID_OUI_FROM_DATABASE=Khomp
-OUI:205B2A*
- ID_OUI_FROM_DATABASE=Private
+OUI:C40F09*
+ ID_OUI_FROM_DATABASE=Hermes electronic GmbH
-OUI:18B430*
- ID_OUI_FROM_DATABASE=Nest Labs Inc.
+OUI:908D1D*
+ ID_OUI_FROM_DATABASE=GH Technologies
-OUI:F8769B*
- ID_OUI_FROM_DATABASE=Neopis Co., Ltd.
+OUI:CCB55A*
+ ID_OUI_FROM_DATABASE=Fraunhofer ITWM
-OUI:08E672*
- ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD.
+OUI:587521*
+ ID_OUI_FROM_DATABASE=CJSC RTSoft
-OUI:C89CDC*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
+OUI:948FEE*
+ ID_OUI_FROM_DATABASE=Hughes Telematics, Inc.
-OUI:58E476*
- ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD
+OUI:E8C320*
+ ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
-OUI:B435F7*
- ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd.
+OUI:D8973B*
+ ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
OUI:0C6E4F*
ID_OUI_FROM_DATABASE=PrimeVOLT Co., Ltd.
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: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: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:BC99BC*
- ID_OUI_FROM_DATABASE=FonSee Technology Inc.
+OUI:58E476*
+ ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD
-OUI:986022*
- ID_OUI_FROM_DATABASE=EMW Co., Ltd.
+OUI:B435F7*
+ ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd.
-OUI:80B32A*
- ID_OUI_FROM_DATABASE=Alstom Grid
+OUI:346F92*
+ ID_OUI_FROM_DATABASE=White Rodgers Division
-OUI:803457*
- ID_OUI_FROM_DATABASE=OT Systems Limited
+OUI:8CDB25*
+ ID_OUI_FROM_DATABASE=ESG Solutions
-OUI:B83D4E*
- ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch
+OUI:641A22*
+ ID_OUI_FROM_DATABASE=Heliospectra AB
-OUI:CCF3A5*
- ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc
+OUI:BC20BA*
+ ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd
-OUI:143E60*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
+OUI:249442*
+ ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
-OUI:C4242E*
- ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc
-
-OUI:6400F1*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:04C5A4*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:E0F379*
+ ID_OUI_FROM_DATABASE=Vaddio
-OUI:3CA72B*
- ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
+OUI:B09AE2*
+ ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH
-OUI:EC55F9*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:E441E6*
+ ID_OUI_FROM_DATABASE=Ottec Technology GmbH
-OUI:F4D9FB*
- ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
+OUI:10E2D5*
+ ID_OUI_FROM_DATABASE=Qi Hardware Inc.
-OUI:584C19*
- ID_OUI_FROM_DATABASE=Chongqing Guohong Technology Development Company Limited
+OUI:7CDA84*
+ ID_OUI_FROM_DATABASE=Dongnian Networks Inc.
-OUI:D0A311*
- ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH
+OUI:A036FA*
+ ID_OUI_FROM_DATABASE=Ettus Research LLC
-OUI:3C5A37*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:EC836C*
+ ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
-OUI:10A13B*
- ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
+OUI:BC71C1*
+ ID_OUI_FROM_DATABASE=XTrillion, Inc.
-OUI:F4E142*
- ID_OUI_FROM_DATABASE=Delta Elektronika BV
+OUI:0C469D*
+ ID_OUI_FROM_DATABASE=MS Sedco
-OUI:F00248*
- ID_OUI_FROM_DATABASE=SmarteBuilding
+OUI:E0E8E8*
+ ID_OUI_FROM_DATABASE=Olive Telecommunication Pvt. Ltd
-OUI:2CDD0C*
- ID_OUI_FROM_DATABASE=Discovergy GmbH
+OUI:0C3C65*
+ ID_OUI_FROM_DATABASE=Dome Imaging Inc
OUI:40B2C8*
ID_OUI_FROM_DATABASE=Nortel Networks
OUI:D491AF*
ID_OUI_FROM_DATABASE=Electroacustica General Iberica, S.A.
-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: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: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:30142D*
- ID_OUI_FROM_DATABASE=Piciorgros GmbH
-
-OUI:E441E6*
- ID_OUI_FROM_DATABASE=Ottec Technology GmbH
-
-OUI:10E2D5*
- ID_OUI_FROM_DATABASE=Qi Hardware Inc.
+OUI:CCF67A*
+ ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
-OUI:7CDA84*
- ID_OUI_FROM_DATABASE=Dongnian Networks Inc.
+OUI:00BB8E*
+ ID_OUI_FROM_DATABASE=HME Co., Ltd.
-OUI:A036FA*
- ID_OUI_FROM_DATABASE=Ettus Research LLC
+OUI:C0A26D*
+ ID_OUI_FROM_DATABASE=Abbott Point of Care
-OUI:EC836C*
- ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
+OUI:205B2A*
+ ID_OUI_FROM_DATABASE=Private
-OUI:C0C520*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:18B430*
+ ID_OUI_FROM_DATABASE=Nest Labs Inc.
-OUI:6083B2*
- ID_OUI_FROM_DATABASE=GkWare e.K.
+OUI:F8769B*
+ ID_OUI_FROM_DATABASE=Neopis Co., Ltd.
-OUI:80D019*
- ID_OUI_FROM_DATABASE=Embed, Inc
+OUI:08E672*
+ ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD.
OUI:D41296*
ID_OUI_FROM_DATABASE=Anobit Technologies Ltd.
OUI:0475F5*
ID_OUI_FROM_DATABASE=CSST
-OUI:BC20BA*
- ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd
+OUI:10A13B*
+ ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
-OUI:249442*
- ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
+OUI:F4E142*
+ ID_OUI_FROM_DATABASE=Delta Elektronika BV
-OUI:E0F379*
- ID_OUI_FROM_DATABASE=Vaddio
+OUI:F00248*
+ ID_OUI_FROM_DATABASE=SmarteBuilding
-OUI:B09AE2*
- ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH
+OUI:2CDD0C*
+ ID_OUI_FROM_DATABASE=Discovergy GmbH
OUI:CCD811*
ID_OUI_FROM_DATABASE=Aiconn Technology Corporation
OUI:3C2F3A*
ID_OUI_FROM_DATABASE=SFORZATO Corp.
-OUI:EC9233*
- ID_OUI_FROM_DATABASE=Eddyfi NDT Inc
+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:08B7EC*
ID_OUI_FROM_DATABASE=Wireless Seismic
-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:30142D*
+ ID_OUI_FROM_DATABASE=Piciorgros GmbH
OUI:942053*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:5CF3FC*
ID_OUI_FROM_DATABASE=IBM Corp
-OUI:D43D67*
- ID_OUI_FROM_DATABASE=Carma Industries Inc.
-
-OUI:00BD27*
- ID_OUI_FROM_DATABASE=Exar Corp.
+OUI:D01CBB*
+ ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd.
-OUI:C8A729*
- ID_OUI_FROM_DATABASE=SYStronics Co., Ltd.
+OUI:9481A4*
+ ID_OUI_FROM_DATABASE=Azuray Technologies
-OUI:6C9CE9*
- ID_OUI_FROM_DATABASE=Nimble Storage
+OUI:BCE09D*
+ ID_OUI_FROM_DATABASE=Eoslink
-OUI:700258*
- ID_OUI_FROM_DATABASE=01DB-METRAVIB
+OUI:D0A311*
+ ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH
-OUI:D4E8B2*
+OUI:3C5A37*
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: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: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:785712*
+ ID_OUI_FROM_DATABASE=Mobile Integration Workgroup
-OUI:44ED57*
- ID_OUI_FROM_DATABASE=Longicorn, inc.
+OUI:380A0A*
+ ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company
OUI:38521A*
ID_OUI_FROM_DATABASE=Alcatel-Lucent 7705
OUI:88ACC1*
ID_OUI_FROM_DATABASE=Generiton Co., Ltd.
-OUI:785712*
- ID_OUI_FROM_DATABASE=Mobile Integration Workgroup
+OUI:700258*
+ ID_OUI_FROM_DATABASE=01DB-METRAVIB
-OUI:380A0A*
- ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company
+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:98FC11*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-OUI:180C77*
- ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC
-
-OUI:ACA016*
+OUI:A40CC3*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:78E400*
+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:E4AD7D*
- ID_OUI_FROM_DATABASE=SCL Elements
+OUI:543131*
+ ID_OUI_FROM_DATABASE=Raster Vision Ltd
-OUI:40D40E*
- ID_OUI_FROM_DATABASE=Biodata Ltd
+OUI:90E0F0*
+ ID_OUI_FROM_DATABASE=IEEE 1722a Working Group
-OUI:7C051E*
- ID_OUI_FROM_DATABASE=RAFAEL LTD.
+OUI:1C6F65*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
-OUI:58570D*
- ID_OUI_FROM_DATABASE=Danfoss Solar Inverters
+OUI:F0AD4E*
+ ID_OUI_FROM_DATABASE=Globalscale Technologies, Inc.
-OUI:E47CF9*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD
+OUI:903D5A*
+ ID_OUI_FROM_DATABASE=Shenzhen Wision Technology Holding Limited
-OUI:0C826A*
- ID_OUI_FROM_DATABASE=Wuhan Huagong Genuine Optics Technology Co., Ltd
+OUI:609AA4*
+ ID_OUI_FROM_DATABASE=GVI SECURITY INC.
-OUI:5C0E8B*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:F0ED1E*
+ ID_OUI_FROM_DATABASE=Bilkon Bilgisayar Kontrollu Cih. Im.Ltd.
-OUI:38C7BA*
- ID_OUI_FROM_DATABASE=CS Services Co.,Ltd.
+OUI:206A8A*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd.
-OUI:70D57E*
- ID_OUI_FROM_DATABASE=Scalar Corporation
+OUI:F80F41*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan) Corporation
-OUI:7866AE*
- ID_OUI_FROM_DATABASE=ZTEC Instruments, Inc.
+OUI:1CDF0F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:24AF4A*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD
+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:84F64C*
ID_OUI_FROM_DATABASE=Cross Point BV
-OUI:206A8A*
- ID_OUI_FROM_DATABASE=Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd.
-
-OUI:F80F41*
- ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan) Corporation
-
-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:180C77*
+ ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC
-OUI:A40CC3*
+OUI:ACA016*
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*
+OUI:78E400*
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: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: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:905446*
ID_OUI_FROM_DATABASE=TES ELECTRONIC SOLUTIONS
OUI:E06290*
ID_OUI_FROM_DATABASE=Jinan Jovision Science & Technology Co., Ltd.
-OUI:A01859*
- ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd
+OUI:68DB96*
+ ID_OUI_FROM_DATABASE=OPWILL Technologies CO .,LTD
-OUI:042234*
- ID_OUI_FROM_DATABASE=Wireless Standard Extensions
+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: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:A8995C*
ID_OUI_FROM_DATABASE=aizo ag
-OUI:F445ED*
- ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd.
+OUI:4012E4*
+ ID_OUI_FROM_DATABASE=Compass-EOS
-OUI:6C32DE*
- ID_OUI_FROM_DATABASE=Indieon Technologies Pvt. Ltd.
+OUI:F8DC7A*
+ ID_OUI_FROM_DATABASE=Variscite LTD
-OUI:FCCF62*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:EC4476*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:D8E72B*
- ID_OUI_FROM_DATABASE=NetScout 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:30EFD1*
ID_OUI_FROM_DATABASE=Alstom Strongwish (Shenzhen) Co., Ltd.
-OUI:C835B8*
- ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K
+OUI:7C2CF3*
+ ID_OUI_FROM_DATABASE=Secure Electrans Ltd
-OUI:243C20*
- ID_OUI_FROM_DATABASE=Dynamode Group
+OUI:304174*
+ ID_OUI_FROM_DATABASE=ALTEC LANSING LLC
-OUI:70D5E7*
- ID_OUI_FROM_DATABASE=Wellcore Corporation
+OUI:7830E1*
+ ID_OUI_FROM_DATABASE=UltraClenz, LLC
-OUI:3CF72A*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:FCFBFB*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:FCE192*
- ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd
+OUI:1C129D*
+ ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB
-OUI:F8912A*
- ID_OUI_FROM_DATABASE=GLP German Light Products GmbH
+OUI:B40832*
+ ID_OUI_FROM_DATABASE=TC Communications
-OUI:E02630*
- ID_OUI_FROM_DATABASE=Intrigue Technologies, Inc.
-
-OUI:8C9236*
- ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd.
-
-OUI:4012E4*
- ID_OUI_FROM_DATABASE=Compass-EOS
+OUI:B42CBE*
+ ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited
-OUI:F8DC7A*
- ID_OUI_FROM_DATABASE=Variscite LTD
+OUI:F47626*
+ ID_OUI_FROM_DATABASE=Viltechmeda UAB
OUI:003A9C*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:2C3427*
ID_OUI_FROM_DATABASE=ERCO & GENER
-OUI:B42CBE*
- ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited
+OUI:389F83*
+ ID_OUI_FROM_DATABASE=OTN Systems N.V.
-OUI:F47626*
- ID_OUI_FROM_DATABASE=Viltechmeda UAB
+OUI:8C541D*
+ ID_OUI_FROM_DATABASE=LGE
-OUI:EC4476*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:601283*
+ ID_OUI_FROM_DATABASE=Soluciones Tecnologicas para la Salud y el Bienestar SA
-OUI:9CEBE8*
- ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd
+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:889821*
ID_OUI_FROM_DATABASE=TERAON
-OUI:CC5076*
- ID_OUI_FROM_DATABASE=Ocom Communications, Inc.
+OUI:0026FD*
+ ID_OUI_FROM_DATABASE=Interactive Intelligence
-OUI:705812*
- ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
+OUI:0026F6*
+ ID_OUI_FROM_DATABASE=Military Communication Institute
-OUI:7C2CF3*
- ID_OUI_FROM_DATABASE=Secure Electrans Ltd
+OUI:0026F0*
+ ID_OUI_FROM_DATABASE=cTrixs International GmbH.
-OUI:304174*
- ID_OUI_FROM_DATABASE=ALTEC LANSING LLC
+OUI:0026EA*
+ ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd.
-OUI:7830E1*
- ID_OUI_FROM_DATABASE=UltraClenz, LLC
+OUI:0026E3*
+ ID_OUI_FROM_DATABASE=DTI
-OUI:FCFBFB*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0026DD*
+ ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd.
-OUI:1C129D*
- ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB
+OUI:0026DE*
+ ID_OUI_FROM_DATABASE=FDI MATELEC
-OUI:B40832*
- ID_OUI_FROM_DATABASE=TC Communications
+OUI:0026D7*
+ ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd.
-OUI:002720*
- ID_OUI_FROM_DATABASE=NEW-SOL COM
+OUI:0026D1*
+ ID_OUI_FROM_DATABASE=S Squared Innovations Inc.
-OUI:00271C*
- ID_OUI_FROM_DATABASE=MERCURY CORPORATION
+OUI:54B620*
+ ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd.
-OUI:002712*
- ID_OUI_FROM_DATABASE=MaxVision LLC
+OUI:C4AAA1*
+ ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o.
-OUI:00270F*
- ID_OUI_FROM_DATABASE=Envisionnovation Inc
+OUI:78C40E*
+ ID_OUI_FROM_DATABASE=H&D Wireless
-OUI:0026D7*
- ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd.
+OUI:9C5B96*
+ ID_OUI_FROM_DATABASE=NMR Corporation
-OUI:0026D1*
- ID_OUI_FROM_DATABASE=S Squared Innovations Inc.
+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:0026A7*
ID_OUI_FROM_DATABASE=CONNECT SRL
-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: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:60391F*
ID_OUI_FROM_DATABASE=ABB Ltd
OUI:586ED6*
ID_OUI_FROM_DATABASE=Private
-OUI:E09153*
- ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+OUI:CC5076*
+ ID_OUI_FROM_DATABASE=Ocom Communications, Inc.
-OUI:CC0080*
- ID_OUI_FROM_DATABASE=BETTINI SRL
+OUI:705812*
+ ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
-OUI:644BC3*
- ID_OUI_FROM_DATABASE=Shanghai WOASiS Telecommunications Ltd., Co.
+OUI:002648*
+ ID_OUI_FROM_DATABASE=Emitech Corp.
-OUI:0CE709*
- ID_OUI_FROM_DATABASE=Fox Crypto B.V.
+OUI:002644*
+ ID_OUI_FROM_DATABASE=Thomson Telecom Belgium
-OUI:002703*
- ID_OUI_FROM_DATABASE=Testech Electronics Pte Ltd
+OUI:00263E*
+ ID_OUI_FROM_DATABASE=Trapeze Networks
-OUI:0026FD*
- ID_OUI_FROM_DATABASE=Interactive Intelligence
+OUI:002638*
+ ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd.
-OUI:0026F6*
- ID_OUI_FROM_DATABASE=Military Communication Institute
+OUI:00263D*
+ ID_OUI_FROM_DATABASE=MIA Corporation
-OUI:0026F0*
- ID_OUI_FROM_DATABASE=cTrixs International GmbH.
+OUI:002631*
+ ID_OUI_FROM_DATABASE=COMMTACT LTD
-OUI:0026EA*
- ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd.
+OUI:00262B*
+ ID_OUI_FROM_DATABASE=Wongs Electronics Co. Ltd.
-OUI:0026E3*
- ID_OUI_FROM_DATABASE=DTI
+OUI:002625*
+ ID_OUI_FROM_DATABASE=MediaSputnik
-OUI:0026DD*
- ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd.
+OUI:00261E*
+ ID_OUI_FROM_DATABASE=QINGBANG ELEC(SZ) CO., LTD
-OUI:0026DE*
- ID_OUI_FROM_DATABASE=FDI MATELEC
+OUI:002619*
+ ID_OUI_FROM_DATABASE=FRC
-OUI:7825AD*
- ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD.
+OUI:0025BA*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD
-OUI:54B620*
- ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd.
+OUI:0025B5*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:C4AAA1*
- ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o.
+OUI:0025AE*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
-OUI:78C40E*
- ID_OUI_FROM_DATABASE=H&D Wireless
+OUI:0025A8*
+ ID_OUI_FROM_DATABASE=Kontron (BeiJing) Technology Co.,Ltd
-OUI:9C5B96*
- ID_OUI_FROM_DATABASE=NMR Corporation
+OUI:0025A7*
+ ID_OUI_FROM_DATABASE=Comverge, Inc.
-OUI:E4FFDD*
- ID_OUI_FROM_DATABASE=ELECTRON INDIA
+OUI:0025A2*
+ ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L.
-OUI:F852DF*
- ID_OUI_FROM_DATABASE=VNL Europe AB
+OUI:002596*
+ ID_OUI_FROM_DATABASE=GIGAVISION srl
-OUI:1CF061*
- ID_OUI_FROM_DATABASE=SCAPS GmbH
+OUI:00259B*
+ ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd
-OUI:A893E6*
- ID_OUI_FROM_DATABASE=JIANGXI JINGGANGSHAN CKING COMMUNICATION 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: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:0025C1*
ID_OUI_FROM_DATABASE=Nawoo Korea Corp.
-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: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:002612*
ID_OUI_FROM_DATABASE=Space Exploration Technologies
OUI:0025F9*
ID_OUI_FROM_DATABASE=GMK electronic design GmbH
-OUI:0025A2*
- ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L.
+OUI:0025F5*
+ ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd
-OUI:002596*
- ID_OUI_FROM_DATABASE=GIGAVISION srl
+OUI:0025F0*
+ ID_OUI_FROM_DATABASE=Suga Electronics Limited
-OUI:00259B*
- ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd
+OUI:0025EA*
+ ID_OUI_FROM_DATABASE=Iphion BV
-OUI:002595*
- ID_OUI_FROM_DATABASE=Northwest Signal Supply, Inc
+OUI:0025E4*
+ ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC
OUI:00258F*
ID_OUI_FROM_DATABASE=Trident Microsystems, Inc.
OUI:002574*
ID_OUI_FROM_DATABASE=KUNIMI MEDIA DEVICE Co., Ltd.
-OUI:00264F*
- ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH
+OUI:00256F*
+ ID_OUI_FROM_DATABASE=Dantherm Power
-OUI:002648*
- ID_OUI_FROM_DATABASE=Emitech Corp.
+OUI:002562*
+ ID_OUI_FROM_DATABASE=interbro Co. Ltd.
-OUI:002644*
- ID_OUI_FROM_DATABASE=Thomson Telecom Belgium
+OUI:002561*
+ ID_OUI_FROM_DATABASE=ProCurve Networking by HP
-OUI:00263E*
- ID_OUI_FROM_DATABASE=Trapeze Networks
+OUI:0023F7*
+ ID_OUI_FROM_DATABASE=Private
-OUI:002638*
- ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd.
+OUI:0023FD*
+ ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH
-OUI:00263D*
- ID_OUI_FROM_DATABASE=MIA Corporation
+OUI:0023F6*
+ ID_OUI_FROM_DATABASE=Softwell Technology Co., Ltd.
-OUI:002631*
- ID_OUI_FROM_DATABASE=COMMTACT LTD
+OUI:0023EC*
+ ID_OUI_FROM_DATABASE=Algorithmix GmbH
-OUI:00256F*
- ID_OUI_FROM_DATABASE=Dantherm Power
+OUI:0023E7*
+ ID_OUI_FROM_DATABASE=Hinke A/S
-OUI:002562*
- ID_OUI_FROM_DATABASE=interbro Co. Ltd.
+OUI:0023E0*
+ ID_OUI_FROM_DATABASE=INO Therapeutics LLC
-OUI:002561*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:0024C2*
+ ID_OUI_FROM_DATABASE=Asumo Co.,Ltd.
-OUI:00255C*
- ID_OUI_FROM_DATABASE=NEC Corporation
+OUI:0024BC*
+ ID_OUI_FROM_DATABASE=HuRob Co.,Ltd
-OUI:002550*
- ID_OUI_FROM_DATABASE=Riverbed Technology
+OUI:0024B7*
+ ID_OUI_FROM_DATABASE=GridPoint, Inc.
-OUI:002555*
- ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd
+OUI:0024AB*
+ ID_OUI_FROM_DATABASE=A7 Engineering, Inc.
-OUI:00254F*
- ID_OUI_FROM_DATABASE=ELETTROLAB Srl
+OUI:0024A6*
+ ID_OUI_FROM_DATABASE=TELESTAR DIGITAL GmbH
-OUI:002518*
- ID_OUI_FROM_DATABASE=Power PLUS Communications AG
+OUI:00249A*
+ ID_OUI_FROM_DATABASE=Beijing Zhongchuang Telecommunication Test Co., Ltd.
-OUI:002511*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
+OUI:00249F*
+ ID_OUI_FROM_DATABASE=RIM Testing Services
-OUI:002513*
- ID_OUI_FROM_DATABASE=CXP DIGITAL BV
+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:0024F2*
ID_OUI_FROM_DATABASE=Uniphone Telecommunication Co., Ltd.
-OUI:0024F4*
- ID_OUI_FROM_DATABASE=Kaminario Technologies Ltd.
-
OUI:0024ED*
ID_OUI_FROM_DATABASE=YT Elec. Co,.Ltd.
OUI:0024DA*
ID_OUI_FROM_DATABASE=Innovar Systems Limited
-OUI:002549*
- ID_OUI_FROM_DATABASE=Jeorich Tech. Co.,Ltd.
-
-OUI:002538*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division
-
-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:0025F5*
- ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd
-
-OUI:0025F0*
- ID_OUI_FROM_DATABASE=Suga Electronics Limited
+OUI:0024CE*
+ ID_OUI_FROM_DATABASE=Exeltech Inc
-OUI:0025EA*
- ID_OUI_FROM_DATABASE=Iphion BV
+OUI:0024D3*
+ ID_OUI_FROM_DATABASE=QUALICA Inc.
-OUI:0025E4*
- ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC
+OUI:0024C7*
+ ID_OUI_FROM_DATABASE=Mobilarm Ltd
-OUI:0025E0*
- ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd
+OUI:002429*
+ ID_OUI_FROM_DATABASE=MK MASTER INC.
-OUI:0025DA*
- ID_OUI_FROM_DATABASE=Secura Key
+OUI:00241C*
+ ID_OUI_FROM_DATABASE=FuGang Electronic (DG) Co.,Ltd
-OUI:0025D9*
- ID_OUI_FROM_DATABASE=DataFab Systems Inc.
+OUI:002428*
+ ID_OUI_FROM_DATABASE=EnergyICT
-OUI:0025D4*
- ID_OUI_FROM_DATABASE=Fortress Technologies
+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: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:002387*
- ID_OUI_FROM_DATABASE=ThinkFlood, Inc.
-
-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:0024CE*
- ID_OUI_FROM_DATABASE=Exeltech Inc
-
-OUI:0024D3*
- ID_OUI_FROM_DATABASE=QUALICA Inc.
-
-OUI:0024C7*
- ID_OUI_FROM_DATABASE=Mobilarm Ltd
-
-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:002487*
ID_OUI_FROM_DATABASE=Blackboard Inc.
OUI:002480*
ID_OUI_FROM_DATABASE=Meteocontrol GmbH
-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: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:002479*
- ID_OUI_FROM_DATABASE=Optec Displays, Inc.
-
-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:002432*
+ ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD
-OUI:002466*
- ID_OUI_FROM_DATABASE=Unitron nv
+OUI:0023DA*
+ ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH
-OUI:002461*
- ID_OUI_FROM_DATABASE=Shin Wang Tech.
+OUI:0023C8*
+ ID_OUI_FROM_DATABASE=TEAM-R
-OUI:00245C*
- ID_OUI_FROM_DATABASE=Design-Com Technologies Pty. Ltd.
+OUI:0023C7*
+ ID_OUI_FROM_DATABASE=AVSystem
-OUI:00244F*
- ID_OUI_FROM_DATABASE=Asantron Technologies Ltd.
+OUI:0023C1*
+ ID_OUI_FROM_DATABASE=Securitas Direct AB
OUI:0023BB*
ID_OUI_FROM_DATABASE=Schmitt Industries
OUI:0023B5*
ID_OUI_FROM_DATABASE=ORTANA LTD
-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:002432*
- ID_OUI_FROM_DATABASE=Neostar Technology Co.,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:002381*
+ ID_OUI_FROM_DATABASE=Lengda Technology(Xiamen) Co.,Ltd.
-OUI:0023E0*
- ID_OUI_FROM_DATABASE=INO Therapeutics LLC
+OUI:002382*
+ ID_OUI_FROM_DATABASE=Lih Rong Electronic Enterprise Co., Ltd.
-OUI:0023DA*
- ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH
+OUI:00237B*
+ ID_OUI_FROM_DATABASE=WHDI LLC
-OUI:0023C8*
- ID_OUI_FROM_DATABASE=TEAM-R
+OUI:002372*
+ ID_OUI_FROM_DATABASE=MORE STAR INDUSTRIAL GROUP LIMITED
-OUI:0023C7*
- ID_OUI_FROM_DATABASE=AVSystem
+OUI:002366*
+ ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd.
-OUI:0023C1*
- ID_OUI_FROM_DATABASE=Securitas Direct AB
+OUI:00236B*
+ ID_OUI_FROM_DATABASE=Xembedded, Inc.
-OUI:0021DC*
- ID_OUI_FROM_DATABASE=TECNOALARM S.r.l.
+OUI:002359*
+ ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited
-OUI:0021E2*
- ID_OUI_FROM_DATABASE=Creative Electronic GmbH
+OUI:00235F*
+ ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH
-OUI:0021D6*
- ID_OUI_FROM_DATABASE=LXI Consortium
+OUI:002353*
+ ID_OUI_FROM_DATABASE=F E T Elettronica snc
-OUI:0021CF*
- ID_OUI_FROM_DATABASE=The Crypto Group
+OUI:002347*
+ ID_OUI_FROM_DATABASE=ProCurve Networking by HP
-OUI:0021C9*
- ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited
+OUI:00234C*
+ ID_OUI_FROM_DATABASE=KTC AB
-OUI:0021CA*
- ID_OUI_FROM_DATABASE=ART System Co., Ltd.
+OUI:00233A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:0021C3*
- ID_OUI_FROM_DATABASE=CORNELL Communications, Inc.
+OUI:002339*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
OUI:002334*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:002310*
ID_OUI_FROM_DATABASE=LNC Technology Co., Ltd.
-OUI:002273*
- ID_OUI_FROM_DATABASE=Techway
-
-OUI:002274*
- ID_OUI_FROM_DATABASE=FamilyPhone AB
+OUI:002304*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:00226F*
- ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd.
+OUI:002236*
+ ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O.
-OUI:00226A*
- ID_OUI_FROM_DATABASE=Honeywell
+OUI:002230*
+ ID_OUI_FROM_DATABASE=FutureLogic Inc.
-OUI:002260*
- ID_OUI_FROM_DATABASE=AFREEY Inc.
+OUI:002229*
+ ID_OUI_FROM_DATABASE=Compumedics Ltd
-OUI:00225B*
- ID_OUI_FROM_DATABASE=Teradici Corporation
+OUI:00221D*
+ ID_OUI_FROM_DATABASE=Freegene Technology LTD
-OUI:002256*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:002224*
+ ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd.
-OUI:002255*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:002223*
+ ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc.
-OUI:00224D*
- ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP.
+OUI:002216*
+ ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION
-OUI:002252*
- ID_OUI_FROM_DATABASE=ZOLL Lifecor Corporation
+OUI:002217*
+ ID_OUI_FROM_DATABASE=Neat Electronics
-OUI:002246*
- ID_OUI_FROM_DATABASE=Evoc Intelligent Technology Co.,Ltd.
+OUI:002211*
+ ID_OUI_FROM_DATABASE=Rohati Systems
-OUI:002366*
- ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd.
+OUI:00220A*
+ ID_OUI_FROM_DATABASE=OnLive, Inc
-OUI:00236B*
- ID_OUI_FROM_DATABASE=Xembedded, Inc.
+OUI:002295*
+ ID_OUI_FROM_DATABASE=SGM Technology for lighting spa
-OUI:002359*
- ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited
+OUI:00228E*
+ ID_OUI_FROM_DATABASE=TV-NUMERIC
-OUI:00235F*
- ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH
+OUI:002289*
+ ID_OUI_FROM_DATABASE=Optosecurity Inc.
-OUI:002353*
- ID_OUI_FROM_DATABASE=F E T Elettronica snc
+OUI:002282*
+ ID_OUI_FROM_DATABASE=8086 Consultancy
-OUI:002347*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:00227C*
+ ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd
-OUI:00234C*
- ID_OUI_FROM_DATABASE=KTC AB
+OUI:002279*
+ ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd.
-OUI:002340*
- ID_OUI_FROM_DATABASE=MiX Telematics
+OUI:002273*
+ ID_OUI_FROM_DATABASE=Techway
-OUI:00233A*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:002274*
+ ID_OUI_FROM_DATABASE=FamilyPhone AB
-OUI:002339*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:00226F*
+ ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd.
-OUI:002304*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00226A*
+ ID_OUI_FROM_DATABASE=Honeywell
OUI:0022F3*
ID_OUI_FROM_DATABASE=SHARP Corporation
OUI:0022DB*
ID_OUI_FROM_DATABASE=Translogic Corporation
-OUI:0022A1*
- ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd.
+OUI:0022CF*
+ ID_OUI_FROM_DATABASE=PLANEX Communications INC
-OUI:00229B*
- ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc.
+OUI:0022D4*
+ ID_OUI_FROM_DATABASE=ComWorth Co., Ltd.
-OUI:00229C*
- ID_OUI_FROM_DATABASE=Verismo Networks Inc
+OUI:0022CA*
+ ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd.
-OUI:002295*
- ID_OUI_FROM_DATABASE=SGM Technology for lighting spa
+OUI:0022C5*
+ ID_OUI_FROM_DATABASE=INFORSON Co,Ltd.
-OUI:00228E*
- ID_OUI_FROM_DATABASE=TV-NUMERIC
+OUI:002260*
+ ID_OUI_FROM_DATABASE=AFREEY Inc.
-OUI:002289*
- ID_OUI_FROM_DATABASE=Optosecurity Inc.
+OUI:00225B*
+ ID_OUI_FROM_DATABASE=Teradici Corporation
-OUI:002282*
- ID_OUI_FROM_DATABASE=8086 Consultancy
+OUI:002256*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:00227C*
- ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd
+OUI:002255*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:002279*
- ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd.
+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:002236*
- ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O.
+OUI:0022C0*
+ ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd
-OUI:002230*
- ID_OUI_FROM_DATABASE=FutureLogic Inc.
+OUI:0022BB*
+ ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG
-OUI:002229*
- ID_OUI_FROM_DATABASE=Compumedics Ltd
+OUI:0022AE*
+ ID_OUI_FROM_DATABASE=Mattel Inc.
-OUI:00221D*
- ID_OUI_FROM_DATABASE=Freegene Technology LTD
+OUI:0022AD*
+ ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC.
-OUI:002224*
- ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd.
+OUI:0022A8*
+ ID_OUI_FROM_DATABASE=Ouman Oy
-OUI:002223*
- ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc.
+OUI:0022A1*
+ ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd.
-OUI:002216*
- ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION
+OUI:00229B*
+ ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc.
-OUI:002217*
- ID_OUI_FROM_DATABASE=Neat Electronics
+OUI:00229C*
+ ID_OUI_FROM_DATABASE=Verismo Networks Inc
-OUI:002211*
- ID_OUI_FROM_DATABASE=Rohati Systems
+OUI:0023A8*
+ ID_OUI_FROM_DATABASE=Marshall Electronics
-OUI:00220A*
- ID_OUI_FROM_DATABASE=OnLive, Inc
+OUI:00239B*
+ ID_OUI_FROM_DATABASE=Elster Solutions, LLC
-OUI:002204*
- ID_OUI_FROM_DATABASE=KORATEK
+OUI:002396*
+ ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION
-OUI:0021FF*
- ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA
+OUI:002391*
+ ID_OUI_FROM_DATABASE=Maxian
-OUI:0021FB*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:00238C*
+ ID_OUI_FROM_DATABASE=Private
-OUI:0021F5*
- ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc.
+OUI:002387*
+ ID_OUI_FROM_DATABASE=ThinkFlood, Inc.
-OUI:0021EF*
- ID_OUI_FROM_DATABASE=Kapsys
+OUI:0021D6*
+ ID_OUI_FROM_DATABASE=LXI Consortium
-OUI:0021EE*
- ID_OUI_FROM_DATABASE=Full Spectrum Inc.
+OUI:0021CF*
+ ID_OUI_FROM_DATABASE=The Crypto Group
-OUI:0022CF*
- ID_OUI_FROM_DATABASE=PLANEX Communications INC
+OUI:0021C9*
+ ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited
-OUI:0022D4*
- ID_OUI_FROM_DATABASE=ComWorth Co., Ltd.
+OUI:0021CA*
+ ID_OUI_FROM_DATABASE=ART System Co., Ltd.
-OUI:0022CA*
- ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd.
+OUI:0021C3*
+ ID_OUI_FROM_DATABASE=CORNELL Communications, Inc.
-OUI:0022C5*
- ID_OUI_FROM_DATABASE=INFORSON Co,Ltd.
+OUI:0021BC*
+ ID_OUI_FROM_DATABASE=ZALA COMPUTER
-OUI:0022C0*
- ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd
+OUI:0021B7*
+ ID_OUI_FROM_DATABASE=Lexmark International Inc.
-OUI:0022BB*
- ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG
+OUI:002152*
+ ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited
-OUI:0022AE*
- ID_OUI_FROM_DATABASE=Mattel Inc.
+OUI:002157*
+ ID_OUI_FROM_DATABASE=National Datacast, Inc.
-OUI:0022AD*
- ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC.
+OUI:00214B*
+ ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd
-OUI:0022A8*
- ID_OUI_FROM_DATABASE=Ouman Oy
+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:002131*
ID_OUI_FROM_DATABASE=Blynke Inc.
-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:001FD1*
+ ID_OUI_FROM_DATABASE=OPTEX CO.,LTD.
-OUI:002119*
- ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics
+OUI:001FCA*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:002112*
- ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD
+OUI:001FBE*
+ ID_OUI_FROM_DATABASE=Shenzhen Mopnet Industrial Co.,Ltd
OUI:001FB9*
ID_OUI_FROM_DATABASE=Paltronics
OUI:001FB2*
ID_OUI_FROM_DATABASE=Sontheim Industrie Elektronik 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:00211F*
+ ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD.
-OUI:00215E*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:002120*
+ ID_OUI_FROM_DATABASE=Sequel Technologies
-OUI:002151*
- ID_OUI_FROM_DATABASE=Millinet Co., Ltd.
+OUI:002125*
+ ID_OUI_FROM_DATABASE=KUK JE TONG SHIN Co.,LTD
-OUI:002152*
- ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited
+OUI:002119*
+ ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics
-OUI:002157*
- ID_OUI_FROM_DATABASE=National Datacast, Inc.
+OUI:002112*
+ ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD
-OUI:00214B*
- ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd
+OUI:002103*
+ ID_OUI_FROM_DATABASE=GHI Electronics, LLC
-OUI:002145*
- ID_OUI_FROM_DATABASE=Semptian Technologies Ltd.
+OUI:0021B0*
+ ID_OUI_FROM_DATABASE=Tyco Telecommunications
-OUI:002144*
- ID_OUI_FROM_DATABASE=SS Telecoms
+OUI:0021A4*
+ ID_OUI_FROM_DATABASE=Dbii Networks
-OUI:00213C*
- ID_OUI_FROM_DATABASE=AliphCom
+OUI:00219A*
+ ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd
-OUI:00213B*
- ID_OUI_FROM_DATABASE=Berkshire Products, Inc
+OUI:002196*
+ ID_OUI_FROM_DATABASE=Telsey S.p.A.
OUI:002190*
ID_OUI_FROM_DATABASE=Goliath Solutions
OUI:002183*
ID_OUI_FROM_DATABASE=VATECH HYDRO
-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:002103*
- ID_OUI_FROM_DATABASE=GHI Electronics, LLC
-
OUI:001FFA*
ID_OUI_FROM_DATABASE=Coretree, Co, Ltd
OUI:001FDB*
ID_OUI_FROM_DATABASE=Network Supply Corp.,
-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: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:00217D*
+ ID_OUI_FROM_DATABASE=PYXIS S.R.L.
-OUI:001F56*
- ID_OUI_FROM_DATABASE=DIGITAL FORECAST
+OUI:002177*
+ ID_OUI_FROM_DATABASE=W. L. Gore & Associates
-OUI:001F4F*
- ID_OUI_FROM_DATABASE=Thinkware Co. Ltd.
+OUI:002176*
+ ID_OUI_FROM_DATABASE=YMax Telecom Ltd.
-OUI:001F48*
- ID_OUI_FROM_DATABASE=Mojix Inc.
+OUI:002171*
+ ID_OUI_FROM_DATABASE=Wesung TNC Co., Ltd.
-OUI:001F43*
- ID_OUI_FROM_DATABASE=ENTES ELEKTRONIK
+OUI:002164*
+ ID_OUI_FROM_DATABASE=Special Design Bureau for Seismic Instrumentation
-OUI:001F8E*
- ID_OUI_FROM_DATABASE=Metris USA Inc.
+OUI:00215E*
+ ID_OUI_FROM_DATABASE=IBM Corp
-OUI:001F88*
- ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG
+OUI:002151*
+ ID_OUI_FROM_DATABASE=Millinet Co., Ltd.
-OUI:001F81*
- ID_OUI_FROM_DATABASE=Accel Semiconductor Corp
+OUI:002204*
+ ID_OUI_FROM_DATABASE=KORATEK
-OUI:001B58*
- ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd.
+OUI:0021FF*
+ ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA
-OUI:001F78*
- ID_OUI_FROM_DATABASE=Blue Fox Porini Textile
+OUI:0021FB*
+ ID_OUI_FROM_DATABASE=LG Electronics
-OUI:001F6E*
- ID_OUI_FROM_DATABASE=Vtech Engineering Corporation
+OUI:0021F5*
+ ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc.
-OUI:001F68*
- ID_OUI_FROM_DATABASE=Martinsson Elektronik AB
+OUI:0021EF*
+ ID_OUI_FROM_DATABASE=Kapsys
-OUI:0021BC*
- ID_OUI_FROM_DATABASE=ZALA COMPUTER
+OUI:0021EE*
+ ID_OUI_FROM_DATABASE=Full Spectrum Inc.
-OUI:0021B7*
- ID_OUI_FROM_DATABASE=Lexmark International Inc.
+OUI:0021DC*
+ ID_OUI_FROM_DATABASE=TECNOALARM S.r.l.
-OUI:0021B0*
- ID_OUI_FROM_DATABASE=Tyco Telecommunications
+OUI:0021E2*
+ ID_OUI_FROM_DATABASE=Creative Electronic GmbH
-OUI:0021A4*
- ID_OUI_FROM_DATABASE=Dbii Networks
+OUI:001FAB*
+ ID_OUI_FROM_DATABASE=I.S HIGH TECH.INC
-OUI:00219A*
- ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd
+OUI:001FA6*
+ ID_OUI_FROM_DATABASE=Stilo srl
-OUI:002196*
- ID_OUI_FROM_DATABASE=Telsey S.p.A.
+OUI:001FA1*
+ ID_OUI_FROM_DATABASE=Gtran Inc
-OUI:001E4B*
- ID_OUI_FROM_DATABASE=City Theatrical
+OUI:001F9C*
+ ID_OUI_FROM_DATABASE=LEDCO
-OUI:001E47*
- ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering
+OUI:001F8E*
+ ID_OUI_FROM_DATABASE=Metris USA Inc.
OUI:001E41*
ID_OUI_FROM_DATABASE=Microwave Communication & Component, Inc.
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:001DEC*
ID_OUI_FROM_DATABASE=Marusys
-OUI:001DE6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001F88*
+ ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG
-OUI:001DDA*
- ID_OUI_FROM_DATABASE=Mikroelektronika spol. s r. o.
+OUI:001F81*
+ ID_OUI_FROM_DATABASE=Accel Semiconductor Corp
-OUI:001DDF*
- ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
+OUI:001B58*
+ ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd.
-OUI:001DCC*
- ID_OUI_FROM_DATABASE=Hetra Secure Solutions
+OUI:001F78*
+ ID_OUI_FROM_DATABASE=Blue Fox Porini Textile
-OUI:001DC7*
- ID_OUI_FROM_DATABASE=L-3 Communications Geneva Aerospace
+OUI:001F6E*
+ ID_OUI_FROM_DATABASE=Vtech Engineering Corporation
-OUI:001DC0*
- ID_OUI_FROM_DATABASE=Enphase Energy
+OUI:001F68*
+ ID_OUI_FROM_DATABASE=Martinsson Elektronik AB
-OUI:001ED8*
- ID_OUI_FROM_DATABASE=Digital United Inc.
+OUI:001F62*
+ ID_OUI_FROM_DATABASE=JSC Stilsoft
-OUI:001ED2*
- ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc
+OUI:001F67*
+ ID_OUI_FROM_DATABASE=Hitachi,Ltd.
-OUI:001ED1*
- ID_OUI_FROM_DATABASE=Keyprocessor B.V.
+OUI:001F55*
+ ID_OUI_FROM_DATABASE=Honeywell Security (China) Co., Ltd.
-OUI:001ECC*
- ID_OUI_FROM_DATABASE=CDVI
+OUI:001E9B*
+ ID_OUI_FROM_DATABASE=San-Eisha, Ltd.
-OUI:001EC5*
- ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc
+OUI:001E94*
+ ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION
-OUI:001EC0*
- ID_OUI_FROM_DATABASE=Microchip Technology Inc.
+OUI:001E8F*
+ ID_OUI_FROM_DATABASE=CANON INC.
-OUI:001EBF*
- ID_OUI_FROM_DATABASE=Haas Automation Inc.
+OUI:001E87*
+ ID_OUI_FROM_DATABASE=Realease Limited
-OUI:001EB9*
- ID_OUI_FROM_DATABASE=Sing Fai Technology Limited
+OUI:001E80*
+ ID_OUI_FROM_DATABASE=Last Mile Ltd.
-OUI:001EB2*
- ID_OUI_FROM_DATABASE=LG innotek
+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:001F27*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001F20*
- ID_OUI_FROM_DATABASE=Logitech Europe SA
+OUI:001EF5*
+ ID_OUI_FROM_DATABASE=Hitek Automated Inc.
-OUI:001F14*
- ID_OUI_FROM_DATABASE=NexG
+OUI:001EFB*
+ ID_OUI_FROM_DATABASE=Trio Motion Technology Ltd
-OUI:001F1B*
- ID_OUI_FROM_DATABASE=RoyalTek Company Ltd.
+OUI:001EE9*
+ ID_OUI_FROM_DATABASE=Stoneridge Electronics AB
-OUI:001F0D*
- ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West
+OUI:001EEE*
+ ID_OUI_FROM_DATABASE=ETL Systems Ltd
-OUI:001F0E*
- ID_OUI_FROM_DATABASE=Japan Kyastem Co., Ltd
+OUI:001EE2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:001E22*
- ID_OUI_FROM_DATABASE=ARVOO Imaging Products BV
+OUI:001ED8*
+ ID_OUI_FROM_DATABASE=Digital United Inc.
-OUI:001E1B*
- ID_OUI_FROM_DATABASE=Digital Stream Technology, Inc.
+OUI:001ED2*
+ ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc
-OUI:001E16*
- ID_OUI_FROM_DATABASE=Keytronix
+OUI:001ED1*
+ ID_OUI_FROM_DATABASE=Keyprocessor B.V.
-OUI:001E15*
- ID_OUI_FROM_DATABASE=Beech Hill Electronics
+OUI:001ECC*
+ ID_OUI_FROM_DATABASE=CDVI
-OUI:001E11*
- ID_OUI_FROM_DATABASE=ELELUX INTERNATIONAL LTD
+OUI:001EC5*
+ ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc
-OUI:001E05*
- ID_OUI_FROM_DATABASE=Xseed Technologies & Computing
+OUI:001EC0*
+ ID_OUI_FROM_DATABASE=Microchip Technology Inc.
-OUI:001E0C*
- ID_OUI_FROM_DATABASE=Sherwood Information Partners, Inc.
+OUI:001EBF*
+ ID_OUI_FROM_DATABASE=Haas Automation Inc.
-OUI:001DFE*
- ID_OUI_FROM_DATABASE=Palm, Inc
+OUI:001EB9*
+ ID_OUI_FROM_DATABASE=Sing Fai Technology Limited
-OUI:001DF9*
- ID_OUI_FROM_DATABASE=Cybiotronics (Far East) Limited
+OUI:001EB2*
+ ID_OUI_FROM_DATABASE=LG innotek
OUI:001EAD*
ID_OUI_FROM_DATABASE=Wingtech Group Limited
OUI:001EA1*
ID_OUI_FROM_DATABASE=Brunata a/s
-OUI:001E9B*
- ID_OUI_FROM_DATABASE=San-Eisha, Ltd.
+OUI:001F20*
+ ID_OUI_FROM_DATABASE=Logitech Europe SA
-OUI:001E94*
- ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION
+OUI:001F14*
+ ID_OUI_FROM_DATABASE=NexG
-OUI:001E8F*
- ID_OUI_FROM_DATABASE=CANON INC.
+OUI:001F1B*
+ ID_OUI_FROM_DATABASE=RoyalTek Company Ltd.
-OUI:001E87*
- ID_OUI_FROM_DATABASE=Realease Limited
+OUI:001F0D*
+ ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West
-OUI:001E80*
- ID_OUI_FROM_DATABASE=Last Mile Ltd.
+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: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: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:001E71*
ID_OUI_FROM_DATABASE=MIrcom Group of Companies
OUI:001E51*
ID_OUI_FROM_DATABASE=Converter Industry Srl
-OUI:001DB9*
- ID_OUI_FROM_DATABASE=Wellspring Wireless
-
-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:001D45*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001E4B*
+ ID_OUI_FROM_DATABASE=City Theatrical
-OUI:001D3E*
- ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD
+OUI:001E47*
+ ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering
OUI:001D37*
ID_OUI_FROM_DATABASE=Thales-Panda Transportation System
OUI:001D1A*
ID_OUI_FROM_DATABASE=OvisLink S.A.
-OUI:001D7A*
- ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc.
-
-OUI:001D74*
- ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd.
-
-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:001CE8*
- ID_OUI_FROM_DATABASE=Cummins Inc
-
-OUI:001CE4*
- ID_OUI_FROM_DATABASE=EleSy JSC
+OUI:001D14*
+ ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED
OUI:001CDD*
ID_OUI_FROM_DATABASE=COWBELL ENGINEERING CO., LTD.
OUI:001CC5*
ID_OUI_FROM_DATABASE=3Com Ltd
-OUI:001D0D*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment inc.
+OUI:001CB9*
+ ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD.
-OUI:001D14*
- ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED
+OUI:001CAF*
+ ID_OUI_FROM_DATABASE=Plato Networks Inc.
-OUI:001D08*
- ID_OUI_FROM_DATABASE=JIANGSU YINHE ELECTRONICS CO., LTD
+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:001CF5*
ID_OUI_FROM_DATABASE=Wiseblue Technology Limited
-OUI:001CB9*
- ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD.
-
-OUI:001CAF*
- ID_OUI_FROM_DATABASE=Plato Networks Inc.
+OUI:001CE8*
+ ID_OUI_FROM_DATABASE=Cummins Inc
-OUI:001CB4*
- ID_OUI_FROM_DATABASE=Iridium Satellite LLC
+OUI:001CE4*
+ ID_OUI_FROM_DATABASE=EleSy JSC
OUI:001C9F*
ID_OUI_FROM_DATABASE=Razorstream, LLC
OUI:001C82*
ID_OUI_FROM_DATABASE=Genew Technologies
-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: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:001C7D*
ID_OUI_FROM_DATABASE=Excelpoint Manufacturing Pte Ltd
OUI:001C78*
ID_OUI_FROM_DATABASE=WYPLAY SAS
-OUI:001C6C*
- ID_OUI_FROM_DATABASE=Jabil Circuit (Guangzhou) Limited
-
-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:001C30*
- ID_OUI_FROM_DATABASE=Mode Lighting (UK ) Ltd.
+OUI:001D62*
+ ID_OUI_FROM_DATABASE=InPhase Technologies
-OUI:001C2B*
- ID_OUI_FROM_DATABASE=Alertme.com Limited
+OUI:001D61*
+ ID_OUI_FROM_DATABASE=BIJ Corporation
-OUI:001C2A*
- ID_OUI_FROM_DATABASE=Envisacor Technologies Inc.
+OUI:001D5B*
+ ID_OUI_FROM_DATABASE=Tecvan Informática Ltda
-OUI:001C29*
- ID_OUI_FROM_DATABASE=CORE DIGITAL ELECTRONICS CO., LTD
+OUI:001D54*
+ ID_OUI_FROM_DATABASE=Sunnic Technology & Merchandise INC.
-OUI:001C24*
- ID_OUI_FROM_DATABASE=Formosa Wireless Systems Corp.
+OUI:001D4A*
+ ID_OUI_FROM_DATABASE=Carestream Health, Inc.
-OUI:001C1F*
- ID_OUI_FROM_DATABASE=Quest Retail Technology Pty Ltd
+OUI:001D45*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001D97*
- ID_OUI_FROM_DATABASE=Alertus Technologies LLC
+OUI:001D3E*
+ ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD
OUI:001D90*
ID_OUI_FROM_DATABASE=EMCO Flow Systems
OUI:001D67*
ID_OUI_FROM_DATABASE=AMEC
-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: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:001B7D*
- ID_OUI_FROM_DATABASE=CXR Anderson Jacobson
-
-OUI:001B71*
- ID_OUI_FROM_DATABASE=Telular Corp.
+OUI:001D7A*
+ ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc.
-OUI:001B6A*
- ID_OUI_FROM_DATABASE=Powerwave Technologies Sweden AB
+OUI:001D74*
+ ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd.
-OUI:001B65*
- ID_OUI_FROM_DATABASE=China Gridcom Co., Ltd
+OUI:001DB4*
+ ID_OUI_FROM_DATABASE=KUMHO ENG CO.,LTD
-OUI:001B5E*
- ID_OUI_FROM_DATABASE=BPL Limited
+OUI:001DAF*
+ ID_OUI_FROM_DATABASE=Nortel
-OUI:001B57*
- ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PRIVATE LIMITED
+OUI:001D9E*
+ ID_OUI_FROM_DATABASE=AXION TECHNOLOGIES
-OUI:001B46*
- ID_OUI_FROM_DATABASE=Blueone Technology Co.,Ltd
+OUI:001DA3*
+ ID_OUI_FROM_DATABASE=SabiOso
-OUI:001B4B*
- ID_OUI_FROM_DATABASE=SANION Co., Ltd.
+OUI:001D9D*
+ ID_OUI_FROM_DATABASE=ARTJOY INTERNATIONAL LIMITED
-OUI:001BAD*
- ID_OUI_FROM_DATABASE=iControl Incorporated
+OUI:001D97*
+ ID_OUI_FROM_DATABASE=Alertus Technologies LLC
OUI:001BA6*
ID_OUI_FROM_DATABASE=intotech inc.
OUI:001B84*
ID_OUI_FROM_DATABASE=Scan Engineering Telecom
-OUI:001BD1*
- ID_OUI_FROM_DATABASE=SOGESTMATIC
+OUI:001B7D*
+ ID_OUI_FROM_DATABASE=CXR Anderson Jacobson
-OUI:001BD6*
- ID_OUI_FROM_DATABASE=Kelvin Hughes Ltd
+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:001BB4*
ID_OUI_FROM_DATABASE=Airvod Limited
-OUI:001BB9*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co.
-
-OUI:001B14*
- ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory
-
-OUI:001B0D*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-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:001BAD*
+ ID_OUI_FROM_DATABASE=iControl Incorporated
OUI:001AD1*
ID_OUI_FROM_DATABASE=FARGO CO., LTD.
OUI:001AC0*
ID_OUI_FROM_DATABASE=JOYBIEN TECHNOLOGIES CO., LTD.
-OUI:001A60*
- ID_OUI_FROM_DATABASE=Wave Electronics Co.,Ltd.
+OUI:001AB4*
+ ID_OUI_FROM_DATABASE=FFEI Ltd.
-OUI:001A55*
- ID_OUI_FROM_DATABASE=ACA-Digital Corporation
+OUI:001AAF*
+ ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY
-OUI:001A5A*
- ID_OUI_FROM_DATABASE=Korea Electric Power Data Network (KDN) Co., Ltd
+OUI:001C07*
+ ID_OUI_FROM_DATABASE=Cwlinux Limited
-OUI:001A4E*
- ID_OUI_FROM_DATABASE=NTI AG / LinMot
+OUI:001C00*
+ ID_OUI_FROM_DATABASE=Entry Point, LLC
-OUI:001A53*
- ID_OUI_FROM_DATABASE=Zylaya
+OUI:001BF4*
+ ID_OUI_FROM_DATABASE=KENWIN INDUSTRIAL(HK) LTD.
-OUI:001A42*
- ID_OUI_FROM_DATABASE=Techcity Technology co., Ltd.
+OUI:001BEF*
+ ID_OUI_FROM_DATABASE=Blossoms Digital Technology Co.,Ltd.
-OUI:001A47*
- ID_OUI_FROM_DATABASE=Agami Systems, Inc.
+OUI:001BE2*
+ ID_OUI_FROM_DATABASE=AhnLab,Inc.
-OUI:001A3B*
- ID_OUI_FROM_DATABASE=Doah Elecom Inc.
+OUI:001BD1*
+ ID_OUI_FROM_DATABASE=SOGESTMATIC
-OUI:001B3F*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+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:001B19*
ID_OUI_FROM_DATABASE=IEEE I&M Society TC9
-OUI:001AB4*
- ID_OUI_FROM_DATABASE=FFEI Ltd.
+OUI:001B14*
+ ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory
-OUI:001AAF*
- ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY
+OUI:001B0D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:001AA8*
ID_OUI_FROM_DATABASE=Mamiya Digital Imaging Co., Ltd.
OUI:001AA6*
ID_OUI_FROM_DATABASE=Telefunken Radio Communication Systems GmbH &CO.KG
-OUI:00193F*
- ID_OUI_FROM_DATABASE=RDI technology(Shenzhen) Co.,LTD
+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:00192D*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:001921*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co.
-
OUI:001926*
ID_OUI_FROM_DATABASE=BitsGen Co., Ltd.
OUI:00191A*
ID_OUI_FROM_DATABASE=IRLINK
-OUI:001993*
- ID_OUI_FROM_DATABASE=Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea
-
-OUI:001998*
- ID_OUI_FROM_DATABASE=SATO CORPORATION
-
OUI:00199D*
ID_OUI_FROM_DATABASE=VIZIO, Inc.
OUI:001944*
ID_OUI_FROM_DATABASE=Fossil Partners, L.P.
-OUI:001A2F*
+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:001A34*
- ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+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:001A06*
ID_OUI_FROM_DATABASE=OpVista, Inc.
-OUI:0018CD*
- ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd
-
-OUI:0018D2*
- ID_OUI_FROM_DATABASE=High-Gain Antennas LLC
-
-OUI:0018D7*
- ID_OUI_FROM_DATABASE=Javad Navigation 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:0019FA*
+ ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD.
-OUI:0018AE*
- ID_OUI_FROM_DATABASE=TVT CO.,LTD
+OUI:0019FF*
+ ID_OUI_FROM_DATABASE=Finnzymes
OUI:001902*
ID_OUI_FROM_DATABASE=Cambridge Consultants Ltd
OUI:0018E5*
ID_OUI_FROM_DATABASE=Adhoco AG
-OUI:0018A2*
- ID_OUI_FROM_DATABASE=XIP Technology AB
-
-OUI:0018A9*
- ID_OUI_FROM_DATABASE=Ethernet Direct Corporation
-
-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:0019C8*
- ID_OUI_FROM_DATABASE=AnyDATA Corporation
-
-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:0019FA*
- ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD.
+OUI:0018CD*
+ ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd
-OUI:0019FF*
- ID_OUI_FROM_DATABASE=Finnzymes
+OUI:0018D2*
+ ID_OUI_FROM_DATABASE=High-Gain Antennas LLC
OUI:0019EC*
ID_OUI_FROM_DATABASE=Sagamore Systems, Inc.
OUI:0019D9*
ID_OUI_FROM_DATABASE=Zeutschel GmbH
-OUI:001823*
- ID_OUI_FROM_DATABASE=Delta Electronics, Inc.
+OUI:0019C8*
+ ID_OUI_FROM_DATABASE=AnyDATA Corporation
OUI:001817*
ID_OUI_FROM_DATABASE=D. E. Shaw Research, LLC
OUI:001805*
ID_OUI_FROM_DATABASE=Beijing InHand Networking Technology Co.,Ltd.
-OUI:0017B8*
- ID_OUI_FROM_DATABASE=NOVATRON CO., LTD.
+OUI:0017F4*
+ ID_OUI_FROM_DATABASE=ZERON ALLIANCE
-OUI:0017BD*
- ID_OUI_FROM_DATABASE=Tibetsystem
+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:00179B*
ID_OUI_FROM_DATABASE=Chant Sincere CO., LTD.
-OUI:00170F*
+OUI:00178F*
+ ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD.
+
+OUI:001794*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001705*
- ID_OUI_FROM_DATABASE=Methode Electronics
+OUI:00178D*
+ ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc.
-OUI:00170A*
- ID_OUI_FROM_DATABASE=INEW DIGITAL COMPANY
+OUI:0018D9*
+ ID_OUI_FROM_DATABASE=Santosha Internatonal, Inc
-OUI:0016F9*
- ID_OUI_FROM_DATABASE=CETRTA POT, d.o.o., Kranj
+OUI:0018C1*
+ ID_OUI_FROM_DATABASE=Almitec Informática e Comércio
-OUI:0016F2*
- ID_OUI_FROM_DATABASE=Dmobile System Co., Ltd.
+OUI:0018C8*
+ ID_OUI_FROM_DATABASE=ISONAS Inc.
-OUI:0016F7*
- ID_OUI_FROM_DATABASE=L-3 Communications, Aviation Recorders
+OUI:0018BC*
+ ID_OUI_FROM_DATABASE=ZAO NVP Bolid
-OUI:0016E6*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+OUI:0018B5*
+ ID_OUI_FROM_DATABASE=Magna Carta
-OUI:00178F*
- ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD.
+OUI:0018B0*
+ ID_OUI_FROM_DATABASE=Nortel
-OUI:001794*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0018AE*
+ ID_OUI_FROM_DATABASE=TVT CO.,LTD
-OUI:00178D*
- ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc.
+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: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:001836*
ID_OUI_FROM_DATABASE=Reliance Electric Limited
-OUI:001759*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001823*
+ ID_OUI_FROM_DATABASE=Delta Electronics, Inc.
OUI:001754*
ID_OUI_FROM_DATABASE=Arkino HiTOP Corporation Limited
OUI:00172E*
ID_OUI_FROM_DATABASE=FXC Inc.
-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: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:0017ED*
ID_OUI_FROM_DATABASE=WooJooIT Ltd.
OUI:0017C4*
ID_OUI_FROM_DATABASE=Quanta Microsystems, INC.
-OUI:001880*
- ID_OUI_FROM_DATABASE=Maxim Integrated Products
+OUI:0017B8*
+ ID_OUI_FROM_DATABASE=NOVATRON CO., LTD.
-OUI:00186D*
- ID_OUI_FROM_DATABASE=Zhenjiang Sapphire Electronic Industry CO.
+OUI:0017BD*
+ ID_OUI_FROM_DATABASE=Tibetsystem
-OUI:001872*
- ID_OUI_FROM_DATABASE=Expertise Engineering
+OUI:00189D*
+ ID_OUI_FROM_DATABASE=Navcast Inc.
-OUI:001874*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001893*
+ ID_OUI_FROM_DATABASE=SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD
-OUI:001879*
- ID_OUI_FROM_DATABASE=dSys
+OUI:001898*
+ ID_OUI_FROM_DATABASE=KINGSTATE ELECTRONICS CORPORATION
-OUI:001686*
- ID_OUI_FROM_DATABASE=Karl Storz Imaging
+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:00165F*
ID_OUI_FROM_DATABASE=Fairmount Automation
-OUI:0016AA*
- ID_OUI_FROM_DATABASE=Kei Communication Technology Inc.
-
-OUI:0016AF*
- ID_OUI_FROM_DATABASE=Shenzhen Union Networks Equipment Co.,Ltd.
-
-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:00165A*
ID_OUI_FROM_DATABASE=Harman Specialty Group
OUI:001653*
ID_OUI_FROM_DATABASE=LEGO System A/S IE Electronics Division
-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:0015F5*
- ID_OUI_FROM_DATABASE=Sustainable Energy Systems
-
-OUI:0015F4*
- ID_OUI_FROM_DATABASE=Eventide
-
-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:001598*
- ID_OUI_FROM_DATABASE=Kolektor group
-
-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:0016DF*
ID_OUI_FROM_DATABASE=Lundinova AB
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:0015FA*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001563*
+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:001557*
- ID_OUI_FROM_DATABASE=Olivetti
+OUI:001642*
+ ID_OUI_FROM_DATABASE=Pangolin
-OUI:00155C*
- ID_OUI_FROM_DATABASE=Dresser Wayne
+OUI:00163D*
+ ID_OUI_FROM_DATABASE=Tsinghua Tongfang Legend Silicon Tech. Co., Ltd.
-OUI:00154B*
- ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd
+OUI:001636*
+ ID_OUI_FROM_DATABASE=Quanta Computer Inc.
-OUI:001550*
- ID_OUI_FROM_DATABASE=Nits Technology 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:001545*
- ID_OUI_FROM_DATABASE=SEECODE Co., Ltd.
+OUI:0015DD*
+ ID_OUI_FROM_DATABASE=IP Control Systems Ltd.
-OUI:00153E*
- ID_OUI_FROM_DATABASE=Q-Matic Sweden AB
+OUI:0015D8*
+ ID_OUI_FROM_DATABASE=Interlink Electronics
+
+OUI:0015CA*
+ ID_OUI_FROM_DATABASE=TeraRecon, Inc.
OUI:0015BC*
ID_OUI_FROM_DATABASE=Develco
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:001510*
ID_OUI_FROM_DATABASE=Techsphere Co., Ltd
-OUI:001453*
- ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES 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:001436*
ID_OUI_FROM_DATABASE=Qwerty Elektronik AB
-OUI:00142A*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co., Ltd
-
-OUI:0014AB*
- ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd.
-
-OUI:0014B0*
- ID_OUI_FROM_DATABASE=Naeil Community
+OUI:001423*
+ ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM
-OUI:0014B4*
- ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd
+OUI:001593*
+ ID_OUI_FROM_DATABASE=U4EA Technologies Inc.
-OUI:0014A9*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00158C*
+ ID_OUI_FROM_DATABASE=Liab ApS
-OUI:0014AA*
- ID_OUI_FROM_DATABASE=Ashly Audio, Inc.
+OUI:001586*
+ ID_OUI_FROM_DATABASE=Xiamen Overseas Chinese Electronic Co., Ltd.
-OUI:00149D*
- ID_OUI_FROM_DATABASE=Sound ID Inc.
+OUI:001585*
+ ID_OUI_FROM_DATABASE=Aonvision Technolopy Corp.
-OUI:001498*
- ID_OUI_FROM_DATABASE=Viking Design Technology
+OUI:001587*
+ ID_OUI_FROM_DATABASE=Takenaka Seisakusho Co.,Ltd
-OUI:00148A*
- ID_OUI_FROM_DATABASE=Elin Ebg Traction Gmbh
+OUI:001580*
+ ID_OUI_FROM_DATABASE=U-WAY CORPORATION
-OUI:001491*
- ID_OUI_FROM_DATABASE=Daniels Electronics Ltd. dbo Codan Rado Communications
+OUI:00157B*
+ ID_OUI_FROM_DATABASE=Leuze electronic GmbH + Co. KG
-OUI:001485*
- ID_OUI_FROM_DATABASE=Giga-Byte
+OUI:001576*
+ ID_OUI_FROM_DATABASE=LABiTec - Labor Biomedical Technologies GmbH
-OUI:001479*
- ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd.
+OUI:00156A*
+ ID_OUI_FROM_DATABASE=DG2L Technologies Pvt. Ltd.
-OUI:00147E*
- ID_OUI_FROM_DATABASE=InnerWireless
+OUI:00156F*
+ ID_OUI_FROM_DATABASE=Xiranet Communications GmbH
-OUI:001478*
- ID_OUI_FROM_DATABASE=ShenZhen TP-LINK Technologies Co., Ltd.
+OUI:001563*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:001477*
- ID_OUI_FROM_DATABASE=Nertec Inc.
+OUI:0014FD*
+ ID_OUI_FROM_DATABASE=Thecus Technology Corp.
-OUI:001472*
- ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard Group
+OUI:0014EF*
+ ID_OUI_FROM_DATABASE=TZero Technologies, Inc.
-OUI:001466*
- ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH
+OUI:0014F1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:00146B*
- ID_OUI_FROM_DATABASE=Anagran, Inc.
+OUI:0014F0*
+ ID_OUI_FROM_DATABASE=Business Security OL AB
-OUI:00145F*
- ID_OUI_FROM_DATABASE=ADITEC CO. LTD
+OUI:0014EA*
+ ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.)
-OUI:001458*
- ID_OUI_FROM_DATABASE=HS Automatic ApS
+OUI:0014E5*
+ ID_OUI_FROM_DATABASE=Alticast
OUI:0014E6*
ID_OUI_FROM_DATABASE=AIM Infrarotmodule GmbH
OUI:0014B5*
ID_OUI_FROM_DATABASE=PHYSIOMETRIX,INC
-OUI:0013C7*
- ID_OUI_FROM_DATABASE=IONOS Co.,Ltd.
+OUI:0014AB*
+ ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd.
-OUI:0013C0*
- ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda.
+OUI:0014B0*
+ ID_OUI_FROM_DATABASE=Naeil Community
-OUI:0013B6*
- ID_OUI_FROM_DATABASE=Sling Media, Inc.
+OUI:0014B4*
+ ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd
-OUI:0013AF*
- ID_OUI_FROM_DATABASE=NUMA Technology,Inc.
+OUI:0014A9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:0013B0*
- ID_OUI_FROM_DATABASE=Jablotron
+OUI:001557*
+ ID_OUI_FROM_DATABASE=Olivetti
-OUI:0013AA*
- ID_OUI_FROM_DATABASE=ALS & TEC Ltd.
+OUI:00155C*
+ ID_OUI_FROM_DATABASE=Dresser Wayne
-OUI:0013A3*
- ID_OUI_FROM_DATABASE=Siemens Com CPE Devices
+OUI:00154B*
+ ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd
-OUI:00139E*
- ID_OUI_FROM_DATABASE=Ciara Technologies Inc.
+OUI:001550*
+ ID_OUI_FROM_DATABASE=Nits Technology Inc
-OUI:001502*
- ID_OUI_FROM_DATABASE=BETA tech
+OUI:001545*
+ ID_OUI_FROM_DATABASE=SEECODE Co., Ltd.
-OUI:001509*
- ID_OUI_FROM_DATABASE=Plus Technology Co., Ltd
+OUI:00153E*
+ ID_OUI_FROM_DATABASE=Q-Matic Sweden AB
-OUI:0014FD*
- ID_OUI_FROM_DATABASE=Thecus Technology Corp.
+OUI:001477*
+ ID_OUI_FROM_DATABASE=Nertec Inc.
-OUI:0014EF*
- ID_OUI_FROM_DATABASE=TZero Technologies, Inc.
+OUI:001472*
+ ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard Group
-OUI:0014F1*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001466*
+ ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH
-OUI:0014F0*
- ID_OUI_FROM_DATABASE=Business Security OL AB
+OUI:00146B*
+ ID_OUI_FROM_DATABASE=Anagran, Inc.
-OUI:0014EA*
- ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.)
+OUI:00145F*
+ ID_OUI_FROM_DATABASE=ADITEC CO. LTD
-OUI:0014E5*
- ID_OUI_FROM_DATABASE=Alticast
+OUI:001458*
+ ID_OUI_FROM_DATABASE=HS Automatic ApS
-OUI:001423*
- ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM
+OUI:001453*
+ ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES CO.,LTD
OUI:001419*
ID_OUI_FROM_DATABASE=SIDSA
OUI:0013F1*
ID_OUI_FROM_DATABASE=AMOD Technology Co., Ltd.
-OUI:0013F7*
- ID_OUI_FROM_DATABASE=SMC Networks, Inc.
+OUI:00135C*
+ ID_OUI_FROM_DATABASE=OnSite Systems, Inc.
-OUI:0013E7*
- ID_OUI_FROM_DATABASE=Halcro
+OUI:001355*
+ ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc.
-OUI:0013DB*
- ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd
+OUI:001356*
+ ID_OUI_FROM_DATABASE=FLIR Radiation Inc
-OUI:0013CC*
- ID_OUI_FROM_DATABASE=Tall Maple Systems
+OUI:001350*
+ ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc
-OUI:001283*
- ID_OUI_FROM_DATABASE=Nortel Networks
+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:00125A*
ID_OUI_FROM_DATABASE=Microsoft Corporation
-OUI:00125F*
- ID_OUI_FROM_DATABASE=AWIND Inc.
+OUI:0012FA*
+ ID_OUI_FROM_DATABASE=THX LTD
-OUI:001255*
- ID_OUI_FROM_DATABASE=NetEffect Incorporated
+OUI:001301*
+ ID_OUI_FROM_DATABASE=IronGate S.L.
-OUI:00124E*
- ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
+OUI:001307*
+ ID_OUI_FROM_DATABASE=Paravirtual Corporation
-OUI:001247*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
+OUI:0012F5*
+ ID_OUI_FROM_DATABASE=Imarda New Zealand Limited
-OUI:001248*
- ID_OUI_FROM_DATABASE=EMC Corporation (Kashya)
+OUI:0012EB*
+ ID_OUI_FROM_DATABASE=PDH Solutions, LLC
-OUI:001242*
- ID_OUI_FROM_DATABASE=Millennial Net
+OUI:0012DE*
+ ID_OUI_FROM_DATABASE=Radio Components Sweden AB
-OUI:001236*
- ID_OUI_FROM_DATABASE=ConSentry Networks
+OUI:0012DD*
+ ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd.
-OUI:00123B*
- ID_OUI_FROM_DATABASE=KeRo Systems ApS
+OUI:0012E4*
+ ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG
-OUI:001368*
- ID_OUI_FROM_DATABASE=Saab Danmark A/S
+OUI:0012D8*
+ ID_OUI_FROM_DATABASE=International Games System Co., Ltd.
-OUI:00135C*
- ID_OUI_FROM_DATABASE=OnSite Systems, Inc.
+OUI:0013B6*
+ ID_OUI_FROM_DATABASE=Sling Media, Inc.
-OUI:001355*
- ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc.
+OUI:0013AF*
+ ID_OUI_FROM_DATABASE=NUMA Technology,Inc.
-OUI:001356*
- ID_OUI_FROM_DATABASE=FLIR Radiation Inc
+OUI:0013B0*
+ ID_OUI_FROM_DATABASE=Jablotron
-OUI:001350*
- ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc
+OUI:0013AA*
+ ID_OUI_FROM_DATABASE=ALS & TEC Ltd.
-OUI:001344*
- ID_OUI_FROM_DATABASE=Fargo Electronics Inc.
+OUI:0013A3*
+ ID_OUI_FROM_DATABASE=Siemens Com CPE Devices
-OUI:001349*
- ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+OUI:00139E*
+ ID_OUI_FROM_DATABASE=Ciara Technologies Inc.
-OUI:001343*
- ID_OUI_FROM_DATABASE=Matsushita Electronic Components (Europe) GmbH
+OUI:00139D*
+ ID_OUI_FROM_DATABASE=Marvell Hispana S.L.
-OUI:00133D*
- ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co
+OUI:0012A8*
+ ID_OUI_FROM_DATABASE=intec GmbH
-OUI:001397*
- ID_OUI_FROM_DATABASE=Oracle Corporation
+OUI:0012A2*
+ ID_OUI_FROM_DATABASE=VITA
-OUI:00139D*
- ID_OUI_FROM_DATABASE=Marvell Hispana S.L.
+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:001363*
ID_OUI_FROM_DATABASE=Verascape, Inc.
-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:001368*
+ ID_OUI_FROM_DATABASE=Saab Danmark A/S
-OUI:0012DD*
- ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd.
+OUI:0013F7*
+ ID_OUI_FROM_DATABASE=SMC Networks, Inc.
-OUI:0012E4*
- ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG
+OUI:0013E7*
+ ID_OUI_FROM_DATABASE=Halcro
-OUI:0012AF*
- ID_OUI_FROM_DATABASE=ELPRO Technologies
+OUI:0013DB*
+ ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd
-OUI:0012A8*
- ID_OUI_FROM_DATABASE=intec GmbH
+OUI:0013CC*
+ ID_OUI_FROM_DATABASE=Tall Maple Systems
-OUI:0012A2*
- ID_OUI_FROM_DATABASE=VITA
+OUI:0013C7*
+ ID_OUI_FROM_DATABASE=IONOS Co.,Ltd.
-OUI:0012A1*
- ID_OUI_FROM_DATABASE=BluePacket Communications Co., Ltd.
+OUI:0013C0*
+ ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda.
-OUI:00129C*
- ID_OUI_FROM_DATABASE=Yulinet
+OUI:0012CB*
+ ID_OUI_FROM_DATABASE=CSS Inc.
-OUI:001290*
- ID_OUI_FROM_DATABASE=KYOWA Electric & Machinery Corp.
+OUI:0012C5*
+ ID_OUI_FROM_DATABASE=V-Show Technology (China) Co.,Ltd
-OUI:001295*
- ID_OUI_FROM_DATABASE=Aiware Inc.
+OUI:0012CC*
+ ID_OUI_FROM_DATABASE=Bitatek CO., LTD
-OUI:00132A*
- ID_OUI_FROM_DATABASE=Sitronics Telecom Solutions
+OUI:0012B4*
+ ID_OUI_FROM_DATABASE=Work Microwave GmbH
-OUI:001331*
- ID_OUI_FROM_DATABASE=CellPoint Connect
+OUI:0012BB*
+ ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee
-OUI:001336*
- ID_OUI_FROM_DATABASE=Tianjin 712 Communication Broadcasting co., ltd.
+OUI:0012AF*
+ ID_OUI_FROM_DATABASE=ELPRO Technologies
OUI:001324*
ID_OUI_FROM_DATABASE=Schneider Electric Ultra Terminal
OUI:001308*
ID_OUI_FROM_DATABASE=Nuvera Fuel Cells
-OUI:00122F*
- ID_OUI_FROM_DATABASE=Sanei Electric Inc.
+OUI:001181*
+ ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd,
-OUI:001235*
- ID_OUI_FROM_DATABASE=Andrew Corporation
+OUI:00117B*
+ ID_OUI_FROM_DATABASE=Büchi Labortechnik AG
-OUI:00122B*
- ID_OUI_FROM_DATABASE=Virbiage Pty Ltd
+OUI:00116F*
+ ID_OUI_FROM_DATABASE=Netforyou Co., LTD.
-OUI:001212*
- ID_OUI_FROM_DATABASE=PLUS Corporation
+OUI:001168*
+ ID_OUI_FROM_DATABASE=HomeLogic LLC
-OUI:001219*
- ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc
+OUI:00115E*
+ ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH
-OUI:0012D8*
- ID_OUI_FROM_DATABASE=International Games System Co., Ltd.
+OUI:001157*
+ ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd.
-OUI:0012CB*
- ID_OUI_FROM_DATABASE=CSS Inc.
+OUI:001158*
+ ID_OUI_FROM_DATABASE=Nortel Networks
-OUI:0012C5*
- ID_OUI_FROM_DATABASE=V-Show Technology (China) Co.,Ltd
+OUI:001152*
+ ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS
-OUI:0012CC*
- ID_OUI_FROM_DATABASE=Bitatek CO., LTD
+OUI:0011A4*
+ ID_OUI_FROM_DATABASE=JStream Technologies Inc.
-OUI:0012B4*
- ID_OUI_FROM_DATABASE=Work Microwave GmbH
+OUI:001198*
+ ID_OUI_FROM_DATABASE=Prism Media Products Limited
-OUI:0012BB*
- ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee
+OUI:00119D*
+ ID_OUI_FROM_DATABASE=Diginfo Technology Corporation
-OUI:001206*
- ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd
+OUI:00119E*
+ ID_OUI_FROM_DATABASE=Solectron Brazil
-OUI:00120B*
- ID_OUI_FROM_DATABASE=Chinasys Technologies Limited
+OUI:00118E*
+ ID_OUI_FROM_DATABASE=Halytech Mace
-OUI:00120C*
- ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd
+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:0011E9*
ID_OUI_FROM_DATABASE=STARNEX CO., LTD.
-OUI:001187*
- ID_OUI_FROM_DATABASE=Category Solutions, Inc
-
-OUI:001182*
- ID_OUI_FROM_DATABASE=IMI Norgren Ltd
-
-OUI:001181*
- ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd,
-
-OUI:00117B*
- ID_OUI_FROM_DATABASE=Büchi Labortechnik AG
-
-OUI:001174*
- ID_OUI_FROM_DATABASE=Wibhu Technologies, Inc.
-
-OUI:00116F*
- ID_OUI_FROM_DATABASE=Netforyou Co., LTD.
-
-OUI:001168*
- ID_OUI_FROM_DATABASE=HomeLogic LLC
+OUI:0011DD*
+ ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd.
-OUI:00115E*
- ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH
+OUI:0011E2*
+ ID_OUI_FROM_DATABASE=Hua Jung Components Co., Ltd.
-OUI:001157*
- ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd.
+OUI:000FFA*
+ ID_OUI_FROM_DATABASE=Optinel Systems, Inc.
-OUI:001158*
- ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:000FFF*
+ ID_OUI_FROM_DATABASE=Control4
-OUI:000FB2*
- ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd.
+OUI:000FF1*
+ ID_OUI_FROM_DATABASE=nex-G Systems Pte.Ltd
-OUI:000FA5*
- ID_OUI_FROM_DATABASE=BWA Technology GmbH
+OUI:000FE4*
+ ID_OUI_FROM_DATABASE=Pantech Co.,Ltd
-OUI:000FB1*
- ID_OUI_FROM_DATABASE=Cognio Inc.
+OUI:000FEA*
+ ID_OUI_FROM_DATABASE=Giga-Byte Technology Co.,LTD.
-OUI:000FAC*
- ID_OUI_FROM_DATABASE=IEEE 802.11
+OUI:000FE3*
+ ID_OUI_FROM_DATABASE=Damm Cellular Systems A/S
-OUI:000F9C*
- ID_OUI_FROM_DATABASE=Panduit Corp
+OUI:000FD7*
+ ID_OUI_FROM_DATABASE=Harman Music Group
-OUI:000FA0*
- ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC.
+OUI:001235*
+ ID_OUI_FROM_DATABASE=Andrew Corporation
-OUI:000F97*
- ID_OUI_FROM_DATABASE=Avanex Corporation
+OUI:00122B*
+ ID_OUI_FROM_DATABASE=Virbiage Pty Ltd
-OUI:000F8A*
- ID_OUI_FROM_DATABASE=WideView
+OUI:001212*
+ ID_OUI_FROM_DATABASE=PLUS Corporation
-OUI:000F89*
- ID_OUI_FROM_DATABASE=Winnertec System Co., Ltd.
+OUI:001219*
+ ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc
-OUI:000F90*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001206*
+ ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd
-OUI:000FD7*
- ID_OUI_FROM_DATABASE=Harman Music Group
+OUI:00120B*
+ ID_OUI_FROM_DATABASE=Chinasys Technologies Limited
-OUI:000FD1*
- ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc.
+OUI:00120C*
+ ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd
-OUI:000FD2*
- ID_OUI_FROM_DATABASE=EWA Technologies, Inc.
+OUI:001130*
+ ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd.
-OUI:000FC4*
- ID_OUI_FROM_DATABASE=NST co.,LTD.
+OUI:00111E*
+ ID_OUI_FROM_DATABASE=EPSG (Ethernet Powerlink Standardization Group)
-OUI:000FCB*
- ID_OUI_FROM_DATABASE=3Com Ltd
+OUI:00111F*
+ ID_OUI_FROM_DATABASE=Doremi Labs, Inc.
-OUI:000FBF*
- ID_OUI_FROM_DATABASE=DGT Sp. z o.o.
+OUI:001112*
+ ID_OUI_FROM_DATABASE=Honeywell CMSS
-OUI:000FB8*
- ID_OUI_FROM_DATABASE=CallURL Inc.
+OUI:001118*
+ ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd.
-OUI:0011DD*
- ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd.
+OUI:001105*
+ ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd.
-OUI:0011E2*
- ID_OUI_FROM_DATABASE=Hua Jung Components 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:0011BD*
ID_OUI_FROM_DATABASE=Bombardier Transportation
-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: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:0011AB*
ID_OUI_FROM_DATABASE=TRUSTABLE TECHNOLOGY CO.,LTD.
OUI:0011B0*
ID_OUI_FROM_DATABASE=Fortelink Inc.
-OUI:0011A4*
- ID_OUI_FROM_DATABASE=JStream Technologies Inc.
+OUI:00125F*
+ ID_OUI_FROM_DATABASE=AWIND Inc.
-OUI:001198*
- ID_OUI_FROM_DATABASE=Prism Media Products Limited
+OUI:001255*
+ ID_OUI_FROM_DATABASE=NetEffect Incorporated
-OUI:00119D*
- ID_OUI_FROM_DATABASE=Diginfo Technology Corporation
+OUI:00124E*
+ ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
-OUI:00119E*
- ID_OUI_FROM_DATABASE=Solectron Brazil
+OUI:001247*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
-OUI:00118E*
- ID_OUI_FROM_DATABASE=Halytech Mace
+OUI:001248*
+ ID_OUI_FROM_DATABASE=EMC Corporation (Kashya)
-OUI:001193*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001242*
+ ID_OUI_FROM_DATABASE=Millennial Net
-OUI:001152*
- ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS
+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:00112C*
ID_OUI_FROM_DATABASE=IZT GmbH
-OUI:001130*
- ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd.
+OUI:000F77*
+ ID_OUI_FROM_DATABASE=DENTUM CO.,LTD
-OUI:00111E*
- ID_OUI_FROM_DATABASE=EPSG (Ethernet Powerlink Standardization Group)
+OUI:000F71*
+ ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd
-OUI:00111F*
- ID_OUI_FROM_DATABASE=Doremi Labs, Inc.
+OUI:000F78*
+ ID_OUI_FROM_DATABASE=Datacap Systems Inc
-OUI:001112*
- ID_OUI_FROM_DATABASE=Honeywell CMSS
+OUI:000F6A*
+ ID_OUI_FROM_DATABASE=Nortel Networks
-OUI:001118*
- ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd.
+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:000F2B*
ID_OUI_FROM_DATABASE=GREENBELL SYSTEMS
-OUI:000E98*
- ID_OUI_FROM_DATABASE=HME Clear-Com LTD.
-
OUI:000E93*
ID_OUI_FROM_DATABASE=Milénio 3 Sistemas Electrónicos, Lda.
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: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:000F77*
- ID_OUI_FROM_DATABASE=DENTUM CO.,LTD
+OUI:000FD1*
+ ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc.
-OUI:000F71*
- ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd
+OUI:000FD2*
+ ID_OUI_FROM_DATABASE=EWA Technologies, Inc.
-OUI:000F78*
- ID_OUI_FROM_DATABASE=Datacap Systems Inc
+OUI:000FC4*
+ ID_OUI_FROM_DATABASE=NST co.,LTD.
-OUI:000F6A*
- ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:000FCB*
+ ID_OUI_FROM_DATABASE=3Com Ltd
-OUI:000F65*
- ID_OUI_FROM_DATABASE=icube Corp.
+OUI:000FBF*
+ ID_OUI_FROM_DATABASE=DGT Sp. z o.o.
-OUI:000F5E*
- ID_OUI_FROM_DATABASE=Veo
+OUI:000FB8*
+ ID_OUI_FROM_DATABASE=CallURL Inc.
-OUI:000E71*
- ID_OUI_FROM_DATABASE=Gemstar Technology Development Ltd.
+OUI:000FB2*
+ ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd.
-OUI:000E6C*
- ID_OUI_FROM_DATABASE=Device Drivers Limited
+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:000E3F*
ID_OUI_FROM_DATABASE=Soronti, Inc.
-OUI:000EC5*
- ID_OUI_FROM_DATABASE=Digital Multitools Inc
-
-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:000E0A*
- ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE
-
-OUI:000E12*
- ID_OUI_FROM_DATABASE=Adaptive Micro Systems 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:000E03*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
-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:000EF9*
- ID_OUI_FROM_DATABASE=REA Elektronik GmbH
-
OUI:000EF2*
ID_OUI_FROM_DATABASE=Infinico Corporation
OUI:000ED6*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-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:000C7E*
- ID_OUI_FROM_DATABASE=Tellium Incorporated
-
-OUI:000C86*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000EC5*
+ ID_OUI_FROM_DATABASE=Digital Multitools Inc
-OUI:000C81*
- ID_OUI_FROM_DATABASE=Schneider Electric (Australia)
+OUI:000DB2*
+ ID_OUI_FROM_DATABASE=Ammasso, Inc.
-OUI:000C72*
- ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd.
+OUI:000DAD*
+ ID_OUI_FROM_DATABASE=Dataprobe, Inc.
-OUI:000C79*
- ID_OUI_FROM_DATABASE=Extel Communications P/L
+OUI:000D9E*
+ ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd.
-OUI:000C66*
- ID_OUI_FROM_DATABASE=Pronto Networks Inc
+OUI:000DA5*
+ ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc
-OUI:000C6B*
- ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH
+OUI:000D99*
+ ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group
-OUI:000C6D*
- ID_OUI_FROM_DATABASE=Edwards Ltd.
+OUI:000D8C*
+ ID_OUI_FROM_DATABASE=Shanghai Wedone Digital Ltd. CO.
-OUI:000DDF*
- ID_OUI_FROM_DATABASE=Japan Image & Network Inc.
+OUI:000D8B*
+ ID_OUI_FROM_DATABASE=T&D Corporation
-OUI:000DD2*
- ID_OUI_FROM_DATABASE=Simrad Optronics ASA
+OUI:000D85*
+ ID_OUI_FROM_DATABASE=Tapwave, Inc.
-OUI:000DD1*
- ID_OUI_FROM_DATABASE=Stryker Corporation
+OUI:000D86*
+ ID_OUI_FROM_DATABASE=Huber + Suhner AG
OUI:000DD8*
ID_OUI_FROM_DATABASE=BBN
OUI:000DB9*
ID_OUI_FROM_DATABASE=PC Engines GmbH
-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: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:000D4C*
+ ID_OUI_FROM_DATABASE=Outline Electronics Ltd.
-OUI:000D5F*
- ID_OUI_FROM_DATABASE=Minds Inc
+OUI:000D53*
+ ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp.
-OUI:000D66*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000D3F*
+ ID_OUI_FROM_DATABASE=VTI Instruments Corporation
-OUI:000CB1*
- ID_OUI_FROM_DATABASE=Salland Engineering (Europe) BV
+OUI:000D44*
+ ID_OUI_FROM_DATABASE=Audio BU - Logitech
-OUI:000CB7*
- ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd.
+OUI:000D38*
+ ID_OUI_FROM_DATABASE=NISSIN INC.
-OUI:000CBE*
- ID_OUI_FROM_DATABASE=Innominate Security Technologies AG
+OUI:000D32*
+ ID_OUI_FROM_DATABASE=DispenseSource, Inc.
-OUI:000CC3*
- ID_OUI_FROM_DATABASE=BeWAN systems
+OUI:000D31*
+ ID_OUI_FROM_DATABASE=Compellent Technologies, Inc.
-OUI:000CB2*
- ID_OUI_FROM_DATABASE=UNION co., ltd.
+OUI:000E04*
+ ID_OUI_FROM_DATABASE=CMA/Microdialysis AB
-OUI:000CA5*
- ID_OUI_FROM_DATABASE=Naman NZ LTd
+OUI:000DF7*
+ ID_OUI_FROM_DATABASE=Space Dynamics Lab
-OUI:000CAC*
- ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd.
+OUI:000DFE*
+ ID_OUI_FROM_DATABASE=Hauppauge Computer Works, Inc.
-OUI:000C94*
- ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI)
+OUI:000DF1*
+ ID_OUI_FROM_DATABASE=IONIX INC.
-OUI:000C99*
- ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd
+OUI:000DEB*
+ ID_OUI_FROM_DATABASE=CompXs Limited
-OUI:000CA0*
- ID_OUI_FROM_DATABASE=StorCase Technology, Inc.
+OUI:000DF2*
+ ID_OUI_FROM_DATABASE=Private
-OUI:000C8D*
- ID_OUI_FROM_DATABASE=MATRIX VISION GmbH
+OUI:000DE4*
+ ID_OUI_FROM_DATABASE=DIGINICS, Inc.
-OUI:000C92*
- ID_OUI_FROM_DATABASE=WolfVision Gmbh
+OUI:000DDF*
+ ID_OUI_FROM_DATABASE=Japan Image & Network Inc.
-OUI:000D32*
- ID_OUI_FROM_DATABASE=DispenseSource, Inc.
+OUI:000DD2*
+ ID_OUI_FROM_DATABASE=Simrad Optronics ASA
-OUI:000D31*
- ID_OUI_FROM_DATABASE=Compellent Technologies, Inc.
+OUI:000DD1*
+ ID_OUI_FROM_DATABASE=Stryker Corporation
OUI:000D2C*
ID_OUI_FROM_DATABASE=Patapsco Designs Ltd
OUI:000D12*
ID_OUI_FROM_DATABASE=AXELL Corporation
-OUI:000DB2*
- ID_OUI_FROM_DATABASE=Ammasso, Inc.
+OUI:000D00*
+ ID_OUI_FROM_DATABASE=Seaway Networks Inc.
-OUI:000DAD*
- ID_OUI_FROM_DATABASE=Dataprobe, Inc.
+OUI:000D06*
+ ID_OUI_FROM_DATABASE=Compulogic Limited
-OUI:000D9E*
- ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd.
+OUI:000CD1*
+ ID_OUI_FROM_DATABASE=SFOM Technology Corp.
-OUI:000DA5*
- ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc
+OUI:000CD6*
+ ID_OUI_FROM_DATABASE=PARTNER TECH
-OUI:000D99*
- ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group
+OUI:000CDD*
+ ID_OUI_FROM_DATABASE=AOS technologies AG
-OUI:000D58*
+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:000D4C*
- ID_OUI_FROM_DATABASE=Outline Electronics Ltd.
+OUI:000E1E*
+ ID_OUI_FROM_DATABASE=QLogic Corporation
-OUI:000D53*
- ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp.
+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:000D3F*
- ID_OUI_FROM_DATABASE=VTI Instruments Corporation
+OUI:000E0E*
+ ID_OUI_FROM_DATABASE=ESA elettronica S.P.A.
-OUI:000D44*
- ID_OUI_FROM_DATABASE=Audio BU - Logitech
+OUI:000E0A*
+ ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE
-OUI:000D38*
- ID_OUI_FROM_DATABASE=NISSIN INC.
+OUI:000E12*
+ ID_OUI_FROM_DATABASE=Adaptive Micro Systems Inc.
-OUI:000CD1*
- ID_OUI_FROM_DATABASE=SFOM Technology Corp.
+OUI:000D7E*
+ ID_OUI_FROM_DATABASE=Axiowave Networks, Inc.
-OUI:000CD6*
- ID_OUI_FROM_DATABASE=PARTNER TECH
+OUI:000D78*
+ ID_OUI_FROM_DATABASE=Engineering & Security
-OUI:000CDD*
- ID_OUI_FROM_DATABASE=AOS technologies AG
+OUI:000D77*
+ ID_OUI_FROM_DATABASE=FalconStor Software
-OUI:000CCA*
- ID_OUI_FROM_DATABASE=HGST a Western Digital Company
+OUI:000D6B*
+ ID_OUI_FROM_DATABASE=Mita-Teknik A/S
-OUI:000CC4*
- ID_OUI_FROM_DATABASE=Tiptel AG
+OUI:000D65*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:000D00*
- ID_OUI_FROM_DATABASE=Seaway Networks Inc.
+OUI:000D5F*
+ ID_OUI_FROM_DATABASE=Minds Inc
-OUI:000D06*
- ID_OUI_FROM_DATABASE=Compulogic Limited
+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:000CE3*
ID_OUI_FROM_DATABASE=Option International N.V.
-OUI:000B01*
- ID_OUI_FROM_DATABASE=DAIICHI ELECTRONICS CO., LTD.
-
-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:000B5E*
- ID_OUI_FROM_DATABASE=Audio Engineering Society Inc.
-
-OUI:000B63*
- ID_OUI_FROM_DATABASE=Kaleidescape
-
-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:000B95*
- ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd
-
OUI:000B8F*
ID_OUI_FROM_DATABASE=AKITA ELECTRONICS SYSTEMS CO.,LTD.
OUI:000B76*
ID_OUI_FROM_DATABASE=ET&T Technology Co. Ltd.
-OUI:000AC1*
- ID_OUI_FROM_DATABASE=Futuretel
+OUI:000B5E*
+ ID_OUI_FROM_DATABASE=Audio Engineering Society Inc.
-OUI:000AC6*
- ID_OUI_FROM_DATABASE=Overture Networks.
+OUI:000B63*
+ ID_OUI_FROM_DATABASE=Kaleidescape
-OUI:000AAE*
- ID_OUI_FROM_DATABASE=Rosemount Process Analytical
+OUI:000C7E*
+ ID_OUI_FROM_DATABASE=Tellium Incorporated
-OUI:000AB3*
- ID_OUI_FROM_DATABASE=Fa. GIRA
+OUI:000C86*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:000AB5*
- ID_OUI_FROM_DATABASE=Digital Electronic Network
+OUI:000C81*
+ ID_OUI_FROM_DATABASE=Schneider Electric (Australia)
-OUI:000ABA*
- ID_OUI_FROM_DATABASE=Arcon Technology Limited
+OUI:000C72*
+ ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd.
-OUI:000AA2*
- ID_OUI_FROM_DATABASE=SYSTEK INC.
+OUI:000C79*
+ ID_OUI_FROM_DATABASE=Extel Communications P/L
-OUI:000AA7*
- ID_OUI_FROM_DATABASE=FEI Electron Optics
+OUI:000C66*
+ ID_OUI_FROM_DATABASE=Pronto Networks Inc
-OUI:000A8F*
- ID_OUI_FROM_DATABASE=Aska International Inc.
+OUI:000C6B*
+ ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH
-OUI:000A94*
- ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD
+OUI:000C6D*
+ ID_OUI_FROM_DATABASE=Edwards Ltd.
OUI:000C4E*
ID_OUI_FROM_DATABASE=Winbest Technology CO,LT
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:000C09*
ID_OUI_FROM_DATABASE=Hitachi IE Systems Co., Ltd
-OUI:000BD3*
- ID_OUI_FROM_DATABASE=cd3o
+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:000B9E*
ID_OUI_FROM_DATABASE=Yasing Technology Corp.
-OUI:000B27*
- ID_OUI_FROM_DATABASE=Scion Corporation
-
-OUI:000B2E*
- ID_OUI_FROM_DATABASE=Cal-Comp Electronics (Thailand) Public Company Limited Taipe
+OUI:000B95*
+ ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd
-OUI:000B1B*
- ID_OUI_FROM_DATABASE=Systronix, Inc.
+OUI:000CB7*
+ ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd.
-OUI:000B20*
- ID_OUI_FROM_DATABASE=Hirata corporation
+OUI:000CBE*
+ ID_OUI_FROM_DATABASE=Innominate Security Technologies AG
-OUI:000B22*
- ID_OUI_FROM_DATABASE=Environmental Systems and Services
+OUI:000CC3*
+ ID_OUI_FROM_DATABASE=BeWAN systems
-OUI:000B14*
- ID_OUI_FROM_DATABASE=ViewSonic Corporation
+OUI:000CB2*
+ ID_OUI_FROM_DATABASE=UNION co., ltd.
-OUI:000B0D*
- ID_OUI_FROM_DATABASE=Air2U, Inc.
+OUI:000CA5*
+ ID_OUI_FROM_DATABASE=Naman NZ LTd
-OUI:000B0F*
- ID_OUI_FROM_DATABASE=Bosch Rexroth
+OUI:000CAC*
+ ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd.
-OUI:000B08*
- ID_OUI_FROM_DATABASE=Pillar Data Systems
+OUI:000C94*
+ ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI)
-OUI:000AFC*
- ID_OUI_FROM_DATABASE=Core Tec Communications, LLC
+OUI:000C99*
+ ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd
-OUI:000BF6*
- ID_OUI_FROM_DATABASE=Nitgen Co., Ltd
+OUI:000CA0*
+ ID_OUI_FROM_DATABASE=StorCase Technology, Inc.
-OUI:000BFB*
- ID_OUI_FROM_DATABASE=D-NET International Corporation
+OUI:000C8D*
+ ID_OUI_FROM_DATABASE=MATRIX VISION GmbH
-OUI:000C02*
- ID_OUI_FROM_DATABASE=ABB Oy
+OUI:000C92*
+ ID_OUI_FROM_DATABASE=WolfVision Gmbh
OUI:000BEA*
ID_OUI_FROM_DATABASE=Zultys Technologies
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:000962*
ID_OUI_FROM_DATABASE=Sonitor Technologies AS
-OUI:000A9B*
- ID_OUI_FROM_DATABASE=TB Group Inc
+OUI:000967*
+ ID_OUI_FROM_DATABASE=Tachyon, Inc
-OUI:000A9A*
- ID_OUI_FROM_DATABASE=Aiptek International 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:000A68*
ID_OUI_FROM_DATABASE=SolarFlare Communications, Inc.
-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:0009ED*
- ID_OUI_FROM_DATABASE=CipherOptics
-
-OUI:0009F2*
- ID_OUI_FROM_DATABASE=Cohu, Inc., Electronics Division
+OUI:000A5C*
+ ID_OUI_FROM_DATABASE=Carel s.p.a.
OUI:0009E6*
ID_OUI_FROM_DATABASE=Cyber Switching Inc.
OUI:0009D3*
ID_OUI_FROM_DATABASE=Western DataCom Co., Inc.
-OUI:000901*
- ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co
-
-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:000967*
- ID_OUI_FROM_DATABASE=Tachyon, Inc
-
-OUI:00096E*
- ID_OUI_FROM_DATABASE=GIANT ELECTRONICS LTD.
-
-OUI:00095E*
- ID_OUI_FROM_DATABASE=Masstech Group Inc.
+OUI:000AAE*
+ ID_OUI_FROM_DATABASE=Rosemount Process Analytical
-OUI:000959*
- ID_OUI_FROM_DATABASE=Sitecsoft
+OUI:000AB3*
+ ID_OUI_FROM_DATABASE=Fa. GIRA
-OUI:00094D*
- ID_OUI_FROM_DATABASE=Braintree Communications Pty Ltd
+OUI:000AB5*
+ ID_OUI_FROM_DATABASE=Digital Electronic Network
-OUI:000952*
- ID_OUI_FROM_DATABASE=Auerswald GmbH & Co. KG
+OUI:000ABA*
+ ID_OUI_FROM_DATABASE=Arcon Technology Limited
-OUI:000946*
- ID_OUI_FROM_DATABASE=Cluster Labs GmbH
+OUI:000AA2*
+ ID_OUI_FROM_DATABASE=SYSTEK INC.
-OUI:000940*
- ID_OUI_FROM_DATABASE=AGFEO GmbH & Co. KG
+OUI:000AA7*
+ ID_OUI_FROM_DATABASE=FEI Electron Optics
-OUI:00093F*
- ID_OUI_FROM_DATABASE=Double-Win Enterpirse CO., LTD
+OUI:000A8F*
+ ID_OUI_FROM_DATABASE=Aska International Inc.
-OUI:00093A*
- ID_OUI_FROM_DATABASE=Molex Fiber Optics
+OUI:000A94*
+ ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD
-OUI:000933*
- ID_OUI_FROM_DATABASE=Ophit Co.Ltd.
+OUI:000A9B*
+ ID_OUI_FROM_DATABASE=TB Group Inc
-OUI:000A5C*
- ID_OUI_FROM_DATABASE=Carel s.p.a.
+OUI:000A9A*
+ ID_OUI_FROM_DATABASE=Aiptek International Inc
OUI:000A50*
ID_OUI_FROM_DATABASE=REMOTEK CORPORATION
OUI:000A2F*
ID_OUI_FROM_DATABASE=Artnix Inc.
-OUI:000927*
- ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD.
+OUI:000A20*
+ ID_OUI_FROM_DATABASE=SVA Networks, Inc.
-OUI:00092E*
- ID_OUI_FROM_DATABASE=B&Tech System Inc.
+OUI:000A25*
+ ID_OUI_FROM_DATABASE=CERAGON NETWORKS
-OUI:000920*
- ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD.
+OUI:000A14*
+ ID_OUI_FROM_DATABASE=TECO a.s.
-OUI:00091B*
- ID_OUI_FROM_DATABASE=Digital Generation Inc.
+OUI:000A19*
+ ID_OUI_FROM_DATABASE=Valere Power, Inc.
-OUI:000914*
- ID_OUI_FROM_DATABASE=COMPUTROLS 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:00090E*
- ID_OUI_FROM_DATABASE=Helix Technology Inc.
+OUI:00072C*
+ ID_OUI_FROM_DATABASE=Fabricom
-OUI:000908*
- ID_OUI_FROM_DATABASE=VTech Technology Corp.
+OUI:000733*
+ ID_OUI_FROM_DATABASE=DANCONTROL Engineering
-OUI:00090D*
- ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP.
+OUI:000732*
+ ID_OUI_FROM_DATABASE=AAEON Technology Inc.
-OUI:000A20*
- ID_OUI_FROM_DATABASE=SVA Networks, Inc.
+OUI:000716*
+ ID_OUI_FROM_DATABASE=J & S Marine Ltd.
-OUI:000A25*
- ID_OUI_FROM_DATABASE=CERAGON NETWORKS
+OUI:00071B*
+ ID_OUI_FROM_DATABASE=CDVI Americas Ltd
-OUI:000A14*
- ID_OUI_FROM_DATABASE=TECO a.s.
+OUI:000722*
+ ID_OUI_FROM_DATABASE=The Nielsen Company
-OUI:000A19*
- ID_OUI_FROM_DATABASE=Valere Power, Inc.
+OUI:00071C*
+ ID_OUI_FROM_DATABASE=AT&T Fixed Wireless Services
-OUI:000A0D*
- ID_OUI_FROM_DATABASE=FCI Deutschland GmbH
+OUI:00070A*
+ ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd.
-OUI:000A12*
- ID_OUI_FROM_DATABASE=Azylex Technology, Inc
+OUI:00070F*
+ ID_OUI_FROM_DATABASE=Fujant, Inc.
-OUI:0009F9*
- ID_OUI_FROM_DATABASE=ART JAPAN CO., LTD.
+OUI:000709*
+ ID_OUI_FROM_DATABASE=Westerstrand Urfabrik AB
-OUI:0009FC*
- ID_OUI_FROM_DATABASE=IPFLEX Inc.
+OUI:000702*
+ ID_OUI_FROM_DATABASE=Varian Medical Systems
-OUI:000A03*
- ID_OUI_FROM_DATABASE=ENDESA SERVICIOS, S.L.
+OUI:0006F3*
+ ID_OUI_FROM_DATABASE=AcceLight Networks
OUI:0006F4*
ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc.
OUI:0006FD*
ID_OUI_FROM_DATABASE=Comjet Information Systems Corp.
-OUI:0006E7*
- ID_OUI_FROM_DATABASE=Bit Blitz Communications Inc.
+OUI:00082D*
+ ID_OUI_FROM_DATABASE=Indus Teqsite Private Limited
-OUI:0006ED*
- ID_OUI_FROM_DATABASE=Inara Networks
+OUI:000821*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:0006DC*
- ID_OUI_FROM_DATABASE=Syabas Technology (Amquest)
+OUI:000814*
+ ID_OUI_FROM_DATABASE=TIL Technologies
-OUI:0006E1*
- ID_OUI_FROM_DATABASE=Techno Trade s.a
+OUI:00081A*
+ ID_OUI_FROM_DATABASE=Sanrad Intelligence Storage Communications (2000) Ltd.
-OUI:0006E6*
- ID_OUI_FROM_DATABASE=DongYang Telecom Co., Ltd.
+OUI:00080F*
+ ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB
-OUI:0006CF*
- ID_OUI_FROM_DATABASE=Thales Avionics In-Flight Systems, LLC
+OUI:000809*
+ ID_OUI_FROM_DATABASE=Systemonic AG
-OUI:0006D6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000803*
+ ID_OUI_FROM_DATABASE=Cos Tron
-OUI:0006D5*
- ID_OUI_FROM_DATABASE=Diamond Systems Corp.
+OUI:0007FF*
+ ID_OUI_FROM_DATABASE=Gluon Networks
-OUI:0006C9*
- ID_OUI_FROM_DATABASE=Technical Marketing Research, Inc.
+OUI:0007F9*
+ ID_OUI_FROM_DATABASE=Sensaphone
-OUI:0007B1*
- ID_OUI_FROM_DATABASE=Equator Technologies
+OUI:0007F3*
+ ID_OUI_FROM_DATABASE=Thinkengine Networks
-OUI:0007B8*
- ID_OUI_FROM_DATABASE=Corvalent Corporation
+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:00077B*
ID_OUI_FROM_DATABASE=Millimetrix Broadband Networks
-OUI:000856*
- ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd.
-
-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:000894*
- ID_OUI_FROM_DATABASE=InnoVISION Multimedia Ltd.
+OUI:00077E*
+ ID_OUI_FROM_DATABASE=Elrest GmbH
-OUI:00088F*
- ID_OUI_FROM_DATABASE=ADVANCED DIGITAL TECHNOLOGY
+OUI:00076F*
+ ID_OUI_FROM_DATABASE=Synoptics Limited
OUI:000888*
ID_OUI_FROM_DATABASE=OULLIM Information Technology Inc,.
OUI:000850*
ID_OUI_FROM_DATABASE=Arizona Instrument Corp.
-OUI:000738*
- ID_OUI_FROM_DATABASE=Young Technology Co., Ltd.
-
-OUI:00073F*
- ID_OUI_FROM_DATABASE=Woojyun Systec 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:0006C3*
- ID_OUI_FROM_DATABASE=Schindler Elevator Ltd.
-
-OUI:0006C8*
- ID_OUI_FROM_DATABASE=Sumitomo Metal Micro Devices, 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:000856*
+ ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd.
-OUI:0006AC*
- ID_OUI_FROM_DATABASE=Intersoft Co.
+OUI:000927*
+ ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD.
-OUI:0006A6*
- ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd
+OUI:00092E*
+ ID_OUI_FROM_DATABASE=B&Tech System Inc.
-OUI:0006A2*
- ID_OUI_FROM_DATABASE=Microtune, Inc.
+OUI:000920*
+ ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD.
-OUI:000695*
- ID_OUI_FROM_DATABASE=Ensure Technologies, Inc.
+OUI:00091B*
+ ID_OUI_FROM_DATABASE=Digital Generation Inc.
-OUI:00069C*
- ID_OUI_FROM_DATABASE=Transmode Systems AB
+OUI:000914*
+ ID_OUI_FROM_DATABASE=COMPUTROLS INC.
-OUI:000696*
- ID_OUI_FROM_DATABASE=Advent Networks
+OUI:00090E*
+ ID_OUI_FROM_DATABASE=Helix Technology Inc.
-OUI:0007F3*
- ID_OUI_FROM_DATABASE=Thinkengine Networks
+OUI:000908*
+ ID_OUI_FROM_DATABASE=VTech Technology Corp.
-OUI:0007EC*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00090D*
+ ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP.
-OUI:0007F2*
- ID_OUI_FROM_DATABASE=IOA Corporation
+OUI:000901*
+ ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co
OUI:0007E6*
ID_OUI_FROM_DATABASE=edgeflow Canada Inc.
OUI:0007BE*
ID_OUI_FROM_DATABASE=DataLogic SpA
-OUI:00077E*
- ID_OUI_FROM_DATABASE=Elrest GmbH
+OUI:0007B1*
+ ID_OUI_FROM_DATABASE=Equator Technologies
-OUI:00076F*
- ID_OUI_FROM_DATABASE=Synoptics Limited
+OUI:0007B8*
+ ID_OUI_FROM_DATABASE=Corvalent Corporation
OUI:00076E*
ID_OUI_FROM_DATABASE=Sinetica Corporation Limited
OUI:000745*
ID_OUI_FROM_DATABASE=Radlan Computer Communications Ltd.
-OUI:0008C2*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+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:00089C*
ID_OUI_FROM_DATABASE=Elecs Industry Co., Ltd.
-OUI:000690*
- ID_OUI_FROM_DATABASE=Euracom Communication GmbH
+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:00065C*
ID_OUI_FROM_DATABASE=Malachite Technologies, Inc.
-OUI:000610*
- ID_OUI_FROM_DATABASE=Abeona Networks Inc
+OUI:000650*
+ ID_OUI_FROM_DATABASE=Tiburon Networks, Inc.
-OUI:000616*
- ID_OUI_FROM_DATABASE=Tel Net Co., Ltd.
+OUI:000656*
+ ID_OUI_FROM_DATABASE=Tactel AB
OUI:00060A*
ID_OUI_FROM_DATABASE=Blue2space
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:0005AC*
ID_OUI_FROM_DATABASE=Northern Digital, Inc.
-OUI:0004E5*
- ID_OUI_FROM_DATABASE=Glonet Systems, Inc.
-
-OUI:0004D9*
- ID_OUI_FROM_DATABASE=Titan Electronics, 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:0004C6*
- ID_OUI_FROM_DATABASE=Yamaha Motor Co., Ltd.
-
-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:000589*
+ ID_OUI_FROM_DATABASE=National Datacomputer
-OUI:0004A0*
- ID_OUI_FROM_DATABASE=Verity Instruments, Inc.
+OUI:000595*
+ ID_OUI_FROM_DATABASE=Alesis Corporation
-OUI:00050C*
- ID_OUI_FROM_DATABASE=Network Photonics, Inc.
+OUI:00058F*
+ ID_OUI_FROM_DATABASE=CLCsoft co.
-OUI:000512*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:000596*
+ ID_OUI_FROM_DATABASE=Genotech Co., Ltd.
OUI:000506*
ID_OUI_FROM_DATABASE=Reddo Networks AB
OUI:0004DF*
ID_OUI_FROM_DATABASE=Teracom Telematica Ltda.
-OUI:000553*
- ID_OUI_FROM_DATABASE=DVC Company, Inc.
+OUI:0004E5*
+ ID_OUI_FROM_DATABASE=Glonet Systems, Inc.
-OUI:000548*
- ID_OUI_FROM_DATABASE=Disco Corporation
+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:000516*
ID_OUI_FROM_DATABASE=SMART Modular Technologies
-OUI:000650*
- ID_OUI_FROM_DATABASE=Tiburon Networks, Inc.
-
-OUI:000656*
- ID_OUI_FROM_DATABASE=Tactel AB
-
-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:00050C*
+ ID_OUI_FROM_DATABASE=Network Photonics, Inc.
-OUI:00064A*
- ID_OUI_FROM_DATABASE=Honeywell Co., Ltd. (KOREA)
+OUI:000512*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Inc
-OUI:00063F*
- ID_OUI_FROM_DATABASE=Everex Communications Inc.
+OUI:0006BF*
+ ID_OUI_FROM_DATABASE=Accella Technologies Co., Ltd.
-OUI:000639*
- ID_OUI_FROM_DATABASE=Newtec
+OUI:0006B9*
+ ID_OUI_FROM_DATABASE=A5TEK Corp.
-OUI:000633*
- ID_OUI_FROM_DATABASE=Cross Match Technologies GmbH
+OUI:0006B2*
+ ID_OUI_FROM_DATABASE=Linxtek Co.
-OUI:000626*
- ID_OUI_FROM_DATABASE=MWE GmbH
+OUI:0006AC*
+ ID_OUI_FROM_DATABASE=Intersoft Co.
-OUI:00061D*
- ID_OUI_FROM_DATABASE=MIP Telecom, Inc.
+OUI:0006A6*
+ ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd
-OUI:000623*
- ID_OUI_FROM_DATABASE=MGE UPS Systems France
+OUI:0006A2*
+ ID_OUI_FROM_DATABASE=Microtune, Inc.
-OUI:000589*
- ID_OUI_FROM_DATABASE=National Datacomputer
+OUI:000695*
+ ID_OUI_FROM_DATABASE=Ensure Technologies, Inc.
-OUI:000595*
- ID_OUI_FROM_DATABASE=Alesis Corporation
+OUI:00069C*
+ ID_OUI_FROM_DATABASE=Transmode Systems AB
-OUI:00058F*
- ID_OUI_FROM_DATABASE=CLCsoft co.
+OUI:000696*
+ ID_OUI_FROM_DATABASE=Advent Networks
-OUI:000596*
- ID_OUI_FROM_DATABASE=Genotech Co., Ltd.
+OUI:000690*
+ ID_OUI_FROM_DATABASE=Euracom Communication GmbH
OUI:00057D*
ID_OUI_FROM_DATABASE=Sun Communications, Inc.
OUI:000560*
ID_OUI_FROM_DATABASE=LEADER COMM.CO., LTD
-OUI:000559*
- ID_OUI_FROM_DATABASE=Intracom S.A.
-
-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:000559*
+ ID_OUI_FROM_DATABASE=Intracom S.A.
-OUI:0003D9*
- ID_OUI_FROM_DATABASE=Secheron SA
+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: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:00036D*
ID_OUI_FROM_DATABASE=Runtop, Inc.
-OUI:0002E3*
- ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc.
+OUI:000361*
+ ID_OUI_FROM_DATABASE=Widcomm, Inc.
OUI:0002DE*
ID_OUI_FROM_DATABASE=Astrodesign, Inc.
OUI:0002AA*
ID_OUI_FROM_DATABASE=PLcom Co., Ltd.
-OUI:00045B*
- ID_OUI_FROM_DATABASE=Techsan Electronics Co., Ltd.
-
-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:000361*
- ID_OUI_FROM_DATABASE=Widcomm, Inc.
+OUI:0002A3*
+ ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems
OUI:00035A*
ID_OUI_FROM_DATABASE=Photron Limited
OUI:0002EA*
ID_OUI_FROM_DATABASE=Focus Enhancements
-OUI:000269*
- ID_OUI_FROM_DATABASE=Nadatel Co., Ltd
+OUI:0002E3*
+ ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc.
-OUI:000265*
- ID_OUI_FROM_DATABASE=Virditech Co. Ltd.
+OUI:0004D3*
+ ID_OUI_FROM_DATABASE=Toyokeiki Co., Ltd.
-OUI:00025E*
- ID_OUI_FROM_DATABASE=High Technology Ltd
+OUI:0004CC*
+ ID_OUI_FROM_DATABASE=Peek Traffic B.V.
-OUI:000261*
- ID_OUI_FROM_DATABASE=Tilgin AB
+OUI:0004C0*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:000259*
- ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group
+OUI:0004B9*
+ ID_OUI_FROM_DATABASE=S.I. Soubou, Inc.
-OUI:000255*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0004BA*
+ ID_OUI_FROM_DATABASE=KDD Media Will Corporation
-OUI:000249*
- ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd.
+OUI:0004AF*
+ ID_OUI_FROM_DATABASE=Digital Fountain, Inc.
-OUI:000250*
- ID_OUI_FROM_DATABASE=Geyser Networks, Inc.
+OUI:0004B4*
+ ID_OUI_FROM_DATABASE=CIAC
-OUI:000242*
- ID_OUI_FROM_DATABASE=Videoframe Systems
+OUI:0004B3*
+ ID_OUI_FROM_DATABASE=Videotek, Inc.
-OUI:000244*
- ID_OUI_FROM_DATABASE=SURECOM Technology Co.
+OUI:0004A6*
+ ID_OUI_FROM_DATABASE=SAF Tehnika Ltd.
-OUI:00022C*
- ID_OUI_FROM_DATABASE=ABB Bomem, Inc.
+OUI:0004A0*
+ ID_OUI_FROM_DATABASE=Verity Instruments, Inc.
-OUI:00023A*
- ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH
+OUI:0004A5*
+ ID_OUI_FROM_DATABASE=Barco Projection Systems NV
-OUI:000425*
- ID_OUI_FROM_DATABASE=Atmel Corporation
+OUI:000499*
+ ID_OUI_FROM_DATABASE=Chino Corporation
-OUI:000419*
- ID_OUI_FROM_DATABASE=Fibercycle Networks, Inc.
+OUI:00048D*
+ ID_OUI_FROM_DATABASE=Teo Technologies, Inc
-OUI:00041A*
- ID_OUI_FROM_DATABASE=Ines Test and Measurement GmbH & CoKG
+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:0003E5*
ID_OUI_FROM_DATABASE=Hermstedt SG
-OUI:0002A3*
- ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems
+OUI:0003D9*
+ ID_OUI_FROM_DATABASE=Secheron SA
-OUI:000298*
- ID_OUI_FROM_DATABASE=Broadframe Corporation
+OUI:00022F*
+ ID_OUI_FROM_DATABASE=P-Cube, Ltd.
-OUI:000292*
- ID_OUI_FROM_DATABASE=Logic Innovations, Inc.
+OUI:000227*
+ ID_OUI_FROM_DATABASE=ESD Electronic System Design GmbH
-OUI:00028D*
- ID_OUI_FROM_DATABASE=Movita Technologies, Inc.
+OUI:00021F*
+ ID_OUI_FROM_DATABASE=Aculab PLC
-OUI:000283*
- ID_OUI_FROM_DATABASE=Spectrum Controls, Inc.
+OUI:00021B*
+ ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix
-OUI:000277*
- ID_OUI_FROM_DATABASE=Cash Systemes Industrie
+OUI:00020C*
+ ID_OUI_FROM_DATABASE=Metro-Optix
-OUI:00027C*
- ID_OUI_FROM_DATABASE=Trilithic, Inc.
+OUI:000218*
+ ID_OUI_FROM_DATABASE=Advanced Scientific Corp
-OUI:000275*
- ID_OUI_FROM_DATABASE=SMART Technologies, Inc.
+OUI:000213*
+ ID_OUI_FROM_DATABASE=S.D.E.L.
-OUI:000270*
- ID_OUI_FROM_DATABASE=Crewave Co., Ltd.
+OUI:00020F*
+ ID_OUI_FROM_DATABASE=AATR
-OUI:000104*
- ID_OUI_FROM_DATABASE=DVICO Co., Ltd.
+OUI:0001F9*
+ ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp.
-OUI:000110*
- ID_OUI_FROM_DATABASE=Gotham Networks
+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:0030BE*
ID_OUI_FROM_DATABASE=City-Net Technology, Inc.
-OUI:000233*
- ID_OUI_FROM_DATABASE=Mantra Communications, Inc.
-
-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:00303E*
+ ID_OUI_FROM_DATABASE=Radcom Ltd.
-OUI:00021B*
- ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix
+OUI:0030D7*
+ ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C.
-OUI:00020C*
- ID_OUI_FROM_DATABASE=Metro-Optix
+OUI:0030FC*
+ ID_OUI_FROM_DATABASE=Terawave Communications, Inc.
-OUI:000218*
- ID_OUI_FROM_DATABASE=Advanced Scientific Corp
+OUI:00300F*
+ ID_OUI_FROM_DATABASE=IMT - Information Management T
-OUI:000213*
- ID_OUI_FROM_DATABASE=S.D.E.L.
+OUI:003004*
+ ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC.
-OUI:00020F*
- ID_OUI_FROM_DATABASE=AATR
+OUI:003018*
+ ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd.
-OUI:0001F4*
- ID_OUI_FROM_DATABASE=Enterasys Networks
+OUI:003088*
+ ID_OUI_FROM_DATABASE=Ericsson
-OUI:0001F9*
- ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp.
+OUI:0030CA*
+ ID_OUI_FROM_DATABASE=Discovery Com
-OUI:000200*
- ID_OUI_FROM_DATABASE=Net & Sys Co., Ltd.
+OUI:00304F*
+ ID_OUI_FROM_DATABASE=PLANET Technology Corporation
OUI:0001FC*
ID_OUI_FROM_DATABASE=Keyence Corporation
OUI:0001B3*
ID_OUI_FROM_DATABASE=Precision Electronic Manufacturing
-OUI:000160*
- ID_OUI_FROM_DATABASE=ELMEX 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:003038*
- ID_OUI_FROM_DATABASE=XCP, INC.
-
-OUI:0030DB*
- ID_OUI_FROM_DATABASE=Mindready Solutions, Inc.
+OUI:0001B1*
+ ID_OUI_FROM_DATABASE=General Bandwidth
-OUI:00306A*
- ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD.
+OUI:0001BB*
+ ID_OUI_FROM_DATABASE=Frequentis
-OUI:003021*
- ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD
+OUI:00025E*
+ ID_OUI_FROM_DATABASE=High Technology Ltd
-OUI:0030EA*
- ID_OUI_FROM_DATABASE=TeraForce Technology Corporation
+OUI:000261*
+ ID_OUI_FROM_DATABASE=Tilgin AB
-OUI:0030F4*
- ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES
+OUI:000259*
+ ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group
-OUI:003087*
- ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG
+OUI:000255*
+ ID_OUI_FROM_DATABASE=IBM Corp
-OUI:003000*
- ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP.
+OUI:000249*
+ ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd.
-OUI:003034*
- ID_OUI_FROM_DATABASE=SET ENGINEERING
+OUI:000250*
+ ID_OUI_FROM_DATABASE=Geyser Networks, Inc.
-OUI:00308D*
- ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc.
+OUI:000242*
+ ID_OUI_FROM_DATABASE=Videoframe Systems
-OUI:00304B*
- ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC.
+OUI:000244*
+ ID_OUI_FROM_DATABASE=SURECOM Technology Co.
-OUI:0030FA*
- ID_OUI_FROM_DATABASE=TELICA, INC.
+OUI:00022C*
+ ID_OUI_FROM_DATABASE=ABB Bomem, Inc.
-OUI:0001B1*
- ID_OUI_FROM_DATABASE=General Bandwidth
+OUI:00023A*
+ ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH
-OUI:0001BB*
- ID_OUI_FROM_DATABASE=Frequentis
+OUI:000233*
+ ID_OUI_FROM_DATABASE=Mantra Communications, Inc.
OUI:0001B7*
ID_OUI_FROM_DATABASE=Centos, Inc.
OUI:000184*
ID_OUI_FROM_DATABASE=SIEB & MEYER AG
-OUI:00303E*
- ID_OUI_FROM_DATABASE=Radcom Ltd.
-
-OUI:0030D7*
- ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C.
+OUI:000160*
+ ID_OUI_FROM_DATABASE=ELMEX Co., LTD.
-OUI:0030FC*
- ID_OUI_FROM_DATABASE=Terawave Communications, Inc.
+OUI:000298*
+ ID_OUI_FROM_DATABASE=Broadframe Corporation
-OUI:00300F*
- ID_OUI_FROM_DATABASE=IMT - Information Management T
+OUI:000292*
+ ID_OUI_FROM_DATABASE=Logic Innovations, Inc.
-OUI:003004*
- ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC.
+OUI:00028D*
+ ID_OUI_FROM_DATABASE=Movita Technologies, Inc.
-OUI:003018*
- ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd.
+OUI:000283*
+ ID_OUI_FROM_DATABASE=Spectrum Controls, Inc.
-OUI:003088*
- ID_OUI_FROM_DATABASE=Ericsson
+OUI:000277*
+ ID_OUI_FROM_DATABASE=Cash Systemes Industrie
-OUI:0030CA*
- ID_OUI_FROM_DATABASE=Discovery Com
+OUI:00027C*
+ ID_OUI_FROM_DATABASE=Trilithic, Inc.
-OUI:00304F*
- ID_OUI_FROM_DATABASE=PLANET Technology Corporation
+OUI:000275*
+ ID_OUI_FROM_DATABASE=SMART Technologies, Inc.
-OUI:00014B*
- ID_OUI_FROM_DATABASE=Ennovate Networks, Inc.
+OUI:000270*
+ ID_OUI_FROM_DATABASE=Crewave Co., Ltd.
-OUI:00012C*
- ID_OUI_FROM_DATABASE=Aravox Technologies, Inc.
+OUI:000269*
+ ID_OUI_FROM_DATABASE=Nadatel Co., Ltd
-OUI:000138*
- ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+OUI:000265*
+ ID_OUI_FROM_DATABASE=Virditech Co. Ltd.
OUI:000134*
ID_OUI_FROM_DATABASE=Selectron Systems AG
OUI:00011F*
ID_OUI_FROM_DATABASE=RC Networks, 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:000104*
+ ID_OUI_FROM_DATABASE=DVICO Co., Ltd.
-OUI:00D086*
- ID_OUI_FROM_DATABASE=FOVEON, INC.
+OUI:000110*
+ ID_OUI_FROM_DATABASE=Gotham Networks
OUI:00D05A*
ID_OUI_FROM_DATABASE=SYMBIONICS, LTD.
OUI:00D0A9*
ID_OUI_FROM_DATABASE=SHINANO KENSHI CO., LTD.
-OUI:0030E9*
- ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G
-
-OUI:003027*
- ID_OUI_FROM_DATABASE=KERBANGO, INC.
+OUI:00D0F2*
+ ID_OUI_FROM_DATABASE=MONTEREY NETWORKS
-OUI:0030F6*
- ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION
+OUI:0030DB*
+ ID_OUI_FROM_DATABASE=Mindready Solutions, Inc.
-OUI:0030B6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00306A*
+ ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD.
-OUI:0030B2*
- ID_OUI_FROM_DATABASE=L-3 Sonoma EO
+OUI:003021*
+ ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD
-OUI:0030D6*
- ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH
+OUI:0030EA*
+ ID_OUI_FROM_DATABASE=TeraForce Technology Corporation
-OUI:003008*
- ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC.
+OUI:0030F4*
+ ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES
-OUI:00306D*
- ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES
+OUI:003087*
+ ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG
-OUI:0030E4*
- ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN
+OUI:003000*
+ ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP.
-OUI:00301A*
- ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD.
+OUI:003034*
+ ID_OUI_FROM_DATABASE=SET ENGINEERING
-OUI:0030CD*
- ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC.
+OUI:00308D*
+ ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc.
-OUI:003001*
- ID_OUI_FROM_DATABASE=SMP
+OUI:00304B*
+ ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC.
-OUI:0030E1*
- ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc.
+OUI:0030FA*
+ ID_OUI_FROM_DATABASE=TELICA, INC.
-OUI:0050A7*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0030E9*
+ ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G
-OUI:00D0EE*
- ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION
+OUI:003027*
+ ID_OUI_FROM_DATABASE=KERBANGO, INC.
OUI:00D0B8*
ID_OUI_FROM_DATABASE=Iomega Corporation
OUI:00503C*
ID_OUI_FROM_DATABASE=TSINGHUA NOVEL ELECTRONICS
-OUI:005030*
- ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS
-
-OUI:005037*
- ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO.
-
-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:00D03E*
- ID_OUI_FROM_DATABASE=ROCKETCHIPS, INC.
+OUI:0050B6*
+ ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD.
-OUI:00D03F*
- ID_OUI_FROM_DATABASE=AMERICAN COMMUNICATION
+OUI:0050FF*
+ ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD.
-OUI:00D033*
- ID_OUI_FROM_DATABASE=DALIAN DAXIAN NETWORK
+OUI:005032*
+ ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC.
-OUI:00D0CE*
- ID_OUI_FROM_DATABASE=ASYST ELECTRONIC
+OUI:0030F6*
+ ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION
-OUI:00D090*
+OUI:0030B6*
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:0030B2*
+ ID_OUI_FROM_DATABASE=L-3 Sonoma EO
-OUI:0050B6*
- ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD.
+OUI:0030D6*
+ ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH
-OUI:0050FF*
- ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD.
+OUI:003008*
+ ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC.
-OUI:005032*
- ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC.
+OUI:00306D*
+ ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES
-OUI:0050DA*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:0030E4*
+ ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN
-OUI:0050F9*
- ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC
+OUI:00301A*
+ ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD.
-OUI:0050F6*
- ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP.
+OUI:0030CD*
+ ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC.
-OUI:00506C*
- ID_OUI_FROM_DATABASE=Beijer Electronics Products AB
+OUI:003001*
+ ID_OUI_FROM_DATABASE=SMP
-OUI:0050A5*
- ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD.
+OUI:0030E1*
+ ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc.
-OUI:0050FC*
- ID_OUI_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD.
+OUI:0030D8*
+ ID_OUI_FROM_DATABASE=SITEK
-OUI:005000*
- ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC.
+OUI:003062*
+ ID_OUI_FROM_DATABASE=IP Video Networks Inc
-OUI:00D071*
- ID_OUI_FROM_DATABASE=ECHELON CORP.
+OUI:003081*
+ ID_OUI_FROM_DATABASE=ALTOS C&C
OUI:00D066*
ID_OUI_FROM_DATABASE=WINTRISS ENGINEERING CORP.
OUI:00D00C*
ID_OUI_FROM_DATABASE=SNIJDER MICRO SYSTEMS
-OUI:00D0F2*
- ID_OUI_FROM_DATABASE=MONTEREY NETWORKS
+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:00D0FD*
ID_OUI_FROM_DATABASE=OPTIMA TELE.COM, INC.
-OUI:0030D8*
- ID_OUI_FROM_DATABASE=SITEK
-
-OUI:003062*
- ID_OUI_FROM_DATABASE=IP Video Networks Inc
+OUI:0050A7*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-OUI:003081*
- ID_OUI_FROM_DATABASE=ALTOS C&C
+OUI:00D0EE*
+ ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION
OUI:00D0B0*
ID_OUI_FROM_DATABASE=BITSWITCH LTD.
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:00907B*
ID_OUI_FROM_DATABASE=E-TECH, INC.
-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: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:00909D*
+ ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC
-OUI:00107E*
- ID_OUI_FROM_DATABASE=BACHMANN ELECTRONIC GmbH
+OUI:009038*
+ ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, INC.
-OUI:0010C0*
- ID_OUI_FROM_DATABASE=ARMA, Inc.
+OUI:00501F*
+ ID_OUI_FROM_DATABASE=MRG SYSTEMS, LTD.
-OUI:001016*
- ID_OUI_FROM_DATABASE=T.SQWARE
+OUI:005092*
+ ID_OUI_FROM_DATABASE=Rigaku Corporation Osaka Plant
-OUI:00103D*
- ID_OUI_FROM_DATABASE=PHASECOM, LTD.
+OUI:00501C*
+ ID_OUI_FROM_DATABASE=JATOM SYSTEMS, INC.
-OUI:0010C2*
- ID_OUI_FROM_DATABASE=WILLNET, INC.
+OUI:00505C*
+ ID_OUI_FROM_DATABASE=TUNDO CORPORATION
-OUI:00107A*
- ID_OUI_FROM_DATABASE=AmbiCom, Inc.
+OUI:005068*
+ ID_OUI_FROM_DATABASE=ELECTRONIC INDUSTRIES ASSOCIATION
-OUI:0010C4*
- ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD.
+OUI:00501A*
+ ID_OUI_FROM_DATABASE=IQinVision
-OUI:0010EB*
- ID_OUI_FROM_DATABASE=SELSIUS SYSTEMS, INC.
+OUI:005063*
+ ID_OUI_FROM_DATABASE=OY COMSEL SYSTEM AB
-OUI:0010FE*
- ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+OUI:0050DE*
+ ID_OUI_FROM_DATABASE=SIGNUM SYSTEMS CORP.
-OUI:00102E*
- ID_OUI_FROM_DATABASE=NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD.
+OUI:00507B*
+ ID_OUI_FROM_DATABASE=MERLOT COMMUNICATIONS
-OUI:0010C1*
- ID_OUI_FROM_DATABASE=OI ELECTRIC CO., LTD.
+OUI:005078*
+ ID_OUI_FROM_DATABASE=MEGATON HOUSE, LTD.
-OUI:00103E*
- ID_OUI_FROM_DATABASE=NETSCHOOLS CORPORATION
+OUI:00508F*
+ ID_OUI_FROM_DATABASE=ASITA TECHNOLOGIES INT'L LTD.
-OUI:001049*
- ID_OUI_FROM_DATABASE=ShoreTel, Inc
+OUI:005057*
+ ID_OUI_FROM_DATABASE=BROADBAND ACCESS SYSTEMS
-OUI:00105E*
- ID_OUI_FROM_DATABASE=Spirent plc, Service Assurance Broadband
+OUI:005087*
+ ID_OUI_FROM_DATABASE=TERASAKI ELECTRIC CO., LTD.
OUI:005088*
ID_OUI_FROM_DATABASE=AMANO 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:0010E5*
ID_OUI_FROM_DATABASE=SOLECTRON TEXAS
-OUI:00909D*
- ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC
+OUI:00102A*
+ ID_OUI_FROM_DATABASE=ZF MICROSYSTEMS, INC.
-OUI:009038*
- ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, 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:0090CF*
ID_OUI_FROM_DATABASE=NORTEL
-OUI:00900F*
- ID_OUI_FROM_DATABASE=KAWASAKI HEAVY INDUSTRIES, LTD
+OUI:0050DA*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
-OUI:009036*
- ID_OUI_FROM_DATABASE=ens, inc.
+OUI:0050F9*
+ ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC
-OUI:0090E9*
- ID_OUI_FROM_DATABASE=JANZ COMPUTER AG
+OUI:0050F6*
+ ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP.
-OUI:009032*
- ID_OUI_FROM_DATABASE=PELCOMBE GROUP LTD.
+OUI:00506C*
+ ID_OUI_FROM_DATABASE=Beijer Electronics Products AB
-OUI:0090B8*
- ID_OUI_FROM_DATABASE=ROHDE & SCHWARZ GMBH & CO. KG
+OUI:0050A5*
+ ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD.
-OUI:009058*
- ID_OUI_FROM_DATABASE=Ultra Electronics Ltd., Command and Control Systems
+OUI:005000*
+ ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC.
-OUI:0090BE*
- ID_OUI_FROM_DATABASE=IBC/INTEGRATED BUSINESS COMPUTERS
+OUI:005030*
+ ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS
-OUI:009062*
- ID_OUI_FROM_DATABASE=ICP VORTEX COMPUTERSYSTEME GmbH
+OUI:005037*
+ ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO.
-OUI:00108F*
- ID_OUI_FROM_DATABASE=RAPTOR SYSTEMS
+OUI:00106C*
+ ID_OUI_FROM_DATABASE=EDNT GmbH
-OUI:001089*
- ID_OUI_FROM_DATABASE=WebSonic
+OUI:0010D4*
+ ID_OUI_FROM_DATABASE=STORAGE COMPUTER CORPORATION
-OUI:001086*
- ID_OUI_FROM_DATABASE=ATTO Technology, Inc.
+OUI:0010BF*
+ ID_OUI_FROM_DATABASE=InterAir Wireless
-OUI:001027*
- ID_OUI_FROM_DATABASE=L-3 COMMUNICATIONS EAST
+OUI:001036*
+ ID_OUI_FROM_DATABASE=INTER-TEL INTEGRATED SYSTEMS
-OUI:0010B8*
- ID_OUI_FROM_DATABASE=ISHIGAKI COMPUTER SYSTEM CO.
+OUI:001026*
+ ID_OUI_FROM_DATABASE=ACCELERATED NETWORKS, INC.
-OUI:00104C*
- ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc
+OUI:00104B*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
-OUI:001001*
- ID_OUI_FROM_DATABASE=Citel
+OUI:000629*
+ ID_OUI_FROM_DATABASE=IBM Corp
-OUI:0010CF*
- ID_OUI_FROM_DATABASE=FIBERLANE COMMUNICATIONS
+OUI:001004*
+ ID_OUI_FROM_DATABASE=THE BRANTLEY COILE COMPANY,INC
-OUI:001068*
- ID_OUI_FROM_DATABASE=COMOS TELECOM
+OUI:00103A*
+ ID_OUI_FROM_DATABASE=DIAMOND NETWORK TECH
-OUI:001067*
- ID_OUI_FROM_DATABASE=Ericsson
+OUI:0010D8*
+ ID_OUI_FROM_DATABASE=CALISTA
-OUI:0010F1*
- ID_OUI_FROM_DATABASE=I-O CORPORATION
+OUI:001031*
+ ID_OUI_FROM_DATABASE=OBJECTIVE COMMUNICATIONS, INC.
-OUI:001073*
- ID_OUI_FROM_DATABASE=TECHNOBOX, INC.
+OUI:00103D*
+ ID_OUI_FROM_DATABASE=PHASECOM, LTD.
-OUI:00E0C0*
- ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., 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: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:00E0C4*
ID_OUI_FROM_DATABASE=HORNER ELECTRIC, INC.
-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:00E0A1*
- ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG
+OUI:0010E6*
+ ID_OUI_FROM_DATABASE=APPLIED INTELLIGENT SYSTEMS, INC.
-OUI:00E028*
- ID_OUI_FROM_DATABASE=APTIX CORPORATION
+OUI:00101E*
+ ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRONIC INSTRUMENTS CORP.
-OUI:00E0F2*
- ID_OUI_FROM_DATABASE=ARLOTTO COMNET, INC.
+OUI:0010F2*
+ ID_OUI_FROM_DATABASE=ANTEC
-OUI:00E020*
- ID_OUI_FROM_DATABASE=TECNOMEN OY
+OUI:0010BE*
+ ID_OUI_FROM_DATABASE=MARCH NETWORKS CORPORATION
OUI:00E0C5*
ID_OUI_FROM_DATABASE=BCOM ELECTRONICS INC.
OUI:00E0B7*
ID_OUI_FROM_DATABASE=PI GROUP, LTD.
-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: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:006074*
- ID_OUI_FROM_DATABASE=QSC AUDIO PRODUCTS
-
-OUI:006058*
- ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC.
-
-OUI:00601B*
- ID_OUI_FROM_DATABASE=MESA ELECTRONICS
+OUI:00E0C0*
+ ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., LTD.
-OUI:0060FF*
- ID_OUI_FROM_DATABASE=QuVis, Inc.
+OUI:006098*
+ ID_OUI_FROM_DATABASE=HT COMMUNICATIONS
-OUI:006056*
- ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC.
+OUI:0060F7*
+ ID_OUI_FROM_DATABASE=DATAFUSION SYSTEMS
-OUI:0060D8*
- ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC.
+OUI:0060DE*
+ ID_OUI_FROM_DATABASE=Kayser-Threde GmbH
-OUI:00607A*
- ID_OUI_FROM_DATABASE=DVS GMBH
+OUI:0060D0*
+ ID_OUI_FROM_DATABASE=SNMP RESEARCH INCORPORATED
-OUI:006097*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:006079*
+ ID_OUI_FROM_DATABASE=Mainstream Data, Inc.
-OUI:0060E3*
- ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS
+OUI:006020*
+ ID_OUI_FROM_DATABASE=PIVOTAL NETWORKING, INC.
-OUI:00E0FD*
- ID_OUI_FROM_DATABASE=A-TREND TECHNOLOGY CO., LTD.
+OUI:0005A8*
+ ID_OUI_FROM_DATABASE=WYLE ELECTRONICS
-OUI:00E0FB*
- ID_OUI_FROM_DATABASE=LEIGHTRONIX, INC.
+OUI:0060B7*
+ ID_OUI_FROM_DATABASE=CHANNELMATIC, INC.
-OUI:00E0D3*
- ID_OUI_FROM_DATABASE=DATENTECHNIK GmbH
+OUI:0060A3*
+ ID_OUI_FROM_DATABASE=CONTINUUM TECHNOLOGY CORP.
-OUI:00E05E*
- ID_OUI_FROM_DATABASE=JAPAN AVIATION ELECTRONICS INDUSTRY, LTD.
+OUI:006050*
+ ID_OUI_FROM_DATABASE=INTERNIX INC.
-OUI:00E0E5*
- ID_OUI_FROM_DATABASE=CINCO NETWORKS, INC.
+OUI:0060E0*
+ ID_OUI_FROM_DATABASE=AXIOM TECHNOLOGY CO., LTD.
-OUI:00E0CF*
- ID_OUI_FROM_DATABASE=INTEGRATED DEVICE TECHNOLOGY, INC.
+OUI:0060A8*
+ ID_OUI_FROM_DATABASE=TIDOMAT AB
-OUI:00A0FD*
- ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC.
+OUI:00608E*
+ ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH
-OUI:00A0F5*
- ID_OUI_FROM_DATABASE=RADGUARD LTD.
+OUI:0060F0*
+ ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC
OUI:00A022*
ID_OUI_FROM_DATABASE=CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING
OUI:00A044*
ID_OUI_FROM_DATABASE=NTT IT CO., LTD.
-OUI:006008*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
-
-OUI:0060EF*
- ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY 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: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:00A0B0*
- ID_OUI_FROM_DATABASE=I-O DATA DEVICE, INC.
-
OUI:00A05F*
ID_OUI_FROM_DATABASE=BTG Electronics Design BV
OUI:00A09C*
ID_OUI_FROM_DATABASE=Xyplex, Inc.
-OUI:00A092*
- ID_OUI_FROM_DATABASE=H. BOLLMANN MANUFACTURERS, LTD
-
-OUI:00A04D*
- ID_OUI_FROM_DATABASE=EDA INSTRUMENTS, INC.
-
-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:006051*
- ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR
-
-OUI:00605E*
- ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING
+OUI:00A0A0*
+ ID_OUI_FROM_DATABASE=COMPACT DATA, LTD.
OUI:0060C6*
ID_OUI_FROM_DATABASE=DCS AG
OUI:00A06D*
ID_OUI_FROM_DATABASE=MANNESMANN TALLY CORPORATION
-OUI:00608E*
- ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH
+OUI:00A056*
+ ID_OUI_FROM_DATABASE=MICROPROSS
-OUI:0060F0*
- ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC
+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:0060C3*
ID_OUI_FROM_DATABASE=NETVISION CORPORATION
-OUI:00A0A0*
- ID_OUI_FROM_DATABASE=COMPACT DATA, LTD.
-
-OUI:00A0A4*
- ID_OUI_FROM_DATABASE=MICROS SYSTEMS, INC.
-
-OUI:00A024*
- ID_OUI_FROM_DATABASE=3COM 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:00C0BC*
- ID_OUI_FROM_DATABASE=TELECOM AUSTRALIA/CSSC
-
-OUI:00C0EF*
- ID_OUI_FROM_DATABASE=ABIT CORPORATION
+OUI:006051*
+ ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR
-OUI:00C03C*
- ID_OUI_FROM_DATABASE=TOWER TECH S.R.L.
+OUI:00605E*
+ ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING
-OUI:00C061*
- ID_OUI_FROM_DATABASE=SOLECTEK CORPORATION
+OUI:006058*
+ ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC.
-OUI:00C074*
- ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM
+OUI:00601B*
+ ID_OUI_FROM_DATABASE=MESA ELECTRONICS
-OUI:00C07F*
- ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP.
+OUI:0060FF*
+ ID_OUI_FROM_DATABASE=QuVis, Inc.
-OUI:00C027*
- ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC.
+OUI:006056*
+ ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC.
-OUI:00C025*
- ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION
+OUI:0060D8*
+ ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC.
-OUI:00C022*
- ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC.
+OUI:00607A*
+ ID_OUI_FROM_DATABASE=DVS GMBH
-OUI:00C0E6*
- ID_OUI_FROM_DATABASE=Verilink Corporation
+OUI:006097*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
-OUI:00C05C*
- ID_OUI_FROM_DATABASE=ELONEX PLC
+OUI:0060E3*
+ ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS
-OUI:00C0C1*
- ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC.
+OUI:006008*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
-OUI:00C091*
- ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC.
+OUI:0060EF*
+ ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY CO., LTD.
-OUI:00C002*
- ID_OUI_FROM_DATABASE=SERCOMM CORPORATION
+OUI:00E04D*
+ ID_OUI_FROM_DATABASE=INTERNET INITIATIVE JAPAN, INC
-OUI:00C0F5*
- ID_OUI_FROM_DATABASE=METACOMP, INC.
+OUI:00607F*
+ ID_OUI_FROM_DATABASE=AURORA TECHNOLOGIES, INC.
-OUI:00C042*
- ID_OUI_FROM_DATABASE=DATALUX CORP.
+OUI:00E039*
+ ID_OUI_FROM_DATABASE=PARADYNE CORP.
-OUI:00C089*
- ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION
+OUI:006091*
+ ID_OUI_FROM_DATABASE=FIRST PACIFIC NETWORKS, INC.
-OUI:00C09D*
- ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC
+OUI:006002*
+ ID_OUI_FROM_DATABASE=SCREEN SUBTITLING SYSTEMS, LTD
-OUI:00C0A5*
- ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS
+OUI:006061*
+ ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP.
-OUI:00C0E3*
- ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC.
+OUI:0060BD*
+ ID_OUI_FROM_DATABASE=HUBBELL-PULSECOM
-OUI:00C071*
- ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC.
+OUI:006074*
+ ID_OUI_FROM_DATABASE=QSC AUDIO PRODUCTS
-OUI:00C0AF*
- ID_OUI_FROM_DATABASE=TEKLOGIX INC.
+OUI:00A024*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
-OUI:00209F*
- ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC.
+OUI:00A0FD*
+ ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC.
-OUI:0020B7*
- ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE
+OUI:00A0F5*
+ ID_OUI_FROM_DATABASE=RADGUARD LTD.
OUI:00201B*
ID_OUI_FROM_DATABASE=NORTHERN TELECOM/NETWORK
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:00C055*
ID_OUI_FROM_DATABASE=MODULAR COMPUTING TECHNOLOGIES
-OUI:00C067*
- ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES
-
-OUI:00C0B4*
- ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC.
+OUI:00A0DB*
+ ID_OUI_FROM_DATABASE=FISHER & PAYKEL PRODUCTION
-OUI:00C080*
- ID_OUI_FROM_DATABASE=NETSTAR, INC.
+OUI:00A0A5*
+ ID_OUI_FROM_DATABASE=TEKNOR MICROSYSTEME, INC.
-OUI:00C015*
- ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION
+OUI:00A018*
+ ID_OUI_FROM_DATABASE=CREATIVE CONTROLLERS, INC.
-OUI:00C09F*
- ID_OUI_FROM_DATABASE=QUANTA COMPUTER, INC.
+OUI:00A09F*
+ ID_OUI_FROM_DATABASE=COMMVISION CORP.
-OUI:0070B3*
- ID_OUI_FROM_DATABASE=DATA RECALL LTD.
+OUI:00A06B*
+ ID_OUI_FROM_DATABASE=DMS DORSCH MIKROSYSTEM GMBH
-OUI:00E6D3*
- ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP.
+OUI:00209F*
+ ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC.
-OUI:00C083*
- ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC.
+OUI:0020B7*
+ ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE
OUI:00C005*
ID_OUI_FROM_DATABASE=LIVINGSTON ENTERPRISES, INC.
OUI:00C03B*
ID_OUI_FROM_DATABASE=MULTIACCESS COMPUTING CORP.
-OUI:0020F4*
- ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION
-
-OUI:00204E*
- ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC.
-
-OUI:002027*
- ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD
-
-OUI:0020ED*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD.
+OUI:00C099*
+ ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD.
-OUI:00200E*
- ID_OUI_FROM_DATABASE=SATELLITE TECHNOLOGY MGMT, INC
+OUI:00C0FC*
+ ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC.
-OUI:002096*
- ID_OUI_FROM_DATABASE=Invensys
+OUI:00C067*
+ ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES
-OUI:0020BB*
- ID_OUI_FROM_DATABASE=ZAX CORPORATION
+OUI:00C0B4*
+ ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC.
-OUI:00204D*
- ID_OUI_FROM_DATABASE=INOVIS GMBH
+OUI:00C080*
+ ID_OUI_FROM_DATABASE=NETSTAR, INC.
-OUI:002089*
- ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC.
+OUI:00C015*
+ ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION
-OUI:00205F*
- ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH
+OUI:00C09F*
+ ID_OUI_FROM_DATABASE=QUANTA COMPUTER, INC.
-OUI:002035*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0070B3*
+ ID_OUI_FROM_DATABASE=DATA RECALL LTD.
-OUI:0020E2*
- ID_OUI_FROM_DATABASE=INFORMATION RESOURCE ENGINEERING
+OUI:00E6D3*
+ ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP.
-OUI:002058*
- ID_OUI_FROM_DATABASE=ALLIED SIGNAL INC.
+OUI:00C083*
+ ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC.
OUI:002081*
ID_OUI_FROM_DATABASE=TITAN ELECTRONICS
OUI:0020F7*
ID_OUI_FROM_DATABASE=CYBERDATA CORPORATION
-OUI:0020EE*
- ID_OUI_FROM_DATABASE=GTECH CORPORATION
-
-OUI:00208C*
- ID_OUI_FROM_DATABASE=GALAXY NETWORKS, INC.
+OUI:000267*
+ ID_OUI_FROM_DATABASE=NODE RUNNER, INC.
-OUI:002063*
- ID_OUI_FROM_DATABASE=WIPRO INFOTECH LTD.
+OUI:002064*
+ ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC.
-OUI:0020DC*
- ID_OUI_FROM_DATABASE=DENSITRON TAIWAN LTD.
+OUI:002032*
+ ID_OUI_FROM_DATABASE=ALCATEL TAISEL
-OUI:002078*
- ID_OUI_FROM_DATABASE=RUNTOP, INC.
+OUI:002027*
+ ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD
-OUI:002042*
- ID_OUI_FROM_DATABASE=DATAMETRICS CORP.
+OUI:0020ED*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD.
-OUI:0020F8*
- ID_OUI_FROM_DATABASE=CARRERA COMPUTERS, INC.
+OUI:00200E*
+ ID_OUI_FROM_DATABASE=SATELLITE TECHNOLOGY MGMT, INC
-OUI:00200C*
- ID_OUI_FROM_DATABASE=ADASTRA SYSTEMS CORP.
+OUI:002096*
+ ID_OUI_FROM_DATABASE=Invensys
-OUI:0020C4*
- ID_OUI_FROM_DATABASE=INET,INC.
+OUI:0020BB*
+ ID_OUI_FROM_DATABASE=ZAX CORPORATION
-OUI:00C099*
- ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD.
+OUI:00204D*
+ ID_OUI_FROM_DATABASE=INOVIS GMBH
-OUI:00C0FC*
- ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC.
+OUI:002089*
+ ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC.
-OUI:00C0D0*
- ID_OUI_FROM_DATABASE=RATOC SYSTEM INC.
+OUI:00205F*
+ ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH
-OUI:00C07A*
- ID_OUI_FROM_DATABASE=PRIVA B.V.
+OUI:0020EE*
+ ID_OUI_FROM_DATABASE=GTECH CORPORATION
-OUI:000701*
- ID_OUI_FROM_DATABASE=RACAL-DATACOM
+OUI:00A08B*
+ ID_OUI_FROM_DATABASE=ASTON ELECTRONIC DESIGNS LTD.
-OUI:00C09C*
- ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION
+OUI:00A0AA*
+ ID_OUI_FROM_DATABASE=SPACELABS MEDICAL
-OUI:00C004*
- ID_OUI_FROM_DATABASE=JAPAN BUSINESS COMPUTER CO.LTD
+OUI:00A04F*
+ ID_OUI_FROM_DATABASE=AMERITEC CORP.
-OUI:00C062*
- ID_OUI_FROM_DATABASE=IMPULSE TECHNOLOGY
+OUI:00A073*
+ ID_OUI_FROM_DATABASE=COM21, INC.
-OUI:000267*
- ID_OUI_FROM_DATABASE=NODE RUNNER, INC.
+OUI:00A084*
+ ID_OUI_FROM_DATABASE=Dataplex Pty Ltd
-OUI:002064*
- ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC.
+OUI:00A034*
+ ID_OUI_FROM_DATABASE=AXEL
-OUI:002032*
- ID_OUI_FROM_DATABASE=ALCATEL TAISEL
+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:00202A*
ID_OUI_FROM_DATABASE=N.V. DZINE
-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: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:0020F4*
+ ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION
-OUI:0080FE*
- ID_OUI_FROM_DATABASE=AZURE TECHNOLOGIES, INC.
+OUI:00204E*
+ ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC.
-OUI:008028*
- ID_OUI_FROM_DATABASE=TRADPOST (HK) LTD
+OUI:00C074*
+ ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM
-OUI:0080B6*
- ID_OUI_FROM_DATABASE=THEMIS COMPUTER
+OUI:00C07F*
+ ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP.
-OUI:008058*
- ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORPORATION
+OUI:00C027*
+ ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC.
-OUI:0080C0*
- ID_OUI_FROM_DATABASE=PENRIL DATACOMM
+OUI:00C025*
+ ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION
-OUI:0080F5*
- ID_OUI_FROM_DATABASE=Quantel Ltd
+OUI:00C022*
+ ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC.
-OUI:00401D*
- ID_OUI_FROM_DATABASE=INVISIBLE SOFTWARE, INC.
+OUI:00C0E6*
+ ID_OUI_FROM_DATABASE=Verilink Corporation
-OUI:0040BD*
- ID_OUI_FROM_DATABASE=STARLIGHT NETWORKS, INC.
+OUI:00C05C*
+ ID_OUI_FROM_DATABASE=ELONEX PLC
-OUI:00406D*
- ID_OUI_FROM_DATABASE=LANCO, INC.
+OUI:00C0C1*
+ ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC.
-OUI:00404D*
- ID_OUI_FROM_DATABASE=TELECOMMUNICATIONS TECHNIQUES
+OUI:00C091*
+ ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC.
-OUI:0040A5*
- ID_OUI_FROM_DATABASE=CLINICOMP INTL.
+OUI:00C002*
+ ID_OUI_FROM_DATABASE=SERCOMM CORPORATION
-OUI:004059*
- ID_OUI_FROM_DATABASE=YOSHIDA KOGYO K. K.
+OUI:00C0F5*
+ ID_OUI_FROM_DATABASE=METACOMP, INC.
-OUI:004021*
- ID_OUI_FROM_DATABASE=RASTER GRAPHICS
+OUI:00C042*
+ ID_OUI_FROM_DATABASE=DATALUX CORP.
-OUI:004081*
- ID_OUI_FROM_DATABASE=MANNESMANN SCANGRAPHIC GMBH
+OUI:00C089*
+ ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION
-OUI:00806C*
- ID_OUI_FROM_DATABASE=CEGELEC PROJECTS LTD
+OUI:00C09D*
+ ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC
-OUI:00404A*
- ID_OUI_FROM_DATABASE=WEST AUSTRALIAN DEPARTMENT
+OUI:00C0A5*
+ ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS
-OUI:00400A*
- ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES, INC.
+OUI:00C0E3*
+ ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC.
-OUI:004032*
- ID_OUI_FROM_DATABASE=DIGITAL COMMUNICATIONS
+OUI:00C071*
+ ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC.
-OUI:004042*
- ID_OUI_FROM_DATABASE=N.A.T. GMBH
+OUI:00C0AF*
+ ID_OUI_FROM_DATABASE=TEKLOGIX INC.
-OUI:0040C2*
- ID_OUI_FROM_DATABASE=APPLIED COMPUTING DEVICES
+OUI:00C05D*
+ ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES
-OUI:00403C*
- ID_OUI_FROM_DATABASE=FORKS, INC.
+OUI:00C0E4*
+ ID_OUI_FROM_DATABASE=SIEMENS BUILDING
OUI:0040C4*
ID_OUI_FROM_DATABASE=KINKEI SYSTEM CORPORATION
OUI:00409A*
ID_OUI_FROM_DATABASE=NETWORK EXPRESS, INC.
-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:00C05D*
- ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES
-
-OUI:00C0E4*
- ID_OUI_FROM_DATABASE=SIEMENS BUILDING
+OUI:004055*
+ ID_OUI_FROM_DATABASE=METRONIX GMBH
OUI:00C01B*
ID_OUI_FROM_DATABASE=SOCKET COMMUNICATIONS, INC.
OUI:0040CC*
ID_OUI_FROM_DATABASE=SILCOM MANUF'G TECHNOLOGY INC.
-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: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:00404B*
ID_OUI_FROM_DATABASE=MAPLE COMPUTER SYSTEMS
-OUI:004055*
- ID_OUI_FROM_DATABASE=METRONIX GMBH
+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:0040C7*
ID_OUI_FROM_DATABASE=RUBY TECH CORPORATION
-OUI:004004*
- ID_OUI_FROM_DATABASE=ICM CO. LTD.
+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:00C0E7*
ID_OUI_FROM_DATABASE=FIBERDATA AB
-OUI:00800A*
- ID_OUI_FROM_DATABASE=JAPAN COMPUTER CORP.
+OUI:008095*
+ ID_OUI_FROM_DATABASE=BASIC MERTON HANDELSGES.M.B.H.
-OUI:00806E*
- ID_OUI_FROM_DATABASE=NIPPON STEEL CORPORATION
+OUI:008053*
+ ID_OUI_FROM_DATABASE=INTELLICOM, INC.
-OUI:008010*
- ID_OUI_FROM_DATABASE=COMMODORE INTERNATIONAL
+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:0080E5*
- ID_OUI_FROM_DATABASE=NetApp, Inc
-
OUI:0080BC*
ID_OUI_FROM_DATABASE=HITACHI ENGINEERING CO., LTD
OUI:008063*
ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH
-OUI:00608C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:008030*
+ ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS
-OUI:00804E*
- ID_OUI_FROM_DATABASE=APEX COMPUTER COMPANY
+OUI:008022*
+ ID_OUI_FROM_DATABASE=SCAN-OPTICS
-OUI:00800E*
- ID_OUI_FROM_DATABASE=ATLANTIX CORPORATION
+OUI:000041*
+ ID_OUI_FROM_DATABASE=ICE CORPORATION
-OUI:00806F*
- ID_OUI_FROM_DATABASE=ONELAN LTD.
+OUI:0040DE*
+ ID_OUI_FROM_DATABASE=Elsag Datamat spa
-OUI:008098*
- ID_OUI_FROM_DATABASE=TDK CORPORATION
+OUI:004063*
+ ID_OUI_FROM_DATABASE=VIA TECHNOLOGIES, INC.
-OUI:00809C*
- ID_OUI_FROM_DATABASE=LUXCOM, INC.
+OUI:00406C*
+ ID_OUI_FROM_DATABASE=COPERNIQUE
-OUI:008065*
- ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD.
+OUI:0040DF*
+ ID_OUI_FROM_DATABASE=DIGALOG SYSTEMS, INC.
-OUI:008016*
- ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN
+OUI:004015*
+ ID_OUI_FROM_DATABASE=ASCOM INFRASYS AG
-OUI:0080E6*
- ID_OUI_FROM_DATABASE=PEER NETWORKS, INC.
+OUI:008056*
+ ID_OUI_FROM_DATABASE=SPHINX Electronics GmbH & Co KG
-OUI:0080A2*
- ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS
+OUI:008060*
+ ID_OUI_FROM_DATABASE=NETWORK INTERFACE CORPORATION
-OUI:0080E0*
- ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC.
+OUI:00805E*
+ ID_OUI_FROM_DATABASE=LSI LOGIC CORPORATION
-OUI:008050*
- ID_OUI_FROM_DATABASE=ZIATECH CORPORATION
+OUI:008093*
+ ID_OUI_FROM_DATABASE=XYRON CORPORATION
-OUI:0000E0*
- ID_OUI_FROM_DATABASE=QUADRAM CORP.
+OUI:008006*
+ ID_OUI_FROM_DATABASE=COMPUADD CORPORATION
-OUI:000057*
- ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD.
+OUI:0080EF*
+ ID_OUI_FROM_DATABASE=RATIONAL
-OUI:0000D6*
- ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING
+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:0000F3*
ID_OUI_FROM_DATABASE=GANDALF DATA LIMITED
-OUI:000064*
- ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation
+OUI:00005C*
+ ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC.
-OUI:00002C*
- ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED
+OUI:0000AC*
+ ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING
-OUI:00002A*
- ID_OUI_FROM_DATABASE=TRW - SEDD/INP
+OUI:0000F2*
+ ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS
-OUI:0000F1*
- ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION
+OUI:000030*
+ ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD
-OUI:000083*
- ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC
+OUI:000035*
+ ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION
-OUI:000020*
- ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB
+OUI:0000E0*
+ ID_OUI_FROM_DATABASE=QUADRAM CORP.
-OUI:00007A*
- ID_OUI_FROM_DATABASE=DANA COMPUTER INC.
+OUI:000057*
+ ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD.
-OUI:00007C*
- ID_OUI_FROM_DATABASE=AMPERE INCORPORATED
+OUI:0000D6*
+ ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING
-OUI:00008A*
- ID_OUI_FROM_DATABASE=DATAHOUSE INFORMATION SYSTEMS
+OUI:00806F*
+ ID_OUI_FROM_DATABASE=ONELAN LTD.
-OUI:000068*
- ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS
+OUI:008098*
+ ID_OUI_FROM_DATABASE=TDK CORPORATION
-OUI:0000A8*
- ID_OUI_FROM_DATABASE=STRATUS COMPUTER INC.
+OUI:00809C*
+ ID_OUI_FROM_DATABASE=LUXCOM, INC.
-OUI:0000DF*
- ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV
+OUI:008065*
+ ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD.
-OUI:000062*
- ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS
+OUI:008016*
+ ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN
-OUI:0000AD*
- ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC.
+OUI:0080E6*
+ ID_OUI_FROM_DATABASE=PEER NETWORKS, INC.
-OUI:0000D0*
- ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD.
+OUI:0080A2*
+ ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS
-OUI:000093*
- ID_OUI_FROM_DATABASE=PROTEON INC.
+OUI:0080E0*
+ ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC.
-OUI:008008*
- ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS
+OUI:008050*
+ ID_OUI_FROM_DATABASE=ZIATECH CORPORATION
OUI:0080FF*
ID_OUI_FROM_DATABASE=SOC. DE TELEINFORMATIQUE RTC
OUI:000048*
ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION
-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:000016*
+ ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS .
OUI:00001E*
ID_OUI_FROM_DATABASE=TELSIST INDUSTRIA ELECTRONICA
OUI:008005*
ID_OUI_FROM_DATABASE=CACTUS COMPUTER 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:000016*
- ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS .
-
-OUI:00005C*
- ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC.
-
-OUI:0000AC*
- ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING
+OUI:008008*
+ ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS
-OUI:0000F2*
- ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS
+OUI:08005E*
+ ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC.
-OUI:000030*
- ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD
+OUI:08005A*
+ ID_OUI_FROM_DATABASE=IBM Corp
-OUI:000035*
- ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION
+OUI:080056*
+ ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER
-OUI:020701*
- ID_OUI_FROM_DATABASE=RACAL-DATACOM
+OUI:080053*
+ ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY
-OUI:080011*
- ID_OUI_FROM_DATABASE=TEKTRONIX INC.
+OUI:08004F*
+ ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
OUI:080040*
ID_OUI_FROM_DATABASE=FERRANTI COMPUTER SYS. LIMITED
OUI:080039*
ID_OUI_FROM_DATABASE=SPIDER SYSTEMS LIMITED
-OUI:080030*
- ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION
+OUI:00DD0C*
+ ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
-OUI:080027*
- ID_OUI_FROM_DATABASE=Cadmus Computer Systems
+OUI:000005*
+ ID_OUI_FROM_DATABASE=XEROX CORPORATION
-OUI:00009B*
- ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC
+OUI:0000AA*
+ ID_OUI_FROM_DATABASE=XEROX CORPORATION
-OUI:00DD0F*
- ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+OUI:000064*
+ ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation
-OUI:000001*
- ID_OUI_FROM_DATABASE=XEROX CORPORATION
+OUI:00002C*
+ ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED
-OUI:080021*
- ID_OUI_FROM_DATABASE=3M COMPANY
+OUI:00002A*
+ ID_OUI_FROM_DATABASE=TRW - SEDD/INP
-OUI:AA0004*
- ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+OUI:0000F1*
+ ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION
-OUI:08000C*
- ID_OUI_FROM_DATABASE=MIKLYN DEVELOPMENT CO.
+OUI:000083*
+ ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC
-OUI:00DD08*
- ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+OUI:000020*
+ ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB
-OUI:0000D8*
- ID_OUI_FROM_DATABASE=NOVELL, INC.
+OUI:00007A*
+ ID_OUI_FROM_DATABASE=DANA COMPUTER INC.
-OUI:0000A0*
- ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd.
+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:08007B*
ID_OUI_FROM_DATABASE=SANYO ELECTRIC CO. LTD.
-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:080074*
+ ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD.
OUI:00406B*
ID_OUI_FROM_DATABASE=SYSGEN
OUI:080003*
ID_OUI_FROM_DATABASE=ADVANCED COMPUTER COMM.
-OUI:080074*
- ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD.
+OUI:00009B*
+ ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC
-OUI:08005E*
- ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC.
+OUI:000068*
+ ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS
-OUI:08005A*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0000A8*
+ ID_OUI_FROM_DATABASE=STRATUS COMPUTER INC.
-OUI:080056*
- ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER
+OUI:0000DF*
+ ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV
-OUI:080053*
- ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY
+OUI:000062*
+ ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS
-OUI:08004F*
- ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
+OUI:0000AD*
+ ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC.
-OUI:F8E71E*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:0000D0*
+ ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD.
-OUI:00194B*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:000093*
+ ID_OUI_FROM_DATABASE=PROTEON INC.
-OUI:001F95*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:0000A0*
+ ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd.
-OUI:000E59*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+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: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:60FE20*
ID_OUI_FROM_DATABASE=2Wire Inc
+OUI:D4AE52*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:989096*
ID_OUI_FROM_DATABASE=Dell 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:0015C5*
ID_OUI_FROM_DATABASE=Dell Inc.
-OUI:D4AE52*
- ID_OUI_FROM_DATABASE=Dell Inc.
-
-OUI:B0E754*
- ID_OUI_FROM_DATABASE=2Wire Inc
-
-OUI:B8E625*
- ID_OUI_FROM_DATABASE=2Wire Inc
-
OUI:549F35*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:348446*
ID_OUI_FROM_DATABASE=Ericsson AB
-OUI:AC2B6E*
- ID_OUI_FROM_DATABASE=Intel Corporate
-
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:0018DE*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:681729*
+OUI:28B2BD*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:5C514F*
+OUI:08D40C*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:B808CF*
+OUI:843A4B*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:C8F733*
+OUI:681729*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:4851B7*
+OUI:5C514F*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:B808CF*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:5CC5D4*
OUI:F40669*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:3CA9F4*
- ID_OUI_FROM_DATABASE=Intel Corporate
-
-OUI:28B2BD*
+OUI:C8F733*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:08D40C*
+OUI:0CD292*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:843A4B*
+OUI:78929C*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:0CD292*
+OUI:6805CA*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:78929C*
+OUI:4851B7*
ID_OUI_FROM_DATABASE=Intel Corporate
-OUI:6805CA*
+OUI:3CA9F4*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:ACA31E*
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:D0E782*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
-OUI:0C4C39*
- ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
-
-OUI:002423*
- ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc.
-
OUI:A81D16*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
OUI:38A53C*
ID_OUI_FROM_DATABASE=COMECER Netherlands
-OUI:001D8B*
- ID_OUI_FROM_DATABASE=ADB Broadband Italia
-
-OUI:A4526F*
- ID_OUI_FROM_DATABASE=ADB Broadband Italia
+OUI:0C4C39*
+ ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
OUI:581243*
ID_OUI_FROM_DATABASE=AcSiP Technology Corp.
OUI:001974*
ID_OUI_FROM_DATABASE=16063
-OUI:ECF00E*
- ID_OUI_FROM_DATABASE=AboCom
-
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: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:001AEB*
ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K.
-OUI:747548*
- ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
-
-OUI:A43111*
- ID_OUI_FROM_DATABASE=ZIV
-
OUI:5C93A2*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
OUI:E8F724*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
-OUI:1C1448*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:707E43*
- 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:701A04*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:747548*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
-OUI:00D9D1*
+OUI:080046*
ID_OUI_FROM_DATABASE=Sony 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:001DBA*
ID_OUI_FROM_DATABASE=Sony Corporation
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:18002D*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
-OUI:3C0771*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:D8D43C*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:0CFE45*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:F8D0AC*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
OUI:04E676*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
OUI:0022F4*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
-OUI:00041F*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+OUI:1C1448*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:080046*
- ID_OUI_FROM_DATABASE=Sony Corporation
+OUI:707E43*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0003E0*
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:0023ED*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:001B52*
+OUI:745612*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:00230B*
+OUI:E46449*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:001E8D*
+OUI:002493*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:0023A2*
+OUI:40FC89*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:001BDD*
+OUI:001B52*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:001404*
+OUI:00230B*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:745612*
+OUI:001E8D*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:E46449*
+OUI:0023A2*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:002493*
+OUI:001BDD*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:40FC89*
+OUI:001404*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00195E*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-OUI:000D92*
- ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
-
-OUI:009096*
- ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
-
OUI:0011F5*
ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
OUI:40BA61*
ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
-OUI:841B5E*
- ID_OUI_FROM_DATABASE=NETGEAR
+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:001F33*
ID_OUI_FROM_DATABASE=NETGEAR
-OUI:1883BF*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:9C80DF*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+OUI:841B5E*
+ ID_OUI_FROM_DATABASE=NETGEAR
OUI:001CCC*
ID_OUI_FROM_DATABASE=BlackBerry RTS
OUI:94EBCD*
ID_OUI_FROM_DATABASE=BlackBerry RTS
-OUI:644FB0*
- ID_OUI_FROM_DATABASE=Hyunjin.com
-
-OUI:001A2A*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:001D19*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:88252C*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
OUI:A4E4B8*
ID_OUI_FROM_DATABASE=BlackBerry RTS
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:100D7F*
ID_OUI_FROM_DATABASE=NETGEAR
-OUI:0020D6*
- ID_OUI_FROM_DATABASE=Breezecom, Ltd.
-
OUI:001018*
ID_OUI_FROM_DATABASE=Broadcom
OUI:001BE9*
ID_OUI_FROM_DATABASE=Broadcom
-OUI:307C5E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0010DB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:00121E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0014F6*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:EC3EF7*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0C8610*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:40A677*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:841888*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:002688*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0017CB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:DC38E1*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:40B4F0*
- ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:0020D6*
+ ID_OUI_FROM_DATABASE=Breezecom, Ltd.
OUI:008077*
ID_OUI_FROM_DATABASE=Brother industries, LTD.
-OUI:029D8E*
- ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC.
-
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: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*
+OUI:E458E7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:981DFA*
+OUI:8CBFA6*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:FCF136*
+OUI:7840E4*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:0C8910*
+OUI:9000DB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:54FA3E*
+OUI:183A2D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:A89FBA*
OUI:646CB2*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:F884F2*
+OUI:A48431*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:14B484*
+OUI:E4F8EF*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:608F5C*
+OUI:1867B0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:F40E22*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:4CBCA5*
OUI:4CA56D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:A48431*
+OUI:08373D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:E4F8EF*
+OUI:50F520*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:1432D1*
+OUI:A4EBD3*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:E458E7*
+OUI:28987B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:8CBFA6*
+OUI:9C3AAF*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:7840E4*
+OUI:1432D1*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:9000DB*
+OUI:F884F2*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:183A2D*
+OUI:14B484*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:08373D*
+OUI:608F5C*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:50F520*
+OUI:389496*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:A4EBD3*
+OUI:0CB319*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:28987B*
+OUI:08EE8B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:1867B0*
+OUI:84A466*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:F40E22*
+OUI:981DFA*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-OUI:9C3AAF*
+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:000FF6*
ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP
-OUI:702559*
- ID_OUI_FROM_DATABASE=CyberTAN Technology Inc.
-
-OUI:0090D6*
- ID_OUI_FROM_DATABASE=Crystal Group, Inc.
-
OUI:001DAA*
ID_OUI_FROM_DATABASE=DrayTek Corp.
-OUI:02CF1C*
- ID_OUI_FROM_DATABASE=Communication Machinery Corporation
-
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:0C1167*
- ID_OUI_FROM_DATABASE=Cisco Systems, 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:001A73*
ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
-OUI:00904B*
- ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
-
-OUI:D86BF7*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
-OUI:A4C0E1*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
OUI:34AF2C*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:F44D17*
ID_OUI_FROM_DATABASE=GOLDCARD HIGH-TECH CO.,LTD.
-OUI:001E35*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
-OUI:001FC5*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
OUI:0021BD*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:E84ECE*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-OUI:0009BF*
+OUI:D86BF7*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
+OUI:A4C0E1*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:001AE9*
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:0019B7*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:002404*
+OUI:001D6E*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:0002EE*
+OUI:001B33*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001C9A*
+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:001F01*
+OUI:002669*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:000EED*
+OUI:0022FD*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001E3A*
+OUI:002109*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001A89*
+OUI:002108*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:0021AA*
+OUI:001F01*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:002669*
+OUI:000EED*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:0022FD*
+OUI:001E3A*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:002109*
+OUI:001A89*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:002108*
+OUI:002404*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001D6E*
+OUI:0002EE*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001B33*
+OUI:001C9A*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:ECF35B*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:B83241*
+ ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd.
-OUI:EC9B5B*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:9897D1*
+ ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
-OUI:BCC6DB*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+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:3C912B*
ID_OUI_FROM_DATABASE=Vexata Inc
-OUI:F8C96C*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
-OUI:48555F*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:54369B*
ID_OUI_FROM_DATABASE=1Verge Internet Technology (Beijing) Co., Ltd.
OUI:3438AF*
ID_OUI_FROM_DATABASE=Inlab Software GmbH
-OUI:D897BA*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:049B9C*
ID_OUI_FROM_DATABASE=Eadingcore Intelligent Technology Co., Ltd.
OUI:08EFAB*
ID_OUI_FROM_DATABASE=SAYME WIRELESS SENSOR NETWORK
-OUI:BC52B4*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:C81B6B*
ID_OUI_FROM_DATABASE=Innova Security
OUI:902CC7*
ID_OUI_FROM_DATABASE=C-MAX Asia Limited
-OUI:B8AEED*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
OUI:1C965A*
ID_OUI_FROM_DATABASE=Weifang goertek Electronics CO.,LTD
OUI:0444A1*
ID_OUI_FROM_DATABASE=TELECON GALICIA,S.A.
-OUI:C03FD5*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., LTD
-
OUI:84569C*
ID_OUI_FROM_DATABASE=Coho Data, Inc.,
OUI:142BD2*
ID_OUI_FROM_DATABASE=Armtel Ltd.
-OUI:D4AD2D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:F845AD*
ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
OUI:B4346C*
ID_OUI_FROM_DATABASE=MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED
-OUI:4C55CC*
- ID_OUI_FROM_DATABASE=ACKme Networks Pty Ltd
-
OUI:9C1465*
ID_OUI_FROM_DATABASE=Edata Elektronik San. ve Tic. A.Ş.
OUI:0C2D89*
ID_OUI_FROM_DATABASE=QiiQ Communications Inc.
-OUI:34BF90*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
-OUI:D467E7*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:604A1C*
ID_OUI_FROM_DATABASE=SUYIN Corporation
OUI:204C6D*
ID_OUI_FROM_DATABASE=Hugo Brennenstuhl Gmbh & Co. KG.
-OUI:D49524*
- ID_OUI_FROM_DATABASE=Clover Network, Inc.
-
OUI:DC825B*
ID_OUI_FROM_DATABASE=JANUS, spol. s r.o.
OUI:8CC5E1*
ID_OUI_FROM_DATABASE=ShenZhen Konka Telecommunication Technology Co.,Ltd
-OUI:7427EA*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
OUI:6CB311*
ID_OUI_FROM_DATABASE=Shenzhen Lianrui Electronics Co.,Ltd
OUI:A00363*
ID_OUI_FROM_DATABASE=Robert Bosch Healthcare GmbH
-OUI:4C8FA5*
- ID_OUI_FROM_DATABASE=Jastec
-
OUI:F0F644*
ID_OUI_FROM_DATABASE=Whitesky Science & Technology Co.,Ltd.
OUI:98291D*
ID_OUI_FROM_DATABASE=Jaguar de Mexico, SA de CV
-OUI:8C3C4A*
- ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC.
-
OUI:18863A*
ID_OUI_FROM_DATABASE=DIGITAL ART SYSTEM
OUI:08B738*
ID_OUI_FROM_DATABASE=Lite-On Technogy Corp.
-OUI:702526*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:9C6650*
ID_OUI_FROM_DATABASE=Glodio Technolies Co.,Ltd Tianjin Branch
OUI:ACEE3B*
ID_OUI_FROM_DATABASE=6harmonics Inc
-OUI:04C1B9*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:681605*
ID_OUI_FROM_DATABASE=Systems And Electronic Development FZCO
OUI:40BC8B*
ID_OUI_FROM_DATABASE=itelio GmbH
-OUI:903AA0*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:88C36E*
ID_OUI_FROM_DATABASE=Beijing Ereneben lnformation Technology Limited
OUI:F05849*
ID_OUI_FROM_DATABASE=CareView Communications
-OUI:E06995*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:BC15A6*
ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd.
OUI:AC02CF*
ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda
-OUI:A0B662*
- ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd.
-
OUI:9067B5*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
OUI:E0BC43*
ID_OUI_FROM_DATABASE=C2 Microsystems, Inc.
-OUI:7071BC*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:7884EE*
ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A.
OUI:00269E*
ID_OUI_FROM_DATABASE=Quanta Computer Inc
-OUI:002697*
- ID_OUI_FROM_DATABASE=Cheetah Technologies, L.P.
-
OUI:002698*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:002672*
ID_OUI_FROM_DATABASE=AAMP of America
-OUI:00266C*
- ID_OUI_FROM_DATABASE=Inventec
-
OUI:00266B*
ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED
OUI:002202*
ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB
-OUI:0021FD*
- ID_OUI_FROM_DATABASE=DSTA S.L.
-
OUI:0021F9*
ID_OUI_FROM_DATABASE=WIRECOM Technologies
OUI:001E20*
ID_OUI_FROM_DATABASE=Intertain Inc.
-OUI:001E25*
- ID_OUI_FROM_DATABASE=Intek Digital Inc
-
OUI:001E19*
ID_OUI_FROM_DATABASE=GTRI
OUI:001989*
ID_OUI_FROM_DATABASE=Sonitrol Corporation
-OUI:001A45*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
OUI:001A3E*
ID_OUI_FROM_DATABASE=Faster Technology LLC
OUI:001870*
ID_OUI_FROM_DATABASE=E28 Shanghai Limited
-OUI:00185C*
- ID_OUI_FROM_DATABASE=EDS Lab Pte Ltd
-
OUI:001863*
ID_OUI_FROM_DATABASE=Veritech Electronics Limited
OUI:0016A2*
ID_OUI_FROM_DATABASE=CentraLite Systems, Inc.
-OUI:00168F*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
OUI:001696*
ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited
OUI:001154*
ID_OUI_FROM_DATABASE=Webpro Technologies Inc.
-OUI:00115B*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
OUI:00114B*
ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH
OUI:000E2D*
ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd.
-OUI:000E2E*
- ID_OUI_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD.
-
OUI:000CEA*
ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme
OUI:000C61*
ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital
-OUI:000C49*
- ID_OUI_FROM_DATABASE=Dangaard Telecom RTC Division A/S
-
OUI:000CBA*
ID_OUI_FROM_DATABASE=Jamex, Inc.
OUI:0008A5*
ID_OUI_FROM_DATABASE=Peninsula Systems Inc.
-OUI:00089F*
- ID_OUI_FROM_DATABASE=EFM Networks
-
OUI:000899*
ID_OUI_FROM_DATABASE=Netbind, Inc.
OUI:00079B*
ID_OUI_FROM_DATABASE=Aurora Networks
-OUI:000795*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
OUI:00078F*
ID_OUI_FROM_DATABASE=Emkay Innovative Products
OUI:000788*
ID_OUI_FROM_DATABASE=Clipcomm, Inc.
-OUI:000782*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:000779*
ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd.
OUI:000167*
ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION
-OUI:00020E*
- ID_OUI_FROM_DATABASE=ECI Telecom, Ltd
-
OUI:000215*
ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B
OUI:0010C6*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
-OUI:00104F*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:0010DA*
ID_OUI_FROM_DATABASE=Kollmorgen Corp
OUI:006027*
ID_OUI_FROM_DATABASE=Superior Modular Products
-OUI:0060DC*
- ID_OUI_FROM_DATABASE=Toyo Network Systems & System Integration Co. LTD
-
OUI:0060C1*
ID_OUI_FROM_DATABASE=WaveSpan Corporation
OUI:00A014*
ID_OUI_FROM_DATABASE=CSIR
-OUI:00A045*
- ID_OUI_FROM_DATABASE=PHOENIX CONTACT GMBH & CO.
-
OUI:00A064*
ID_OUI_FROM_DATABASE=KVB/ANALECT
OUI:00C0ED*
ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC
-OUI:00C0F0*
- ID_OUI_FROM_DATABASE=KINGSTON TECHNOLOGY CORP.
-
OUI:00C0D1*
ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION
OUI:00005A*
ID_OUI_FROM_DATABASE=SysKonnect GmbH
-OUI:0000C9*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
OUI:000023*
ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB
OUI:6CFAA7*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
-OUI:0015C1*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
-OUI:0019C5*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
OUI:0024EF*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
OUI:B4527D*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
-OUI:280DFC*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
OUI:E063E5*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
OUI:18C086*
ID_OUI_FROM_DATABASE=Broadcom
-OUI:80ACAC*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:003146*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:000585*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:F01C2D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:5C4527*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:44F477*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:CCE17F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:3C6104*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:C03E0F*
ID_OUI_FROM_DATABASE=BSkyB Ltd
-OUI:54E032*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:78FE3D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:F8C001*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:50C58D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0024DC*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001F12*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0019E2*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:0020D4*
ID_OUI_FROM_DATABASE=Cabletron Systems, Inc.
OUI:4C2578*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:001EA4*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-
OUI:001262*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
OUI:002547*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-OUI:001DE9*
- 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:A0F9E0*
ID_OUI_FROM_DATABASE=VIVATEL COMPANY LIMITED
-OUI:0C54B9*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:F8C372*
ID_OUI_FROM_DATABASE=TSUZUKI DENKI
OUI:C8458F*
ID_OUI_FROM_DATABASE=Wyler AG
-OUI:74852A*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:149A10*
ID_OUI_FROM_DATABASE=Microsoft Corporation
OUI:DC663A*
ID_OUI_FROM_DATABASE=Apacer Technology Inc.
-OUI:FCF152*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
OUI:B009D3*
ID_OUI_FROM_DATABASE=Avizia
OUI:300D2A*
ID_OUI_FROM_DATABASE=Zhejiang Wellcom Technology Co.,Ltd.
-OUI:C4084A*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:8496D8*
ID_OUI_FROM_DATABASE=Pace plc
OUI:58E326*
ID_OUI_FROM_DATABASE=Compass Technologies Inc.
-OUI:F08CFB*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
OUI:848DC7*
ID_OUI_FROM_DATABASE=Cisco SPVTG
OUI:D86194*
ID_OUI_FROM_DATABASE=Objetivos y Sevicios de Valor Añadido
-OUI:FCF8B7*
- ID_OUI_FROM_DATABASE=TRONTEQ Electronic
-
OUI:589CFC*
ID_OUI_FROM_DATABASE=FreeBSD Foundation
OUI:085DDD*
ID_OUI_FROM_DATABASE=Mercury Corporation
-OUI:88B1E1*
- ID_OUI_FROM_DATABASE=AirTight Networks, Inc.
-
OUI:98349D*
ID_OUI_FROM_DATABASE=Krauss Maffei Technologies GmbH
OUI:F89550*
ID_OUI_FROM_DATABASE=Proton Products Chengdu Ltd
-OUI:943BB1*
- ID_OUI_FROM_DATABASE=KAONMEDIA
-
OUI:447BC4*
ID_OUI_FROM_DATABASE=DualShine Technology(SZ)Co.,Ltd
OUI:74ECF1*
ID_OUI_FROM_DATABASE=Acumen
-OUI:649968*
- ID_OUI_FROM_DATABASE=Elentec
-
OUI:6815D3*
ID_OUI_FROM_DATABASE=Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A.
OUI:1CBBA8*
ID_OUI_FROM_DATABASE=OJSC Ufimskiy Zavod Promsvyaz
-OUI:34AA99*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
OUI:506028*
ID_OUI_FROM_DATABASE=Xirrus Inc.
OUI:B01C91*
ID_OUI_FROM_DATABASE=Elim Co
-OUI:ECA86B*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEMS CO., LTD.
-
OUI:0CA2F4*
ID_OUI_FROM_DATABASE=Chameleon Technology (UK) Limited
OUI:C0E54E*
ID_OUI_FROM_DATABASE=DENX Computer Systems GmbH
-OUI:386077*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
OUI:E435FB*
ID_OUI_FROM_DATABASE=Sabre Technology (Hull) Ltd
-OUI:146308*
- ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD.
-
OUI:28BE9B*
ID_OUI_FROM_DATABASE=Technicolor USA Inc.
OUI:706F81*
ID_OUI_FROM_DATABASE=Private
-OUI:9CDF03*
- ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
-
OUI:30E4DB*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:9CC077*
ID_OUI_FROM_DATABASE=PrintCounts, LLC
-OUI:4487FC*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
-
OUI:A85BB0*
ID_OUI_FROM_DATABASE=Shenzhen Dehoo Technology Co.,Ltd
OUI:0026F8*
ID_OUI_FROM_DATABASE=Golden Highway Industry Development Co., Ltd.
-OUI:0026F7*
- ID_OUI_FROM_DATABASE=Infosys Technologies Ltd.
-
OUI:0026F1*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
OUI:002377*
ID_OUI_FROM_DATABASE=Isotek Electronics Ltd
-OUI:002378*
- ID_OUI_FROM_DATABASE=GN Netcom A/S
-
OUI:002371*
ID_OUI_FROM_DATABASE=SOAM Systel
OUI:00219F*
ID_OUI_FROM_DATABASE=SATEL OY
-OUI:002197*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM
-
OUI:00218A*
ID_OUI_FROM_DATABASE=Electronic Design and Manufacturing Company
OUI:001BFA*
ID_OUI_FROM_DATABASE=G.i.N. mbH
-OUI:001BF3*
- ID_OUI_FROM_DATABASE=TRANSRADIO SenderSysteme Berlin AG
-
OUI:001BE3*
ID_OUI_FROM_DATABASE=Health Hero Network, Inc.
OUI:0015F6*
ID_OUI_FROM_DATABASE=SCIENCE AND ENGINEERING SERVICES, INC.
-OUI:00177D*
- ID_OUI_FROM_DATABASE=IDT International Limited
-
OUI:001782*
ID_OUI_FROM_DATABASE=LoBenn Inc.
OUI:000ABB*
ID_OUI_FROM_DATABASE=Taiwan Secom Co,. Ltd
-OUI:000AC2*
- ID_OUI_FROM_DATABASE=FiberHome Telecommunication Technologies CO.,LTD
-
OUI:000AC7*
ID_OUI_FROM_DATABASE=Unication Group
OUI:000588*
ID_OUI_FROM_DATABASE=Sensoria Corp.
-OUI:000594*
- ID_OUI_FROM_DATABASE=HMS Technology Center Ravensburg GmbH
-
OUI:00058E*
ID_OUI_FROM_DATABASE=Flextronics International GmbH & Co. Nfg. KG
OUI:000174*
ID_OUI_FROM_DATABASE=CyberOptics Corporation
-OUI:00015D*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:000164*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:00D092*
ID_OUI_FROM_DATABASE=GLENAYRE WESTERN MULTIPLEX
-OUI:00D0EC*
- ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS, INC
-
OUI:00D0C5*
ID_OUI_FROM_DATABASE=COMPUTATIONAL SYSTEMS, INC.
OUI:0090DC*
ID_OUI_FROM_DATABASE=TECO INFORMATION SYSTEMS
-OUI:00D0A2*
- ID_OUI_FROM_DATABASE=INTEGRATED DEVICE
-
OUI:00D0AE*
ID_OUI_FROM_DATABASE=ORESIS COMMUNICATIONS, INC.
OUI:00904E*
ID_OUI_FROM_DATABASE=DELEM BV
-OUI:009050*
- ID_OUI_FROM_DATABASE=TELESTE OY
-
OUI:00904A*
ID_OUI_FROM_DATABASE=CONCUR SYSTEM TECHNOLOGIES
OUI:009065*
ID_OUI_FROM_DATABASE=FINISAR CORPORATION
-OUI:001035*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEMS CO., LTD
-
OUI:001053*
ID_OUI_FROM_DATABASE=COMPUTER TECHNOLOGY CORP.
OUI:0010CC*
ID_OUI_FROM_DATABASE=CLP COMPUTER LOGISTIK PLANUNG GmbH
-OUI:00109B*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
OUI:001094*
ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc
OUI:00601F*
ID_OUI_FROM_DATABASE=STALLION TECHNOLOGIES
-OUI:0060B1*
- ID_OUI_FROM_DATABASE=INPUT/OUTPUT, INC.
-
OUI:00608F*
ID_OUI_FROM_DATABASE=TEKRAM TECHNOLOGY CO., LTD.
OUI:00E021*
ID_OUI_FROM_DATABASE=FREEGATE CORP.
-OUI:00E0D5*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
OUI:00E0AB*
ID_OUI_FROM_DATABASE=DIMAT S.A.
OUI:0020DA*
ID_OUI_FROM_DATABASE=Alcatel North America ESD
-OUI:0020F2*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
OUI:002005*
ID_OUI_FROM_DATABASE=SIMPLE TECHNOLOGY
OUI:002098*
ID_OUI_FROM_DATABASE=HECTRONIC AB
-OUI:00208F*
- ID_OUI_FROM_DATABASE=ECI TELECOM LTD.
-
OUI:002065*
ID_OUI_FROM_DATABASE=SUPERNET NETWORKING INC.
OUI:00204F*
ID_OUI_FROM_DATABASE=DEUTSCHE AEROSPACE AG
-OUI:002088*
- ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION
-
OUI:00202E*
ID_OUI_FROM_DATABASE=DAYSTAR DIGITAL
OUI:00806B*
ID_OUI_FROM_DATABASE=SCHMID TELECOMMUNICATION
-OUI:0080B8*
- ID_OUI_FROM_DATABASE=B.U.G. MORISEIKI, INCORPORATED
-
OUI:00802C*
ID_OUI_FROM_DATABASE=THE SAGE GROUP PLC
OUI:026086*
ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD.
-OUI:08000D*
- ID_OUI_FROM_DATABASE=INTERNATIONAL COMPUTERS LTD.
-
OUI:00DD05*
ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
OUI:D05349*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-OUI:0025DC*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
OUI:00BB3A*
ID_OUI_FROM_DATABASE=Private
OUI:001CA4*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
-OUI:00248D*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
OUI:002345*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
OUI:0011B6*
ID_OUI_FROM_DATABASE=Open Systems International
-OUI:002283*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:2C6BF5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:64649B*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:541E56*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:E03E44*
ID_OUI_FROM_DATABASE=Broadcom
OUI:D40129*
ID_OUI_FROM_DATABASE=Broadcom
-OUI:544B8C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:84B59C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:100E7E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:288A1C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:FCB698*
ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
-OUI:3C94D5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:B0A86E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:AC4BC8*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:00E03A*
ID_OUI_FROM_DATABASE=Cabletron Systems, Inc.
-OUI:002159*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
OUI:000117*
ID_OUI_FROM_DATABASE=Canal +
OUI:A04E04*
ID_OUI_FROM_DATABASE=Nokia Corporation
-OUI:001CFC*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
OUI:001370*
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
ID_VENDOR_FROM_DATABASE=Comarch SA
bluetooth:v0225*
- ID_VENDOR_FROM_DATABASE=Nestl Nespresso S.A.
+ ID_VENDOR_FROM_DATABASE=Nestlé Nespresso S.A.
bluetooth:v0226*
ID_VENDOR_FROM_DATABASE=Merlinia A/S
ID_VENDOR_FROM_DATABASE=Microtronics Engineering GmbH
bluetooth:v024F*
- ID_VENDOR_FROM_DATABASE=Schneider Schreibgerte GmbH
+ ID_VENDOR_FROM_DATABASE=Schneider Schreibgeräte GmbH
bluetooth:v0250*
ID_VENDOR_FROM_DATABASE=Sapphire Circuits LLC
ID_VENDOR_FROM_DATABASE=Geotab
bluetooth:v0276*
- ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gertebau GmbH
+ ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gerätebau GmbH
bluetooth:v0277*
ID_VENDOR_FROM_DATABASE=bewhere 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 ( 乐鑫信息科技(上海)有限公司 )
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: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)
ID_MODEL_FROM_DATABASE=Tonga XTV GL [FirePro S7150V]
pci:v00001002d00006938*
- ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X Mac Edition]
+ 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: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: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:v00001014d0000034Asv00001014sd000004C8*
ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2))
-pci:v00001014d0000034Asv00001014sd00000C49*
+pci:v00001014d0000034Asv00001014sd000004C9*
ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD))
pci:v00001014d0000044B*
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: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: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: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: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
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 QL45412H 40GbE Adapter (SR-IOV VF))
+ 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 QL45412H 40GbE Adapter (SR-IOV VF))
+ 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))
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 QL45411H 25GbE Adapter (SR-IOV VF))
+ 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 QL45412H 25GbE Adapter (SR-IOV VF))
+ 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: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: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: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: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: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:v00001093d00007327*
ID_MODEL_FROM_DATABASE=PXI-6529
+pci:v00001093d0000732C*
+ ID_MODEL_FROM_DATABASE=VXI-8360T
+
pci:v00001093d00007331*
ID_MODEL_FROM_DATABASE=PXIe-5602
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:v00001093d000076A5*
ID_MODEL_FROM_DATABASE=PXIe-6537B
+pci:v00001093d0000783E*
+ ID_MODEL_FROM_DATABASE=PXI-8368
+
pci:v00001093d00009020*
ID_MODEL_FROM_DATABASE=PXI-2501
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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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:v00001412d00001712sv00001412sd00001712*
ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24)
-pci:v00001412d00001712sv00001412sd00003632*
- ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta Audiophile 192)
-
pci:v00001412d00001712sv00001412sd0000D630*
ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010)
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: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: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: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: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: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: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: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: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: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: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: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: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)
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function]
pci:v000015B3d00001017*
- ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-4]
+ ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5]
pci:v000015B3d00001018*
ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Virtual Function]
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: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: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: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: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: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: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: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: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: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: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: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:v00001D44d0000A400*
ID_MODEL_FROM_DATABASE=PM2x24/PM3224
+pci:v00001D49*
+ ID_VENDOR_FROM_DATABASE=Lenovo
+
pci:v00001D5C*
ID_VENDOR_FROM_DATABASE=Fantasia Trading LLC
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: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: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: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: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: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: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
ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB EHCI
pci:v00008086d00000F35*
- ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB xHCI
+ 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
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 (D815EEA2 mainboard)
+ 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)
ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Vaio PCG-FX403)
pci:v00008086d00001132sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EEA2 Mainboard)
+ 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: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: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: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
ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics
pci:v00008086d00001603*
- ID_MODEL_FROM_DATABASE=Broadwell-U Camarillo Device
+ ID_MODEL_FROM_DATABASE=Broadwell-U Processor Thermal Subsystem
pci:v00008086d00001604*
ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI
ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics
pci:v00008086d00001900*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001901*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x16)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x16)
+
+pci:v00008086d00001903*
+ ID_MODEL_FROM_DATABASE=Skylake Processor Thermal Subsystem
pci:v00008086d00001904*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001905*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x8)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x8)
pci:v00008086d00001908*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001909*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x4)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x4)
pci:v00008086d0000190C*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d0000190F*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001910*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001911*
- ID_MODEL_FROM_DATABASE=Sky Lake Gaussian Mixture Model
+ ID_MODEL_FROM_DATABASE=Skylake Gaussian Mixture Model
pci:v00008086d00001912*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d00001916*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d00001918*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001919*
- ID_MODEL_FROM_DATABASE=Sky Lake Imaging Unit
+ ID_MODEL_FROM_DATABASE=Skylake Imaging Unit
+
+pci:v00008086d0000191B*
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d0000191E*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d0000191F*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
pci:v00008086d00001926*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d00001932*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d0000193B*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
pci:v00008086d00001960*
ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor
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: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: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: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: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: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: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: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: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: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: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
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 (D815EEA2 mainboard)
+ 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)
ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Supermicro P4SBE Mainboard)
pci:v00008086d00002443sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Desktop Board D815EEA2/D815EFV)
pci:v00008086d00002443sv00008086sd00004557*
ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EGEW Mainboard)
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 (D815EEA2 mainboard)
+ 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: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
ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Supermicro P4SBE Mainboard)
pci:v00008086d0000244Bsv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EEA2 mainboard)
+ 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: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: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: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: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:v00008086d000024C5sv00001734sd00001055*
ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Amilo M1420)
-pci:v00008086d000024C5sv00008086sd000024C5*
- ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Dell Dimension 2400)
-
pci:v00008086d000024C6*
ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
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: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: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: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: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: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: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: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
ID_MODEL_FROM_DATABASE=Sunrise Point-H Northpeak
pci:v00008086d0000A127*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #0
pci:v00008086d0000A128*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART #1
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #1
pci:v00008086d0000A129*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS SPI #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO SPI #0
pci:v00008086d0000A12A*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS SPI #1
+ 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
ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller
pci:v00008086d0000A160*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS I2C Controller #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #0
pci:v00008086d0000A161*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS I2C Controller #1
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #1
pci:v00008086d0000A166*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART Controller #2
+ 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
ID_MODEL_FROM_DATABASE=Bluetooth 1.2 Interface [Broadcom BCM2035]
usb:v03F0p0121*
- ID_MODEL_FROM_DATABASE=HP49g+ Calculator
+ 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
ID_MODEL_FROM_DATABASE=LaserJet M1132 MFP
usb:v03F0p0441*
- ID_MODEL_FROM_DATABASE=HP Prime Calculator
+ ID_MODEL_FROM_DATABASE=Prime [NW280AA, G8X92AA]
usb:v03F0p0504*
ID_MODEL_FROM_DATABASE=DeskJet 885c
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: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: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:v03F0pD104*
ID_MODEL_FROM_DATABASE=Bluetooth Dongle
+usb:v03F0pD507*
+ ID_MODEL_FROM_DATABASE=39gII [NW249AA]
+
usb:v03F0pEFBE*
ID_MODEL_FROM_DATABASE=NEC Picty900
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: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: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.
ID_MODEL_FROM_DATABASE=SMSC USB20H04 3-Port Hub [ThinkPad X4 UltraBase, Wistron S Note-3 Media Slice]
usb:v04B3p4485*
- ID_MODEL_FROM_DATABASE=Serial Converter
+ ID_MODEL_FROM_DATABASE=ThinkPad Dock Hub
usb:v04B3p4524*
ID_MODEL_FROM_DATABASE=40 Character Vacuum Fluorescent Display
ID_MODEL_FROM_DATABASE=PX-1700F
usb:v04B8p087D*
- ID_MODEL_FROM_DATABASE=PX-B750F
+ ID_MODEL_FROM_DATABASE=PX-B750F/WP-4525 Series
usb:v04B8p087F*
ID_MODEL_FROM_DATABASE=PX-403A
usb:v04F3p01A4*
ID_MODEL_FROM_DATABASE=Wireless Keyboard
+usb:v04F3p0201*
+ ID_MODEL_FROM_DATABASE=Touchscreen
+
usb:v04F3p0210*
ID_MODEL_FROM_DATABASE=Optical Mouse
usb:v04F9p035E*
ID_MODEL_FROM_DATABASE=MFC-1910NW
+usb:v04F9p0360*
+ ID_MODEL_FROM_DATABASE=DCP-1618W
+
usb:v04F9p0361*
ID_MODEL_FROM_DATABASE=MFC-1919NW
ID_MODEL_FROM_DATABASE=ET-0405 [Graphire]
usb:v056Ap0011*
- ID_MODEL_FROM_DATABASE=Graphire 2 4x5
+ ID_MODEL_FROM_DATABASE=ET-0405A [Graphire2 (4x5)]
usb:v056Ap0012*
- ID_MODEL_FROM_DATABASE=Graphire 2 5x7
+ ID_MODEL_FROM_DATABASE=ET-0507A [Graphire2 (5x7)]
usb:v056Ap0013*
- ID_MODEL_FROM_DATABASE=Graphire 3 4x5
+ ID_MODEL_FROM_DATABASE=CTE-430 [Graphire3 (4x5)]
usb:v056Ap0014*
- ID_MODEL_FROM_DATABASE=Graphire 3 6x8
+ ID_MODEL_FROM_DATABASE=CTE-630 [Graphire3 (6x8)]
usb:v056Ap0015*
- ID_MODEL_FROM_DATABASE=Graphire 4 4x5
+ ID_MODEL_FROM_DATABASE=CTE-440 [Graphire4 (4x5)]
usb:v056Ap0016*
- ID_MODEL_FROM_DATABASE=Graphire 4 6x8
+ ID_MODEL_FROM_DATABASE=CTE-640 [Graphire4 (6x8)]
usb:v056Ap0017*
- ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun]
+ ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun (small)]
usb:v056Ap0018*
- ID_MODEL_FROM_DATABASE=Bamboo Fun 6x8
+ ID_MODEL_FROM_DATABASE=CTE-650 [Bamboo Fun (medium)]
usb:v056Ap0019*
- ID_MODEL_FROM_DATABASE=Bamboo One Medium
+ ID_MODEL_FROM_DATABASE=CTE-631 [Bamboo One]
usb:v056Ap0020*
- ID_MODEL_FROM_DATABASE=Intuos 4x5
+ ID_MODEL_FROM_DATABASE=GD-0405 [Intuos (4x5)]
usb:v056Ap0021*
- ID_MODEL_FROM_DATABASE=Intuos 6x8
+ ID_MODEL_FROM_DATABASE=GD-0608 [Intuos (6x8)]
usb:v056Ap0022*
- ID_MODEL_FROM_DATABASE=Intuos 9x12
+ ID_MODEL_FROM_DATABASE=GD-0912 [Intuos (9x12)]
usb:v056Ap0023*
- ID_MODEL_FROM_DATABASE=Intuos 12x12
+ ID_MODEL_FROM_DATABASE=GD-1212 [Intuos (12x12)]
usb:v056Ap0024*
- ID_MODEL_FROM_DATABASE=Intuos 12x18
+ ID_MODEL_FROM_DATABASE=GD-1218 [Intuos (12x18)]
usb:v056Ap0026*
- ID_MODEL_FROM_DATABASE=Intuos5 touch S
+ ID_MODEL_FROM_DATABASE=PTH-450 [Intuos5 touch (S)]
usb:v056Ap0027*
- ID_MODEL_FROM_DATABASE=Intuos5 touch M
+ ID_MODEL_FROM_DATABASE=PTH-650 [Intuos5 touch (M)]
usb:v056Ap0028*
- ID_MODEL_FROM_DATABASE=Intuos5 touch L
+ ID_MODEL_FROM_DATABASE=PTH-850 [Intuos5 touch (L)]
usb:v056Ap0029*
- ID_MODEL_FROM_DATABASE=Intuos5 S
+ ID_MODEL_FROM_DATABASE=PTK-450 [Intuos5 (S)]
usb:v056Ap002A*
- ID_MODEL_FROM_DATABASE=Intuos5 M
+ ID_MODEL_FROM_DATABASE=PTK-650 [Intuos5 (M)]
usb:v056Ap0030*
ID_MODEL_FROM_DATABASE=PL400
ID_MODEL_FROM_DATABASE=DTU-710
usb:v056Ap003F*
- ID_MODEL_FROM_DATABASE=Cintiq 21UX (DTZ-2100)
+ ID_MODEL_FROM_DATABASE=DTZ-2100 [Cintiq 21UX]
usb:v056Ap0041*
- ID_MODEL_FROM_DATABASE=Intuos2 4x5
+ ID_MODEL_FROM_DATABASE=XD-0405-U [Intuos2 (4x5)]
usb:v056Ap0042*
- ID_MODEL_FROM_DATABASE=Intuos2 6x8
+ ID_MODEL_FROM_DATABASE=XD-0608-U [Intuos2 (6x8)]
usb:v056Ap0043*
- ID_MODEL_FROM_DATABASE=Intuos2 9x12
+ ID_MODEL_FROM_DATABASE=XD-0912-U [Intuos2 (9x12)]
usb:v056Ap0044*
- ID_MODEL_FROM_DATABASE=Intuos2 12x12
+ ID_MODEL_FROM_DATABASE=XD-1212-U [Intuos2 (12x12)]
usb:v056Ap0045*
- ID_MODEL_FROM_DATABASE=Intuos2 12x18
+ 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=Volito
+ ID_MODEL_FROM_DATABASE=FT-0405 [Volito, PenPartner, PenStation (4x5)]
usb:v056Ap0061*
- ID_MODEL_FROM_DATABASE=PenStation2
+ ID_MODEL_FROM_DATABASE=FT-0203 [Volito, PenPartner, PenStation (2x3)]
usb:v056Ap0062*
- ID_MODEL_FROM_DATABASE=Volito2 4x5
+ ID_MODEL_FROM_DATABASE=CTF-420 [Volito2]
usb:v056Ap0063*
- ID_MODEL_FROM_DATABASE=Volito2 2x3
+ ID_MODEL_FROM_DATABASE=CTF-220 [BizTablet]
usb:v056Ap0064*
- ID_MODEL_FROM_DATABASE=PenPartner2
+ ID_MODEL_FROM_DATABASE=CTF-221 [PenPartner2]
usb:v056Ap0065*
- ID_MODEL_FROM_DATABASE=Bamboo
+ ID_MODEL_FROM_DATABASE=MTE-450 [Bamboo]
usb:v056Ap0069*
- ID_MODEL_FROM_DATABASE=Bamboo One
+ 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=Graphire Wireless 6x8
+ ID_MODEL_FROM_DATABASE=CTE-630BT [Graphire Wireless (6x8)]
usb:v056Ap0084*
ID_MODEL_FROM_DATABASE=Wireless adapter for Bamboo tablets
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=Intuos3 4x5
+ ID_MODEL_FROM_DATABASE=PTZ-430 [Intuos3 (4x5)]
usb:v056Ap00B1*
- ID_MODEL_FROM_DATABASE=Intuos3 6x18
+ ID_MODEL_FROM_DATABASE=PTZ-630 [Intuos3 (6x8)]
usb:v056Ap00B2*
- ID_MODEL_FROM_DATABASE=Intuos3 9x12
+ ID_MODEL_FROM_DATABASE=PTZ-930 [Intuos3 (9x12)]
usb:v056Ap00B3*
- ID_MODEL_FROM_DATABASE=Intuos3 12x12
+ ID_MODEL_FROM_DATABASE=PTZ-1230 [Intuos3 (12x12)]
usb:v056Ap00B4*
- ID_MODEL_FROM_DATABASE=Intuos3 12x19
+ ID_MODEL_FROM_DATABASE=PTZ-1231W [Intuos3 (12x19)]
usb:v056Ap00B5*
- ID_MODEL_FROM_DATABASE=Intuos3 6x11 (PTZ-631W)
+ ID_MODEL_FROM_DATABASE=PTZ-631W [Intuos3 (6x11)]
usb:v056Ap00B7*
- ID_MODEL_FROM_DATABASE=Intuos3 4x6
+ ID_MODEL_FROM_DATABASE=PTZ-431W [Intuos3 (4x6)]
usb:v056Ap00B8*
- ID_MODEL_FROM_DATABASE=Intuos4 4x6
+ ID_MODEL_FROM_DATABASE=PTK-440 [Intuos4 (4x6)]
usb:v056Ap00B9*
- ID_MODEL_FROM_DATABASE=Intuos4 6x9
+ ID_MODEL_FROM_DATABASE=PTK-640 [Intuos4 (6x9)]
usb:v056Ap00BA*
- ID_MODEL_FROM_DATABASE=Intuos4 8x13
+ ID_MODEL_FROM_DATABASE=PTK-840 [Intuos4 (8x13)]
usb:v056Ap00BB*
- ID_MODEL_FROM_DATABASE=Intuos4 12x19
+ ID_MODEL_FROM_DATABASE=PTK-1240 [Intuos4 (12x19)]
usb:v056Ap00C0*
ID_MODEL_FROM_DATABASE=DTF-521
ID_MODEL_FROM_DATABASE=DTF-720
usb:v056Ap00C5*
- ID_MODEL_FROM_DATABASE=Cintiq 20WSX
+ ID_MODEL_FROM_DATABASE=DTZ-20WSX [Cintiq 20WSX]
usb:v056Ap00C6*
- ID_MODEL_FROM_DATABASE=Cintiq 12WX
+ ID_MODEL_FROM_DATABASE=DTZ-12WX [Cintiq 12WX]
usb:v056Ap00C7*
ID_MODEL_FROM_DATABASE=DTU-1931
usb:v056Ap00CC*
- ID_MODEL_FROM_DATABASE=Cintiq 21UX (DTK-2100)
+ 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=Bamboo Pen & Touch (CTH-460-DE)
+ 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=Bamboo Fun (CTH-661)
+ ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)]
usb:v056Ap00D4*
- ID_MODEL_FROM_DATABASE=Bamboo Pen (CTL-460)
+ 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=Bamboo Pen & Touch (CTH-460)
+ 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=Bamboo Fun (CTH-661SE-NL)
+ 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=Bamboo Pen (CTL-470)
+ 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=Cintiq 24HD touch (DTH-2400) touchscreen
+ ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] touchscreen
usb:v056Ap00F8*
- ID_MODEL_FROM_DATABASE=Cintiq 24HD touch (DTH-2400) tablet
+ 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=Intuos CTH480S2 [Manga]
+ 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=Cintiq Companion Hybrid 13HD (DTH-A1300) tablet
+ ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] tablet
usb:v056Ap0309*
- ID_MODEL_FROM_DATABASE=Cintiq Companion Hybrid 13HD (DTH-A1300) touchscreen
+ ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] touchscreen
usb:v056Ap030E*
- ID_MODEL_FROM_DATABASE=Intuos Pen Small (CTL480)
+ 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=Thinkpad T550 touchscreen
+ ID_MODEL_FROM_DATABASE=TPC5010
usb:v056B*
ID_VENDOR_FROM_DATABASE=Decicon, Inc.
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: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: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: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:v05DAp20EE*
ID_MODEL_FROM_DATABASE=Micortek ScanMaker X12USL
+usb:v05DAp2838*
+ ID_MODEL_FROM_DATABASE=RT2832U
+
usb:v05DAp3008*
ID_MODEL_FROM_DATABASE=Scanner
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: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: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
ID_MODEL_FROM_DATABASE=Portable Hard Drive (Store'n'Go)
usb:v18A5p0237*
- ID_MODEL_FROM_DATABASE=Portable Harddrive (500 GB)
+ 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: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: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: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 4 / 10
+ ID_MODEL_FROM_DATABASE=Nexus Device (MTP)
usb:v18D1p4EE2*
- ID_MODEL_FROM_DATABASE=Nexus 4 (debug)
+ ID_MODEL_FROM_DATABASE=Nexus Device (debug)
usb:v18D1p4EE3*
- ID_MODEL_FROM_DATABASE=Nexus 4 (tether)
+ ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (tether)
usb:v18D1p4EE4*
- ID_MODEL_FROM_DATABASE=Nexus 4 (debug + tether)
+ 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: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.
# 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
-# (or /dev/input/event*).
+# udevadm info /dev/input/eventXX.
#
# Allowed properties are:
# EVDEV_ABS_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
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
#########################################
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
#########################################
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
# 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
-# (or /dev/input/event*).
+# udevadm info /dev/input/eventXX.
##########################################
# Acer
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
###########################################################
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
# 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
-# (or /dev/input/event*).
+# udevadm info /dev/input/eventXX.
#
# Allowed properties are:
# MOUSE_DPI
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
# Logitech USB Laser Mouse M-UAS144 [LS1 Laser Mouse]
mouse:usb:v046dpc062:name:Logitech USB Laser Mouse:
-# Logitech USB Laser Mouse M-U0007
-mouse:usb:v046dpc069:name:Logitech USB Laser Mouse:
MOUSE_DPI=1200@125
# Logitech T620 (or, the soap)
# 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
-# (or /dev/input/event*).
+# udevadm info /dev/input/eventXX.
#
# Allowed properties are:
# POINTINGSTICK_CONST_ACCEL
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
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])='-Werror `echo "$3" | sed 's/^-Wno-/-W/'`'"
+ 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]))],
/systemd.directives.xml
/systemd.index.xml
/*.[13578]
+/*.html
/custom-entities.ent
<example>
<title>Invoking a Method</title>
- <para>The following command invokes a the
+ <para>The following command invokes the
<literal>StartUnit</literal> method on the
<literal>org.freedesktop.systemd1.Manager</literal>
interface of the
<xsl:template match="citerefentry[not(@project)]">
<a>
<xsl:attribute name="href">
- <xsl:value-of select="refentrytitle"/><xsl:text>.html</xsl:text>
+ <xsl:value-of select="refentrytitle"/><xsl:text>.html#</xsl:text>
+ <xsl:value-of select="refentrytitle/@target"/>
</xsl:attribute>
<xsl:call-template name="inline.charseq"/>
</a>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="dnssec-trust-anchors.d" conditional='ENABLE_RESOLVED'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>dnssec-trust-anchors.d</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>dnssec-trust-anchors.d</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>dnssec-trust-anchors.d</refname>
+ <refname>systemd.positive</refname>
+ <refname>systemd.negative</refname>
+ <refpurpose>DNSSEC trust anchor configuration files</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/etc/dnssec-trust-anchors.d/*.positive</filename></para>
+ <para><filename>/run/dnssec-trust-anchors.d/*.positive</filename></para>
+ <para><filename>/usr/lib/dnssec-trust-anchors.d/*.positive</filename></para>
+ <para><filename>/etc/dnssec-trust-anchors.d/*.negative</filename></para>
+ <para><filename>/run/dnssec-trust-anchors.d/*.negative</filename></para>
+ <para><filename>/usr/lib/dnssec-trust-anchors.d/*.negative</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>The DNSSEC trust anchor configuration files define positive
+ and negative trust anchors
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ bases DNSSEC integrity proofs on.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Positive Trust Anchors</title>
+
+ <para>Positive trust anchor configuration files contain DNSKEY and
+ DS resource record definitions to use as base for DNSSEC integrity
+ proofs. See <ulink
+ url="https://tools.ietf.org/html/rfc4035#section-4.4">RFC 4035,
+ Section 4.4</ulink> for more information about DNSSEC trust
+ anchors.</para>
+
+ <para>Positive trust anchors are read from files with the suffix
+ <filename>.positive</filename> located in
+ <filename>/etc/dnssec-trust-anchors.d/</filename>,
+ <filename>/run/dnssec-trust-anchors.d/</filename> and
+ <filename>/usr/lib/dnssec-trust-anchors.d/</filename>. 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 <filename>/usr/lib/dnssec-trust-anchors.d/</filename>
+ it is sufficient to provide an identically-named file in
+ <filename>/etc/dnssec-trust-anchors.d/</filename> or
+ <filename>/run/dnssec-trust-anchors.d/</filename> that is either
+ empty or a symlink to <filename>/dev/null</filename> ("masked").</para>
+
+ <para>Positive trust anchor files are simple text files resembling
+ DNS zone files, as documented in <ulink
+ url="https://tools.ietf.org/html/rfc1035#section-5">RFC 1035, Section
+ 5</ulink>. One DS or DNSKEY resource record may be listed per
+ line. Empty lines and lines starting with a semicolon
+ (<literal>;</literal>) are ignored and considered comments. A DS
+ resource record is specified like in the following example:</para>
+
+ <programlisting>. IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5</programlisting>
+
+ <para>The first word specifies the domain, use
+ <literal>.</literal> for the root domain. The domain may be
+ specified with or without trailing dot, which is considered
+ equivalent. The second word must be <literal>IN</literal> the
+ third word <literal>DS</literal>. The following words specify the
+ key tag, signature algorithm, digest algorithm, followed by the
+ hex-encoded key fingerprint. See <ulink
+ url="https://tools.ietf.org/html/rfc4034#section-5">RFC 4034,
+ Section 5</ulink> for details about the precise syntax and meaning
+ of these fields.</para>
+
+ <para>Alternatively, DNSKEY resource records may be used to define
+ trust anchors, like in the following example:</para>
+
+ <programlisting>. IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=</programlisting>
+
+ <para>The first word specifies the domain again, the second word
+ must be <literal>IN</literal>, followed by
+ <literal>DNSKEY</literal>. The subsequent words encode the DNSKEY
+ flags, protocol and algorithm fields, followed by the key data
+ encoded in Base64. See <ulink
+ url="https://tools.ietf.org/html/rfc4034#section-2">RFC 4034,
+ Section 2</ulink> for details about the precise syntax and meaning
+ of these fields.</para>
+
+ <para>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.</para>
+
+ <para>Note that <filename>systemd-resolved</filename> 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.</para>
+
+ <para>It is generally recommended to encode trust anchors in DS
+ resource records, rather than DNSKEY resource records.</para>
+
+ <para>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 <ulink url="https://tools.ietf.org/html/rfc5011">RFC
+ 5011</ulink> for details about revoked trust anchors. Note that
+ <filename>systemd-resolved</filename> 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.</para>
+
+ <para>The current DNSSEC trust anchor for the Internet's root
+ domain is available at the <ulink
+ url="https://data.iana.org/root-anchors/root-anchors.xml">IANA
+ Trust Anchor and Keys</ulink> page.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Negative Trust Anchors</title>
+
+ <para>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
+ <filename>.negative</filename> suffix. Empty lines and lines whose
+ first character is <literal>;</literal> are ignored. Each line
+ specifies one domain name where DNSSEC validation shall be
+ disabled on.</para>
+
+ <para>Negative trust anchors are useful to support private DNS
+ subtrees that are not referenced from the Internet DNS hierarchy,
+ and not signed.</para>
+
+ <para><ulink url="https://tools.ietf.org/html/rfc7646">RFC
+ 7646</ulink> for details on negative trust anchors.</para>
+
+ <para>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.</para>
+
+ <para>It is also possibly to define per-interface negative trust
+ anchors using the <varname>DNSSECNegativeTrustAnchors=</varname>
+ setting in
+ <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ files.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
and restrictions systemd makes on the file system
hierarchy.</para>
- <para>Many of the paths described here are queriable
+ <para>Many of the paths described here can be queried
with the
<citerefentry><refentrytitle>systemd-path</refentrytitle><manvolnum>1</manvolnum></citerefentry>
tool.</para>
for DNS domain name labels, even though this is not a strict
requirement.</para>
- <para>Depending on the operating system, other configuration files
- might be checked for configuration of the hostname as well,
- however only as fallback.</para>
-
<para>You may use
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to change the value of this file during runtime from the command
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 default
- received from network configuration. If a static hostname is set,
- and is valid (something other than localhost), then the transient
- hostname is not used.</para>
+ "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.</para>
<para>Note that the pretty hostname has little restrictions on the
characters used, while the static and transient hostnames are
<literal>[Remote]</literal> section:</para>
<variablelist>
+ <varlistentry>
+ <term><varname>Seal=</varname></term>
+
+ <listitem><para>Periodically sign the data in the journal using Forward Secure Sealing.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>SplitMode=</varname></term>
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
paths may be specified. If a file path refers to an executable
file, this is equivalent to an <literal>_EXE=</literal> match
for the canonicalized binary path. Similarly, if a path refers
- to a device node, this is equivalent to a
- <literal>_KERNEL_DEVICE=</literal> match for the device.</para>
+ to a device node then match is added for the kernel name of the
+ device (<literal>_KERNEL_DEVICE=</literal>). 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 (<literal>_BOOT_ID=</literal>) 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.</para>
<para>Additional constraints may be added using options
<option>--boot</option>, <option>--unit=</option>, etc., to
field can take in all entries of the journal.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-N</option></term>
+ <term><option>--fields</option></term>
+
+ <listitem><para>Print all field names currently used in all entries of the journal.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--system</option></term>
<term><option>--user</option></term>
<term><varname>systemd.default_standard_output=</varname></term>
<term><varname>systemd.default_standard_error=</varname></term>
<term><varname>systemd.setenv=</varname></term>
+ <term><varname>systemd.machine_id=</varname></term>
<listitem>
<para>Parameters understood by the system and service
manager to control system behavior. For details, see
<varname>TasksMax=</varname> setting of the per-user slice
unit, see
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. Defaults to 4096.</para></listitem>
+ for details. Defaults to 12288 (12K).</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RemoveIPC=</varname></term>
- <listitem><para>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 are
- excluded from the effect of this setting. Defaults to
- <literal>yes</literal>.</para></listitem>
+ <listitem><para>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 <literal>yes</literal>.</para></listitem>
</varlistentry>
</variablelist>
at install time. Use
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to initialize it on mounted (but not booted) system images.</para>
+
+ <para>The machine-id may also be set, for example when network
+ booting, by setting the <varname>systemd.machine_id=</varname>
+ kernel command line parameter or passing the option
+ <option>--machine-id=</option> to systemd. A machine-id may not
+ be set to all zeros.</para>
</refsect1>
<refsect1>
<literal>checksum</literal> is specified, the download is
checked for integrity after the transfer is complete, but no
signatures are verified. If <literal>signature</literal> is
- specified, the checksum is verified and the images's signature
+ 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
<literal>signature</literal> if the server and protocol
image.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><option>--dkr-index-url</option></term>
-
- <listitem><para>Specifies the index server to use for
- downloading <literal>dkr</literal> images with the
- <command>pull-dkr</command>. Takes a
- <literal>http://</literal>, <literal>https://</literal>
- URL.</para></listitem>
- </varlistentry>
-
<varlistentry>
<term><option>--format=</option></term>
below.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><command>pull-dkr</command> <replaceable>REMOTE</replaceable> [<replaceable>NAME</replaceable>]</term>
-
- <listitem><para>Downloads a <literal>dkr</literal> container
- image and makes it available locally. The remote name refers
- to a <literal>dkr</literal> container name. If omitted, the
- local machine name is derived from the <literal>dkr</literal>
- container name.</para>
-
- <para>Image verification is not available for
- <literal>dkr</literal> containers, and thus
- <option>--verify=no</option> must always be specified with
- this command.</para>
-
- <para>This command downloads all (missing) layers for the
- specified container and places them in read-only subvolumes in
- <filename>/var/lib/machines/</filename>. A writable snapshot
- of the newest layer is then created under the specified local
- machine name. To omit creation of this writable snapshot, pass
- <literal>-</literal> as local machine name.</para>
-
- <para>The read-only layer subvolumes are prefixed with
- <filename>.dkr-</filename>, and thus not shown by
- <command>list-images</command>, unless <option>--all</option>
- is passed.</para>
-
- <para>To specify the <literal>dkr</literal> index server to
- use for looking up the specified container, use
- <option>--dkr-index-url=</option>.</para>
-
- <para>Note that pressing C-c during execution of this command
- will not abort the download. Use
- <command>cancel-transfer</command>, described
- below.</para></listitem>
- </varlistentry>
-
<varlistentry>
<term><command>import-tar</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term>
<term><command>import-raw</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term>
image is read from standard input, in which case the second
argument is mandatory.</para>
- <para>Similar as with <command>pull-tar</command>,
- <command>pull-raw</command> the file system
- <filename>/var/lib/machines.raw</filename> is increased in
- size of necessary and appropriate. Optionally, the
+ <para>Both <command>pull-tar</command> and <command>pull-raw</command>
+ will resize <filename>/var/lib/machines.raw</filename> and the
+ filesystem therein as necessary. Optionally, the
<option>--read-only</option> switch may be used to create a
read-only container or VM image. No cryptographic validation
is done when importing the images.</para>
<para>Note that many image operations are only supported,
efficient or atomic on btrfs file systems. Due to this, if the
<command>pull-tar</command>, <command>pull-raw</command>,
- <command>pull-dkr</command>, <command>import-tar</command>,
- <command>import-raw</command> and <command>set-limit</command>
- commands notice that <filename>/var/lib/machines</filename> is
- empty and not located on btrfs, they will implicitly set up a
- loopback file <filename>/var/lib/machines.raw</filename>
- containing a btrfs file system that is mounted to
+ <command>import-tar</command>, <command>import-raw</command> and
+ <command>set-limit</command> commands notice that
+ <filename>/var/lib/machines</filename> is empty and not located on
+ btrfs, they will implicitly set up a loopback file
+ <filename>/var/lib/machines.raw</filename> containing a btrfs file
+ system that is mounted to
<filename>/var/lib/machines</filename>. The size of this loopback
file may be controlled dynamically with
<command>set-limit</command>.</para>
login prompt into the container is requested.</para>
</example>
- <example>
- <title>Download a Fedora <literal>dkr</literal> image</title>
-
- <programlisting># machinectl pull-dkr --verify=no mattdm/fedora
-# systemd-nspawn -M fedora</programlisting>
-
- <para>Downloads a <literal>dkr</literal> image and opens a shell
- in it. Note that the specified download command might require an
- index server to be specified with the
- <literal>--dkr-index-url=</literal>.</para>
- </example>
-
<example>
<title>Exports a container image as tar file</title>
is on the local loopback) and the IPv6 address ::1 (which is the
local host).</para></listitem>
- <listitem><para>The hostname <literal>localhost</literal> is
- resolved to the IP addresses 127.0.0.1 and
- ::1.</para></listitem>
+ <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
+ <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
+ resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
<listitem><para>The hostname <literal>gateway</literal> is
resolved to all current default routing gateway addresses,
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<refsect1>
<title>Options</title>
+ <para>The following options are available in the <literal>[Resolve]</literal> section:</para>
+
<variablelist class='network-directives'>
<varlistentry>
<term><varname>DNS=</varname></term>
- <listitem><para>A space-separated list of IPv4 and IPv6
- addresses to be used as system DNS servers. DNS requests are
- sent to one of the listed DNS servers in parallel to any
- per-interface DNS servers acquired from
- <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- For compatibility reasons, if set to the empty list, the DNS
- servers listed in <filename>/etc/resolv.conf</filename> are
- used, if any are configured there. This setting defaults to
- the empty list.</para></listitem>
+ <listitem><para>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
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
+ set at runtime by external applications. For compatibility reasons, if this setting is not specified, the DNS
+ servers listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any servers
+ are configured in it. This setting defaults to the empty list.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FallbackDNS=</varname></term>
- <listitem><para>A space-separated list of IPv4 and IPv6
- addresses to be used as the fallback DNS servers. Any
- per-interface DNS servers obtained from
+ <listitem><para>A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any
+ per-link DNS servers obtained from
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- take precedence over this setting, as do any servers set via
- <varname>DNS=</varname> above or
- <filename>/etc/resolv.conf</filename>. 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.</para></listitem>
+ take precedence over this setting, as do any servers set via <varname>DNS=</varname> above or
+ <filename>/etc/resolv.conf</filename>. 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.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Domains=</varname></term>
+ <listitem><para>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 <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any domains
+ are configured in it. This setting defaults to the empty list.</para>
+
+ <para>Specified domain names may optionally be prefixed with <literal>~</literal>. 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 <varname>DNS=</varname> setting (see above), in case additional, suitable per-link DNS servers
+ are known. If no per-link DNS servers are known using the <literal>~</literal> syntax has no effect. Use the
+ construct <literal>~.</literal> (which is composed of <literal>~</literal> to indicate a routing domain and
+ <literal>.</literal> to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the
+ system DNS server defined with <varname>DNS=</varname> preferably for all domains.</para></listitem>
</varlistentry>
<varlistentry>
<literal>resolve</literal>, only resolution support is enabled,
but responding is disabled. Note that
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- also maintains per-interface LLMNR settings. LLMNR will be
- enabled on an interface only if the per-interface and the
+ also maintains per-link LLMNR settings. LLMNR will be
+ enabled on a link only if the per-link and the
global setting is on.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DNSSEC=</varname></term>
+ <listitem><para>Takes a boolean argument or
+ <literal>allow-downgrade</literal>. 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 <literal>allow-downgrade</literal> 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.</para>
+
+ <para>Note that DNSSEC validation requires retrieval of
+ additional DNS data, and thus results in a small DNS look-up
+ time penalty.</para>
+
+ <para>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
+ <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ 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 <varname>DNSSEC=</varname> is true, all further
+ lookups will fail, as it cannot be proved anymore whether
+ lookups are correctly signed, or validly unsigned. If
+ <varname>DNSSEC=</varname> is set to
+ <literal>allow-downgrade</literal> the resolver will
+ automatically turn off DNSSEC validation in such a case.</para>
+
+ <para>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.</para>
+
+ <para>It is recommended to set <varname>DNSSEC=</varname> 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
+ <varname>DNSSEC=</varname> to
+ <literal>allow-downgrade</literal>.</para>
+
+ <para>In addition to this global DNSSEC setting
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ 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.</para>
+
+ <para>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
+ <literal>allow-downgrade</literal> 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.</para>
+
+ <para>Defaults to off.</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>4</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>4</manvolnum></citerefentry>
</para>
</refsect1>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd-bus" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd-bus</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Documentation</contrib>
+ <firstname>Zbigniew</firstname>
+ <surname>Jędrzejewski-Szmek</surname>
+ <email>zbyszek@in.waw.pl</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd-bus</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd-bus</refname>
+ <refpurpose>A lightweight D-Bus and kdbus client library</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ </funcsynopsis>
+
+ <cmdsynopsis>
+ <command>pkg-config --cflags --libs libsystemd</command>
+ </cmdsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>sd-bus.h</filename> provides an implementation
+ of a D-Bus client. It can interoperate both with the traditional
+ <citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ and with kdbus. See
+ <ulink url="http://www.freedesktop.org/software/dbus/" />
+ for more information about the big picture.
+ </para>
+
+ <important>
+ <para>Interfaces described here have not been declared stable yet,
+ and are not accessible from <filename>libsystemd.so</filename>.
+ This documentation is provided in hope it might be useful for
+ developers, without any guarantees of availability or stability.
+ </para>
+ </important>
+
+ <para>See
+ <citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_string_memfd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_get_cookie</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_address</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_path_encode</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for more information about the functions available.</para>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>dbus-send</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <ulink url="https://developer.gnome.org/gio/stable/gdbus.html">gdbus</ulink>
+ </para>
+ </refsect1>
+
+</refentry>
<refsect1>
<title>Description</title>
- <para><filename>sd-daemon.h</filename> provide APIs for new-style
+ <para><filename>sd-daemon.h</filename> provides APIs for new-style
daemons, as implemented by the
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- init system.</para>
+ service manager.</para>
<para>See
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd-event" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd-event</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd-event</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd-event</refname>
+ <refpurpose>A generic event loop implementation</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+ </funcsynopsis>
+
+ <cmdsynopsis>
+ <command>pkg-config --cflags --libs libsystemd</command>
+ </cmdsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>sd-event.h</filename> provides a generic event
+ loop implementation, based on Linux <citerefentry
+ project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ </para>
+
+ <para>See
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_get_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for more information about the functions available.</para>
+
+ <para>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 <citerefentry
+ project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ primitives.</para>
+
+ <para>The event loop implementation provides the following features:</para>
+
+ <orderedlist>
+ <listitem><para>I/O event sources, based on <citerefentry
+ project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>'s
+ file descriptor watching, including edge triggered events (<constant>EPOLLET</constant>). See <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Timer event sources, based on <citerefentry
+ project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ supporting the <constant>CLOCK_MONOTONIC</constant>,
+ <constant>CLOCK_REALTIME</constant>,
+ <constant>CLOCK_BOOTIME</constant> clocks, as well as the
+ <constant>CLOCK_REALTIME_ALARM</constant> and
+ <constant>CLOCK_BOOTTIME_ALARM</constant> 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 <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>UNIX process signal events, based on
+ <citerefentry
+ project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ including full support for real-time signals, and queued parameters. See <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Child process state change events, based on
+ <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>. See <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>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
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>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
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>The event loop may automatically send watchdog
+ notification messages to the service manager. See
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>The event loop may be integrated into foreign
+ event loops, such as the GLib one. See
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for an example.</para></listitem>
+ </orderedlist>
+
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_get_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_usage</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
- <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for more information about the functions implemented.</para>
<para>Command line access for submitting entries to the journal is
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
modified by the caller.</para>
<para>All functions that take a <parameter>char***</parameter>
- parameter will store the answer there as an address of a an array
+ 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
<parameter>c</parameter> remains valid, and should not be freed or
<refname>sd_bus_creds_get_augmented_mask</refname>
<refname>sd_bus_creds_ref</refname>
<refname>sd_bus_creds_unref</refname>
+ <refname>sd_bus_creds_unrefp</refname>
<refpurpose>Retrieve credentials object for the specified PID</refpurpose>
</refnamediv>
<funcdef>sd_bus_creds *<function>sd_bus_creds_unref</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_bus_creds_unrefp</function></funcdef>
+ <paramdef>sd_bus_creds **<parameter>c</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
<para>
<para><function>sd_bus_creds_unref()</function> destroys a reference
to <parameter>c</parameter>.</para>
+
+ <para><function>sd_bus_creds_unrefp()</function> is similar to
+ <function>sd_bus_creds_unref()</function> but takes a pointer to a
+ pointer to an <type>sd_bus_creds</type> object. This call is useful in
+ conjunction with GCC's and LLVM's <ulink
+ url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+ Variable Attribute</ulink>. Note that this function is defined as
+ inline function.</para>
+
+ <para><function>sd_bus_creds_ref()</function>,
+ <function>sd_bus_creds_unref()</function> and
+ <function>sd_bus_creds_unrefp()</function> execute no operation if
+ the passed in bus credentials object is
+ <constant>NULL</constant>.</para>
+
</refsect1>
<refsect1>
<refname>sd_bus_new</refname>
<refname>sd_bus_ref</refname>
<refname>sd_bus_unref</refname>
+ <refname>sd_bus_unrefp</refname>
<refpurpose>Create a new bus object and create or destroy references to it</refpurpose>
</refnamediv>
<funcdef>sd_bus *<function>sd_bus_unref</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_bus_unrefp</function></funcdef>
+ <paramdef>sd_bus **<parameter>bus</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
only allocate a bus object but also start the connection to a
well-known bus in a single function invocation.</para>
- <para><function>sd_bus_ref()</function> creates a new reference to
- <parameter>bus</parameter>.</para>
+ <para><function>sd_bus_ref()</function> increases the reference
+ counter of <parameter>bus</parameter> by one.</para>
- <para><function>sd_bus_unref()</function> destroys a reference to
- <parameter>bus</parameter>. Once the reference count has dropped
- to zero, <parameter>bus</parameter> cannot be used anymore, so
- further calls to <function>sd_bus_ref()</function> or
+ <para><function>sd_bus_unref()</function> decreases the reference
+ counter of <parameter>bus</parameter> by one. Once the reference
+ count has dropped to zero, <parameter>bus</parameter> is destroyed
+ and cannot be used anymore, so further calls to
+ <function>sd_bus_ref()</function> or
<function>sd_bus_unref()</function> are illegal.</para>
+
+ <para><function>sd_bus_unrefp()</function> is similar to
+ <function>sd_bus_unref()</function> but takes a pointer to a
+ pointer to an <type>sd_bus</type> object. This call is useful in
+ conjunction with GCC's and LLVM's <ulink
+ url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+ Variable Attribute</ulink>. 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:</para>
+
+ <programlisting>{
+ __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));
+ …
+}</programlisting>
+
+ <para><function>sd_bus_ref()</function>,
+ <function>sd_bus_unref()</function> and
+ <function>sd_bus_unrefp()</function> execute no operation if the
+ passed in bus object is <constant>NULL</constant>.</para>
</refsect1>
<refsect1>
positive integer. On failure, it returns a negative errno-style
error code.</para>
- <para><function>sd_bus_ref</function> always returns the argument.
+ <para><function>sd_bus_ref()</function> always returns the argument.
</para>
- <para><function>sd_bus_unref</function> always returns
+ <para><function>sd_bus_unref()</function> always returns
<constant>NULL</constant>.</para>
</refsect1>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_add_child">
+<refentry id="sd_event_add_child" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_add_child</title>
<refnamediv>
<refname>sd_event_add_child</refname>
<refname>sd_event_source_get_child_pid</refname>
+ <refname>sd_event_child_handler_t</refname>
- <refpurpose>Add a child state change event source to an event loop</refpurpose>
+ <refpurpose>Add a child process state change event source to an event loop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_child_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>const siginfo_t *<parameter>si</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_add_child</function></funcdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype>
- <funcprototype>
- <funcdef>typedef int (*<function>sd_event_child_handler_t</function>)</funcdef>
- <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
- <paramdef>const siginfo_t *<parameter>si</parameter></paramdef>
- <paramdef>void *<parameter>userdata</parameter></paramdef>
- </funcprototype>
-
<funcprototype>
<funcdef>int <function>sd_event_source_get_child_pid</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
<title>Description</title>
<para><function>sd_event_add_child()</function> adds a new child
- state change event source to an event loop object. The event loop
- is specified in <parameter>event</parameter>, the event source is
- returned in the <parameter>source</parameter> parameter. The
- <parameter>pid</parameter> parameter specifies the process to
- watch. The <parameter>handler</parameter> must reference a
- function to call when the process changes state. The handler
- function will be passed the <parameter>userdata</parameter>
- pointer, which may be chosen freely by the caller. The handler
- also receives a pointer to a <structname>const
- siginfo_t</structname> structure containing the information about
- the event. The <parameter>options</parameter> parameter determines
- which state changes will be watched for. It must contain an OR-ed
- mask of <constant>WEXITED</constant> (watch for the child
+ process state change event source to an event loop. The event loop
+ object is specified in the <parameter>event</parameter> parameter,
+ the event source object is returned in the
+ <parameter>source</parameter> parameter. The
+ <parameter>pid</parameter> parameter specifies the PID of the
+ process to watch. The <parameter>handler</parameter> must
+ reference a function to call when the process changes state. The
+ handler function will be passed the
+ <parameter>userdata</parameter> pointer, which may be chosen
+ freely by the caller. The handler also receives a pointer to a
+ <structname>siginfo_t</structname> structure containing
+ information about the child process event. The
+ <parameter>options</parameter> parameter determines which state
+ changes will be watched for. It must contain an OR-ed mask of
+ <constant>WEXITED</constant> (watch for the child process
terminating), <constant>WSTOPPED</constant> (watch for the child
- being stopped by a signal), and <constant>WCONTINUED</constant>
- (watch for the child being resumed by a signal). See
- <citerefentry><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ process being stopped by a signal), and
+ <constant>WCONTINUED</constant> (watch for the child process being
+ resumed by a signal). See <citerefentry
+ project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for further information.</para>
<para>Only a single handler may be installed for a specific
- child. The handler is enabled
- for a single event (<constant>SD_EVENT_ONESHOT</constant>),
- but this may be
- changed with
+ child process. The handler is enabled for a single event
+ (<constant>SD_EVENT_ONESHOT</constant>), but this may be changed
+ with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
If the handler function returns a negative error code, it will be
- disabled after the invocation, even if
- <constant>SD_EVENT_ON</constant> mode is set.
+ disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before.
</para>
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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
+ <constant>SD_EVENT_OFF</constant> with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>If the second parameter of
+ <function>sd_event_add_child()</function> 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.</para>
+
+ <para>Note that the <parameter>handler</parameter> 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.</para>
+
+ <para>If both a child process state change event source and a
+ <constant>SIGCHLD</constant> 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.</para>
+
<para><function>sd_event_source_get_child_pid()</function>
- retrieves the configured <parameter>pid</parameter> of a child
- state change event source created previously with
+ retrieves the configured PID of a child process state change event
+ source created previously with
<function>sd_event_add_child()</function>. It takes the event
source object as the <parameter>source</parameter> parameter and a
- pointer to <type>pid_t</type> to return the result in.
+ pointer to a <type>pid_t</type> variable to return the process ID
+ in.
</para>
</refsect1>
<term><constant>-EBUSY</constant></term>
<listitem><para>A handler is already installed for this
- child.</para></listitem>
+ child process.</para></listitem>
</varlistentry>
</varlistentry>
- </variablelist>
- </refsect1>
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
- <refsect1>
- <title>Notes</title>
+ <listitem><para>The passed event source is not a child process event source.</para></listitem>
+ </varlistentry>
- <para><function>sd_event_add_child()</function> and the other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ </variablelist>
</refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
<refsect1>
<title>See Also</title>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_add_defer">
+<refentry id="sd_event_add_defer" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_add_defer</title>
<refname>sd_event_add_defer</refname>
<refname>sd_event_add_post</refname>
<refname>sd_event_add_exit</refname>
+ <refname>sd_event_handler_t</refname>
<refpurpose>Add static event sources to an event loop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_add_defer</function></funcdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype>
- <funcprototype>
- <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
- <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
- <paramdef>void *<parameter>userdata</parameter></paramdef>
- </funcprototype>
-
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para>These three functions add new event sources to an event loop
- object. The event loop is specified in
- <parameter>event</parameter>, the event source is returned in the
- <parameter>source</parameter> 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 <parameter>userdata</parameter> pointer, which may
- be chosen freely by the caller.</para>
+ <para>These three functions add new static event sources to an
+ event loop. The event loop object is specified in the
+ <parameter>event</parameter> parameter, the event source object is
+ returned in the <parameter>source</parameter> 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 <parameter>userdata</parameter>
+ pointer, which may be chosen freely by the caller.</para>
<para><function>sd_event_add_defer()</function> adds a new event
- source that will "fire" the next time the event loop is run. By
- default, the handler will be called once
- (<constant>SD_EVENT_ONESHOT</constant>).</para>
+ 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
+ (<constant>SD_EVENT_ONESHOT</constant>). Note that if the event
+ source is set to <constant>SD_EVENT_ON</constant> the event loop
+ will never go to sleep again, but continuously call the handler,
+ possibly interleaved with other event sources.</para>
<para><function>sd_event_add_post()</function> adds a new event
- source that will "fire" if any event handlers are invoked whenever
- the event loop is run. By default, the source is enabled
- permanently (<constant>SD_EVENT_ON</constant>).</para>
+ 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 (<constant>SD_EVENT_ON</constant>). Note that this
+ event source type will still allow the event loop to go to sleep
+ again, even if set to <constant>SD_EVENT_ON</constant>, as long as
+ no other event source is ever triggered.</para>
<para><function>sd_event_add_exit()</function> adds a new event
- source that will "fire" when the event loop is terminated
- with <function>sd_event_exit()</function>.</para>
+ source that will be dispatched when the event loop is terminated
+ with <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>The
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
function may be used to enable the event source permanently
(<constant>SD_EVENT_ON</constant>) or to make it fire just once
- (<constant>SD_EVENT_ONESHOT</constant>). If the handler function
- returns a negative error code, it will be disabled after the
- invocation, even if <constant>SD_EVENT_ON</constant> mode is
- set.</para>
+ (<constant>SD_EVENT_ONESHOT</constant>).</para>
+
+ <para>If the handler function returns a negative error code, it
+ will be disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before.</para>
+
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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
+ <constant>SD_EVENT_OFF</constant> with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>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.</para>
</refsect1>
<refsect1>
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>Functions described here are available as a shared library,
- which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_add_io" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_add_io</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_add_io</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_add_io</refname>
+ <refname>sd_event_source_get_io_events</refname>
+ <refname>sd_event_source_set_io_events</refname>
+ <refname>sd_event_source_get_io_revents</refname>
+ <refname>sd_event_source_get_io_fd</refname>
+ <refname>sd_event_source_set_io_fd</refname>
+ <refname>sd_event_source</refname>
+ <refname>sd_event_io_handler_t</refname>
+
+ <refpurpose>Add an I/O event source to an event loop</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_io_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>uint32_t <parameter>revents</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_add_io</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>uint32_t <parameter>events</parameter></paramdef>
+ <paramdef>sd_event_io_handler_t <parameter>handler</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_io_events</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>uint32_t *<parameter>events</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_io_events</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>uint32_t <parameter>events</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_io_revents</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>uint32_t *<parameter>revents</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_io_fd</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_io_fd</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_add_io()</function> adds a new I/O event
+ source to an event loop. The event loop object is specified in the
+ <parameter>event</parameter> parameter, the event source object is
+ returned in the <parameter>source</parameter> parameter. The
+ <parameter>fd</parameter> 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
+ <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
+ <parameter>events</parameter> parameter takes a bit mask of events
+ to watch for, a combination of the following event flags:
+ <constant>EPOLLIN</constant>, <constant>EPOLLOUT</constant>,
+ <constant>EPOLLRDHUP</constant>, <constant>EPOLLPRI</constant>,
+ and <constant>EPOLLET</constant>, see
+ <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for details. The <parameter>handler</parameter> shall reference a
+ function to call when the event source is triggered. The
+ <parameter>userdata</parameter> 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
+ <constant>EPOLLERR</constant> and <constant>EPOLLHUP</constant>.
+ </para>
+
+ <para>By default, an event source will stay enabled
+ continuously (<constant>SD_EVENT_ON</constant>), but this may be
+ changed with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ If the handler function returns a negative error code, it will be
+ disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before. Note
+ that an event source set to <constant>SD_EVENT_ON</constant> will
+ fire continuously unless data is read from or written to the file
+ descriptor to reset the mask of events seen.
+ </para>
+
+ <para>Setting the I/O event mask to watch for to 0 does not mean
+ that the event source won't be triggered anymore, as
+ <constant>EPOLLHUP</constant> and <constant>EPOLLERR</constant>
+ may be triggered even with a zero event mask. To temporarily
+ disable an I/O event source use
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with <constant>SD_EVENT_OFF</constant> instead.</para>
+
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with <constant>SD_EVENT_OFF</constant>.</para>
+
+ <para>If the second parameter of
+ <function>sd_event_add_io()</function> is
+ <constant>NULL</constant> 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.</para>
+
+ <para>It is recommended to use
+ <function>sd_event_add_io()</function> only in conjunction with
+ file descriptors that have <constant>O_NONBLOCK</constant> set, to
+ ensure that all I/O operations from invoked handlers are properly
+ asynchronous and non-blocking. Using file descriptors without
+ <constant>O_NONBLOCK</constant> might result in unexpected
+ starvation of other event sources. See
+ <citerefentry project='man-pages'><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for details on enabling <constant>O_NONBLOCK</constant> mode.</para>
+
+ <para><function>sd_event_source_get_io_events()</function> retrieves
+ the configured mask of watched I/O events of an event source created
+ previously with <function>sd_event_add_io()</function>. It takes
+ the event source object and a pointer to a variable to store the
+ mask in.</para>
+
+ <para><function>sd_event_source_set_io_events()</function>
+ configures the mask of watched I/O events of an event source created
+ previously with <function>sd_event_add_io()</function>. It takes the
+ event source object and the new event mask.</para>
+
+ <para><function>sd_event_source_get_io_revents()</function>
+ retrieves the I/O event mask of currently seen but undispatched
+ events from an event source created previously with
+ <function>sd_event_add_io()</function>. 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 <parameter>revents</parameter> 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
+ <function>sd_event_source_get_pending()</function> and
+ <function>sd_event_source_get_io_revents()</function>: 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.</para>
+
+ <para><function>sd_event_source_get_io_fd()</function> retrieves
+ the UNIX file descriptor of an event source created previously
+ with <function>sd_event_add_io()</function>. It takes the event
+ source object and returns the non-negative file descriptor
+ or a negative error number on error (see below).</para>
+
+ <para><function>sd_event_source_set_io_fd()</function>
+ changes the UNIX file descriptor of an I/O event source created
+ previously with <function>sd_event_add_io()</function>. It takes
+ the event source object and the new file descriptor.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive
+ integer. On failure, they return a negative errno-style error
+ code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned values may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory to allocate an object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>An invalid argument has been passed.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para>The passed event source is not an I/O event source.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_add_signal">
+<refentry id="sd_event_add_signal" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_add_signal</title>
<refnamediv>
<refname>sd_event_add_signal</refname>
<refname>sd_event_source_get_signal</refname>
+ <refname>sd_event_signal_handler_t</refname>
- <refpurpose>Add a signal event source to an event loop</refpurpose>
+ <refpurpose>Add a UNIX process signal event source to an event
+ loop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_signal_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>const struct signalfd_siginfo *<parameter>si</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_add_signal</function></funcdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype>
- <funcprototype>
- <funcdef>typedef int (*<function>sd_event_signal_handler_t</function>)</funcdef>
- <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
- <paramdef>const struct signalfd_siginfo *<parameter>si</parameter></paramdef>
- <paramdef>void *<parameter>userdata</parameter></paramdef>
- </funcprototype>
-
<funcprototype>
<funcdef>int <function>sd_event_source_get_signal</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
<refsect1>
<title>Description</title>
- <para><function>sd_event_add_signal()</function> adds a new signal
- event source to an event loop object. The event loop is specified
- in <parameter>event</parameter>, and the event source is returned in
- the <parameter>source</parameter> parameter. The
- <parameter>signal</parameter> parameter specifies the signal to be handled
- (see
- <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
- The <parameter>handler</parameter> must reference a function to
- call when the signal is delivered or be <constant>NULL</constant>.
- The handler function will be passed the
- <parameter>userdata</parameter> pointer, which may be chosen
+ <para><function>sd_event_add_signal()</function> adds a new UNIX
+ process signal event source to an event loop. The event loop
+ object is specified in the <parameter>event</parameter> parameter,
+ and the event source object is returned in the
+ <parameter>source</parameter> parameter. The
+ <parameter>signal</parameter> parameter specifies the numeric
+ signal to be handled (see <citerefentry
+ project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
+ The <parameter>handler</parameter> parameter must reference a
+ function to call when the signal is received or be
+ <constant>NULL</constant>. The handler function will be passed
+ the <parameter>userdata</parameter> pointer, which may be chosen
freely by the caller. The handler also receives a pointer to a
- <structname>const struct signalfd_siginfo</structname> containing
- the information about the received signal. See
- <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ <structname>signalfd_siginfo</structname> structure containing
+ information about the received signal. See <citerefentry
+ project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for further information.</para>
<para>Only a single handler may be installed for a specific
- signal. The signal will be unblocked, and must be
- blocked when the function is called. If the handler is not
- specified (<parameter>handler</parameter> is
+ signal. The signal will be unblocked by this call, and must be
+ blocked before this function is called in all threads (using
+ <citerefentry
+ project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry>). If
+ the handler is not specified (<parameter>handler</parameter> is
<constant>NULL</constant>), a default handler which causes the
- program to exit will be used. By default, the handler is enabled
- permanently (<constant>SD_EVENT_ON</constant>), but this may be
- changed with
+ program to exit cleanly will be used.</para>
+
+ <para>By default, the event source is enabled permanently
+ (<constant>SD_EVENT_ON</constant>), but this may be changed with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
If the handler function returns a negative error code, it will be
- disabled after the invocation, even if
- <constant>SD_EVENT_ON</constant> mode is set.
+ disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before.
</para>
- <para><function>sd_event_source_get_signal()</function> retrieves
- the configured signal number of a signal event source created
- previously with <function>sd_event_add_signal()</function>. It
- takes the event source object as the <parameter>source</parameter>
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with <constant>SD_EVENT_OFF</constant>.</para>
+
+ <para>If the second parameter of
+ <function>sd_event_add_signal()</function> is
+ <constant>NULL</constant> 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.</para>
+
+ <para><function>sd_event_source_get_signal()</function> returns
+ the configured signal number of an event source created previously
+ with <function>sd_event_add_signal()</function>. It takes the
+ event source object as the <parameter>source</parameter>
parameter.</para>
-
</refsect1>
<refsect1>
<para>On success, these functions return 0 or a positive
integer. On failure, they return a negative errno-style error
- code. </para>
+ code.</para>
</refsect1>
<refsect1>
<term><constant>-EINVAL</constant></term>
<listitem><para>An invalid argument has been passed.</para></listitem>
-
</varlistentry>
<varlistentry>
<listitem><para>A handler is already installed for this
signal or the signal was not blocked previously.</para></listitem>
-
</varlistentry>
<varlistentry>
<term><constant>-ESTALE</constant></term>
<listitem><para>The event loop is already terminated.</para></listitem>
-
</varlistentry>
<varlistentry>
<term><constant>-ECHILD</constant></term>
<listitem><para>The event loop has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+ <listitem><para>The passed event source is not a signal event source.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_event_add_signal()</function> and the other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_add_time">
+<refentry id="sd_event_add_time" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_add_time</title>
<refname>sd_event_source_get_time_accuracy</refname>
<refname>sd_event_source_set_time_accuracy</refname>
<refname>sd_event_source_get_time_clock</refname>
+ <refname>sd_event_time_handler_t</refname>
<refpurpose>Add a timer event source to an event loop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_time_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>uint64_t <parameter>usec</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_add_time</function></funcdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype>
- <funcprototype>
- <funcdef>typedef int (*<function>sd_event_time_handler_t</function>)</funcdef>
- <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
- <paramdef>uint64_t <parameter>usec</parameter></paramdef>
- <paramdef>void *<parameter>userdata</parameter></paramdef>
- </funcprototype>
-
<funcprototype>
<funcdef>int <function>sd_event_source_get_time</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>usec_t *<parameter>usec</parameter></paramdef>
+ <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_source_set_time</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>usec_t <parameter>usec</parameter></paramdef>
+ <paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_source_get_time_accuracy</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>usec_t *<parameter>usec</parameter></paramdef>
+ <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_source_set_time_accuracy</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>usec_t <parameter>usec</parameter></paramdef>
+ <paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<refsect1>
<title>Description</title>
- <para><function>sd_event_add_time()</function> adds a new timer
- event source to an event loop object. The event loop is specified
- in <parameter>event</parameter>, the event source is returned in
- the <parameter>source</parameter> parameter. The
- <parameter>clock</parameter> parameter takes a clock identifier,
- one of <constant>CLOCK_REALTIME</constant>,
- <constant>CLOCK_MONOTONIC</constant> and
- <constant>CLOCK_BOOTTIME_ALARM</constant>. See
- <citerefentry><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- for details regarding the various types of clocks. The
- <parameter>usec</parameter> parameter takes a time value in
- microseconds, relative to the clock's epoch specifying when the
- timer shall elapse the earliest. The
- <parameter>accuracy</parameter> parameter takes an additional
- accuracy value in microseconds specifying a time the timer event
- may be delayed. Specify 0 for selecting the default accuracy
- (250ms). Specify 1 for most accurate timers. Consider specifying
- 60000000 or larger (1h) for long-running events that may be
- delayed substantially. Picking higher accuracy values allows the
- system to coalesce timer events more aggressively, thus improving
- power efficiency. The <parameter>handler</parameter> shall
- reference a function to call when the timer elapses. The handler
- function will be passed the <parameter>userdata</parameter>
- pointer, which may be chosen freely by the caller. The handler is
- also passed the configured time it was triggered, however it might
- actually have been called at a slightly later time, subject to the
- specified accuracy value, the kernel timer slack (see
- <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>)
- and additional scheduling latencies.</para>
+ <para><function>sd_event_add_time()</function> adds a new timer event source to an event loop. The event loop
+ object is specified in the <parameter>event</parameter> parameter, the event source object is returned in the
+ <parameter>source</parameter> parameter. The <parameter>clock</parameter> parameter takes a clock identifier, one
+ of <constant>CLOCK_REALTIME</constant>, <constant>CLOCK_MONOTONIC</constant>, <constant>CLOCK_BOOTTIME</constant>,
+ <constant>CLOCK_REALTIME_ALARM</constant>, or <constant>CLOCK_BOOTTIME_ALARM</constant>. See
+ <citerefentry><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details
+ regarding the various types of clocks. The <parameter>usec</parameter> 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 <constant>0</constant>), this timer source "fires" immediately and is ready to be
+ dispatched. If the paramater is specified as <constant>UINT64_MAX</constant> the timer event will never elapse,
+ which may be used as an alternative to explicitly disabling a timer event source with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>. The
+ <parameter>accuracy</parameter> parameter specifies an additional accuracy value in µs specifying how much the
+ timer event may be delayed. Use <constant>0</constant> 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 <parameter>handler</parameter> parameter shall reference a function to call when
+ the timer elapses. The handler function will be passed the <parameter>userdata</parameter> 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
+ <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), and additional
+ scheduling latencies. To query the actual time the handler was called use
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>By default, the timer will elapse once
(<constant>SD_EVENT_ONESHOT</constant>), but this may be changed
with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
If the handler function returns a negative error code, it will be
- disabled after the invocation, even if
- <constant>SD_EVENT_ON</constant> mode is set.
+ disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before. Note
+ that a timer event set to <constant>SD_EVENT_ON</constant> will
+ fire continuously unless its configured time is updated using
+ <function>sd_event_source_set_time()</function>.
</para>
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with <constant>SD_EVENT_OFF</constant>.</para>
+
+ <para>If the second parameter of
+ <function>sd_event_add_time()</function> is
+ <constant>NULL</constant> 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.</para>
+
+ <para>If the <parameter>handler</parameter> to
+ <function>sd_event_add_time()</function> is
+ <constant>NULL</constant>, and the event source fires, this will
+ be considered a request to exit the event loop. In this case, the
+ <parameter>userdata</parameter> parameter, cast to an integer, is
+ used for the exit code passed to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and
+ <constant>CLOCK_REALTIME_ALARM</constant> to define event sources
+ that may wake up the system from suspend.</para>
+
+ <para>In order to set up relative timers (that is, relative to the
+ current time), retrieve the current time via
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ add the desired timespan to it, and use the result as
+ the <parameter>usec</parameter> parameter to
+ <function>sd_event_add_time()</function>.</para>
+
+ <para>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
+ <citerefentry><refentrytitle>sd_event_source_set_time</refentrytitle><manvolnum>3</manvolnum></citerefentry> for the next timer
+ iteration, and reenable the timer using
+ <function>sd_event_source_set_enabled()</function>. To calculate
+ the next point in time to pass to
+ <function>sd_event_source_set_time()</function>, either use as
+ base the <parameter>usec</parameter> parameter passed to the timer
+ callback, or the timestamp returned by
+ <function>sd_event_now()</function>. In the former case timer
+ events will be regular, while in the latter case the scheduling
+ latency will keep accumulating on the timer.</para>
+
<para><function>sd_event_source_get_time()</function> retrieves
- the configured time value of a timer event source created
+ the configured time value of an event source created
previously with <function>sd_event_add_time()</function>. It takes
the event source object and a pointer to a variable to store the
- time in microseconds in.</para>
+ time in, relative to the selected clock's epoch, in µs.</para>
<para><function>sd_event_source_set_time()</function> changes the
- configured time value of a timer event source created previously
- with <function>sd_event_add_time()</function>. It takes the event
- source object and a time relative to the selected clock's
- epoch, in microseconds.</para>
+ time of an event source created previously with
+ <function>sd_event_add_time()</function>. It takes the event
+ source object and a time relative to the selected clock's epoch,
+ in µs.</para>
<para><function>sd_event_source_get_time_accuracy()</function>
- retrieves the configured accuracy value of a timer event source
+ retrieves the configured accuracy value of a event source
created previously with <function>sd_event_add_time()</function>. It
takes the event source object and a pointer to a variable to store
- the accuracy in microseconds in.</para>
+ the accuracy in. The accuracy is specified in µs.</para>
<para><function>sd_event_source_set_time_accuracy()</function>
changes the configured accuracy of a timer event source created
previously with <function>sd_event_add_time()</function>. It takes
- the event source object and an accuracy, in microseconds.</para>
+ the event source object and accuracy, in µs.</para>
<para><function>sd_event_source_get_time_clock()</function>
- retrieves the configured clock of a timer event source created
+ retrieves the configured clock of a event source created
previously with <function>sd_event_add_time()</function>. It takes
the event source object and a pointer to a variable to store the
clock identifier in.</para>
-
</refsect1>
<refsect1>
<refsect1>
<title>Errors</title>
- <para>Returned errors may indicate the following problems:</para>
+ <para>Returned values may indicate the following problems:</para>
<variablelist>
<varlistentry>
<listitem><para>The selected clock is not supported by the event loop implementation.</para></listitem>
</varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Notes</title>
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
- <para><function>sd_event_add_time()</function> and the other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <listitem><para>The passed event source is not a timer event source.</para></listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
<refsect1>
<title>See Also</title>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_exit" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_exit</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_exit</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_exit</refname>
+ <refname>sd_event_get_exit_code</refname>
+
+ <refpurpose>Ask the event loop to exit</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_exit</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>int <parameter>code</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_get_exit_code</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>int *<parameter>code</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_exit()</function> requests the event loop
+ specified in the <parameter>event</parameter> event loop object to
+ exit. The <parameter>code</parameter> parameter may be any integer
+ value and is returned as-is by
+ <citerefentry><refentrytitle>sd_event_loop</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ after the last event loop iteration. It may also be queried
+ using <function>sd_event_get_exit_code()</function>, see
+ below. </para>
+
+ <para>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
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ in the order defined by their priority. After all exit event
+ sources have been dispatched the event loop is terminated.</para>
+
+ <para>If <function>sd_event_exit()</function> 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.</para>
+
+ <para><function>sd_event_get_exit_code()</function> may be used to
+ query the exit code passed into
+ <function>sd_event_exit()</function> earlier.</para>
+
+ <para>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
+ <function>sd_event_loop()</function>, if these exit codes shall be
+ distinguishable.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_exit()</function> and
+ <function>sd_event_get_exit_code()</function> return 0 or a positive
+ integer. On failure, they return a negative errno-style error
+ code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The event loop object or error code pointer are invalid.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop was created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop has exited already and all exit handlers are already processed.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENODATA</constant></term>
+
+ <listitem><para>The event loop has not been requested to exit yet.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_get_fd"
- xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="sd_event_get_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_get_fd</title>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_event_get_fd</function></funcdef>
- <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<title>Description</title>
<para><function>sd_event_get_fd()</function> returns the file
- descriptor that the event loop object returned by the
+ descriptor that an event loop object returned by the
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- function uses to wait for events. This file descriptor can be
- polled for events. This makes it possible to embed the
+ function uses to wait for events. This file descriptor may itself
+ be polled for
+ <constant>POLLIN</constant>/<constant>EPOLLIN</constant>
+ events. This makes it possible to embed an
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- event loop inside of another event loop.</para>
+ event loop into another, possibly foreign, event loop.</para>
+
+ <para>The returned file descriptor refers to an <citerefentry
+ project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ object. It is recommended not to alter it by invoking
+ <citerefentry
+ project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ on it, in order to avoid interference with the event loop's inner
+ logic and assumptions.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, <function>sd_event_get_fd()</function> returns a
- non-negative integer. On failure, it returns a negative
+ non-negative file descriptor. On failure, it returns a negative
errno-style error code.</para>
</refsect1>
<title>Examples</title>
<example>
- <title>Integration in glib event loop</title>
+ <title>Integration in the GLib event loop</title>
<programlisting><xi:include href="glib-event-glue.c" parse="text" /></programlisting>
</example>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_event_get_fd()</function> is available as a
- shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_new">
+<refentry id="sd_event_new" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_new</title>
<refname>sd_event_default</refname>
<refname>sd_event_ref</refname>
<refname>sd_event_unref</refname>
+ <refname>sd_event_unrefp</refname>
+ <refname>sd_event_get_tid</refname>
+ <refname>sd_event</refname>
<refpurpose>Acquire and release an event loop object</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event sd_event;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_event_new</function></funcdef>
- <paramdef>sd_bus **<parameter>event</parameter></paramdef>
+ <paramdef>sd_event **<parameter>event</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_default</function></funcdef>
- <paramdef>sd_bus **<parameter>event</parameter></paramdef>
+ <paramdef>sd_event **<parameter>event</parameter></paramdef>
</funcprototype>
<funcprototype>
- <funcdef>sd_bus *<function>sd_event_ref</function></funcdef>
- <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+ <funcdef>sd_event *<function>sd_event_ref</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
</funcprototype>
<funcprototype>
- <funcdef>sd_bus *<function>sd_event_unref</function></funcdef>
- <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+ <funcdef>sd_event *<function>sd_event_unref</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_event_unrefp</function></funcdef>
+ <paramdef>sd_event **<parameter>event</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_get_tid</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>pid_t *<parameter>tid</parameter></paramdef>
</funcprototype>
</funcsynopsis>
thread. All threads have exactly either zero or one default event loop
objects associated, but never more.</para>
+ <para>After allocating an event loop object, add event sources to
+ it with
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ and then execute the event loop using
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
<para><function>sd_event_ref()</function> increases the reference
count of the specified event loop object by one.</para>
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.</para>
+
+ <para><function>sd_event_unrefp()</function> is similar to
+ <function>sd_event_unref()</function> but takes a pointer to a
+ pointer to an <type>sd_event</type> object. This call is useful in
+ conjunction with GCC's and LLVM's <ulink
+ url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+ Variable Attribute</ulink>. 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:</para>
+
+ <programlisting>{
+ __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));
+ …
+}</programlisting>
+
+ <para><function>sd_event_ref()</function>,
+ <function>sd_event_unref()</function> and
+ <function>sd_event_unrefp()</function> execute no operation if the
+ passed in event loop object is <constant>NULL</constant>.</para>
+
+ <para><function>sd_event_get_tid()</function> 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 <function>sd_event_default()</function>, and
+ returns the identifier for the thread the event loop is the
+ default event loop of. See <citerefentry
+ project='man-pages'><refentrytitle>gettid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for more information on thread identifiers.</para>
</refsect1>
<refsect1>
<listitem><para>The maximum number of event loops has been allocated.</para></listitem>
</varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Notes</title>
+ <varlistentry>
+ <term><constant>-ENXIO</constant></term>
- <para><function>sd_event_new()</function> and the other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <listitem><para><function>sd_event_get_tid()</function> was
+ invoked on an event loop object that was not allocated with
+ <function>sd_event_default()</function>.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
</refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
<refsect1>
<title>See Also</title>
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>gettid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_now" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_now</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_now</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_now</refname>
+
+ <refpurpose>Retrieve current event loop iteration timestamp</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_now</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>clockid_t <parameter>clock</parameter></paramdef>
+ <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_now()</function> 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 <parameter>event</parameter>
+ parameter specifies the event loop object to retrieve the timestamp
+ from. The <parameter>clock</parameter> parameter specifies the clock to
+ retrieve the timestamp for, and is one of
+ <constant>CLOCK_REALTIME</constant> (or equivalently
+ <constant>CLOCK_REALTIME_ALARM</constant>),
+ <constant>CLOCK_MONOTONIC</constant>, or
+ <constant>CLOCK_BOOTTIME</constant> (or equivalently
+ <constant>CLOCK_BOOTTIME_ALARM</constant>), see
+ <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for more information on the various clocks. The retrieved
+ timestamp is stored in the <parameter>usec</parameter> 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 <function>clock_gettime()</function>. 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.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>If the first event loop iteration has not run yet
+ <function>sd_event_now()</function> writes current time to
+ <parameter>usec</parameter> and returns a positive return value.
+ Otherwise, it will write the requested timestamp to <parameter>usec</parameter>
+ and return 0. On failure, the call returns a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned values may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>An invalid parameter was
+ passed.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EOPNOTSUPP</constant></term>
+
+ <listitem><para>Unsupported clock type.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop object was created in a
+ different process.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_run">
+<refentry id="sd_event_run" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_run</title>
<refname>sd_event_run</refname>
<refname>sd_event_loop</refname>
- <refpurpose>Run the libsystemd event loop</refpurpose>
+ <refpurpose>Run an event loop</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcprototype>
<funcdef>int <function>sd_event_run</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
- <paramdef>uint64_t <parameter>timeout</parameter></paramdef>
+ <paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<refsect1>
<title>Description</title>
- <para><function>sd_event_run()</function> can be used to run one
- iteration of the event loop of libsystemd. This function waits
- until an event to process is available, and dispatches a handler
- for it. The <parameter>timeout</parameter> parameter specifices the
- maximum time (in microseconds) to wait. <constant>(uint64_t)
- -1</constant> may be used to specify an infinite timeout.</para>
-
- <para><function>sd_event_loop</function> runs
- <function>sd_event_wait</function> in a loop with a timeout of
- infinity. This makes it suitable for the main event loop of a
- program.</para>
+ <para><function>sd_event_run()</function> may be used to run a single
+ iteration of the event loop specified in the
+ <parameter>event</parameter> parameter. The function waits until an event to
+ process is available, and dispatches the registered handler for
+ it. The <parameter>usec</parameter> parameter specifies the
+ maximum time (in microseconds) to wait for an event. Use
+ <constant>(uint64_t) -1</constant> to specify an infinite
+ timeout.</para>
+
+ <para><function>sd_event_loop()</function> invokes
+ <function>sd_event_run()</function> in a loop, thus implementing
+ the actual event loop. The call returns as soon as exiting was
+ requested using
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>The event loop object <parameter>event</parameter> is
created with
- <function>sd_event_new</function>.
- Events to wait for and their handlers can be registered with
- <function>sd_event_add_time</function>,
- <function>sd_event_add_child</function>,
- <function>sd_event_add_signal</function>,
- <function>sd_event_add_defer</function>,
- <function>sd_event_add_exit</function>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ Events sources to wait for and their handlers may be registered
+ with
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
- <function>sd_event_add_post</function>.
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
- <para>For more fine-grained control,
- <function>sd_event_prepare</function>,
- <function>sd_event_wait</function>, and
- <function>sd_event_dispatch</function> may be used. Along with
- <function>sd_event_get_fd</function>, those functions make it
- possible to integrate the libsystemd loop inside of another event
- loop.</para>
+ <para>For low-level control of event loop execution, use
+ <citerefentry><refentrytitle>sd_event_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>sd_event_dispatch</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ which are wrapped by <function>sd_event_run()</function>. Along
+ with
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ these functions allow integration of an
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ event loop into foreign event loop implementations.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
- <para>On success, these functions return 0 or a positive integer.
- On failure, they return a negative errno-style error code.
- <function>sd_event_run</function> returns 0 if the event loop is
- finished, and a positive value if it can be continued.</para>
+ <para>On failure, these functions return a negative errno-style
+ error code. <function>sd_event_run()</function> 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. <function>sd_event_loop()</function> returns the exit
+ code specified when invoking
+ <function>sd_event_exit()</function>.</para>
</refsect1>
<refsect1>
<term><constant>-EINVAL</constant></term>
<listitem><para>The <parameter>event</parameter> parameter is
- <constant>NULL</constant>.</para></listitem>
+ invalid or <constant>NULL</constant>.</para></listitem>
</varlistentry>
<varlistentry>
<para>Other errors are possible, too.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_event_run()</function> and
- <function>sd_event_loop()</function> are available
- as a shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<ulink url="https://developer.gnome.org/glib/unstable/glib-The-Main-Event-Loop.html">GLib Main Event Loop</ulink>.
</para>
</refsect1>
+++ /dev/null
-<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
- 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 <http://www.gnu.org/licenses/>.
--->
-
-<refentry id="sd_event_set_name"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
- <refentryinfo>
- <title>sd_event_set_name</title>
- <productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>sd_event_set_name</refentrytitle>
- <manvolnum>3</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>sd_event_set_name</refname>
- <refname>sd_event_get_name</refname>
-
- <refpurpose>Set human-readable names for event sources</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
-
- <funcprototype>
- <funcdef>int <function>sd_event_set_name</function></funcdef>
- <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>const char *<parameter>name</parameter></paramdef>
- </funcprototype>
-
- <funcprototype>
- <funcdef>int <function>sd_event_get_name</function></funcdef>
- <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>const char **<parameter>name</parameter></paramdef>
- </funcprototype>
-
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para><function>sd_event_set_name()</function> can be used to set
- an arbitrary name for the event source
- <parameter>source</parameter>. This name will be used in error
- messages generated by
- <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- for this source. The <parameter>name</parameter> must point
- to a <constant>NUL</constant>-terminated string or be
- <constant>NULL</constant>. In the latter case, the name will be
- unset. The string is copied internally, so the
- <parameter>name</parameter> argument is not referenced after the
- function returns.</para>
-
- <para><function>sd_event_set_name()</function> can be used to
- query the current name assigned to source
- <parameter>source</parameter>. It returns a pointer to the current
- name (possibly <constant>NULL</constant>) in
- <parameter>name</parameter>.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, <function>sd_event_set_name()</function> and
- <function>sd_event_get_name()</function> return a
- non-negative integer. On failure, they return a negative
- errno-style error code.</para>
- </refsect1>
-
- <refsect1>
- <title>Errors</title>
-
- <para>Returned errors may indicate the following problems:</para>
-
- <variablelist>
- <varlistentry>
- <term><constant>-EINVAL</constant></term>
-
- <listitem><para><parameter>source</parameter> is not a valid
- pointer to an <structname>sd_event_source</structname>
- structure or the <parameter>name</parameter> argument for
- <function>sd_event_get_name()</function> is
- <constant>NULL</constant>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>-ENOMEM</constant></term>
-
- <listitem><para>Not enough memory to copy the
- name.</para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <para>The functions described here are available as a
- shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <para>
- <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- </para>
- </refsect1>
-
-</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_set_watchdog" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_set_watchdog</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_set_watchdog</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_set_watchdog</refname>
+ <refname>sd_event_get_watchdog</refname>
+
+ <refpurpose>Enable event loop watchdog support</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_set_watchdog</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>int b</paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_get_watchdog</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_set_watchdog()</function> may be used to
+ enable or disable automatic watchdog notification support in the
+ event loop object specified in the <parameter>event</parameter>
+ parameter. Specifically, depending on the <parameter>b</parameter>
+ 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
+ <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ and watchdog messages are sent with
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>. See
+ the <varname>WatchdogSec=</varname> setting in
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ 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
+ <varname>$WATCHDOG_USEC</varname> 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 <parameter>b</parameter> parameter executes no
+ operation. Passing a false <parameter>b</parameter> parameter will
+ disable the automatic sending of watchdog notification messages if
+ it was enabled before. Newly allocated event loop objects have
+ this feature disabled.</para>
+
+ <para>The first watchdog notification message is sent immediately
+ when <function>set_event_set_watchdog()</function> is invoked with
+ a true <parameter>b</parameter> parameter.</para>
+
+ <para>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.</para>
+
+ <para><function>sd_event_get_watchdog()</function> may be used to
+ determine whether watchdog support was previously requested by a
+ call to <function>sd_event_set_watchdog()</function> with a true
+ <parameter>b</parameter> parameter and successfully
+ enabled.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_set_watchdog()</function> and
+ <function>sd_event_get_watchdog()</function> 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
+ <parameter>b</parameter> parameter. On failure, they return a
+ negative errno-style error
+ code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The passed event loop object was invalid.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_get_event" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_get_event</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_get_event</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_get_event</refname>
+
+ <refpurpose>Retrieve the event loop of an event source</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>sd_event* <function>sd_event_source_get_event</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_get_event()</function> may be used
+ to retrieve the event loop object the event source object specified
+ as <parameter>source</parameter> is associated with. The event
+ loop object is specified when creating an event source object with
+ calls such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_get_event()</function>
+ returns the associated event loop object. On failure, it returns
+ NULL.</para>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_get_pending" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_get_pending</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_get_pending</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_get_pending</refname>
+
+ <refpurpose>Determine pending state of event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_pending</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_get_pending()</function> may be
+ used to determine whether the event source object specified as
+ <parameter>source</parameter> has seen events but has not been
+ dispatched yet (and thus is marked "pending").</para>
+
+ <para>Event source objects initially are not marked pending, when
+ they are created with calls such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ with the exception of those created with
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ which are immediately marked pending, and
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for which the "pending" concept is not defined. For details see
+ the respective manual pages.</para>
+
+ <para>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
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>For I/O event sources, as created with
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ the call
+ <citerefentry><refentrytitle>sd_event_source_get_io_revents</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ may be used to query the type of event pending in more
+ detail.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success,
+ <function>sd_event_source_get_pending()</function> 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.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid
+ pointer to an <structname>sd_event_source</structname>
+ object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para><parameter>source</parameter> refers to an
+ event source object created with
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_description" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_description</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>More text</contrib>
+ <firstname>Zbigniew</firstname>
+ <surname>Jędrzejewski-Szmek</surname>
+ <email>zbyszek@in.waw.pl</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_description</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_description</refname>
+ <refname>sd_event_source_get_description</refname>
+
+ <refpurpose>Set or retrieve descriptive names of event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_description</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>const char *<parameter>description</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_description</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>const char **<parameter>description</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_description()</function> may
+ be used to set an arbitrary descriptive name for the event source
+ object specified as <parameter>source</parameter>. This name will
+ be used in debugging messages generated by
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for this event source, and may be queried using
+ <function>sd_event_source_get_description()</function> for
+ debugging purposes. The <parameter>description</parameter> parameter shall
+ point to a <constant>NUL</constant>-terminated string or be
+ <constant>NULL</constant>. In the latter case, the descriptive
+ name will be unset. The string is copied internally, hence the
+ <parameter>description</parameter> argument is not referenced
+ after the function returns.</para>
+
+ <para><function>sd_event_source_get_description()</function> may
+ be used to query the current descriptive name assigned to the
+ event source object <parameter>source</parameter>. It returns a
+ pointer to the current name in <parameter>description</parameter>,
+ stored in memory internal to the event source. The memory is
+ invalidated when the event source is destroyed or the descriptive
+ name is changed.</para>
+
+ <para>Event source objects generally have no description set when
+ they are created, except for UNIX signal event sources created
+ with
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ whose descriptive name is initialized to the signal's C constant
+ name (e.g. <literal>SIGINT</literal> or
+ <literal>SIGTERM</literal>).</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_set_description()</function> and
+ <function>sd_event_source_get_description()</function> return a
+ non-negative integer. On failure, they return a negative
+ errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid
+ pointer to an <structname>sd_event_source</structname>
+ object or the <parameter>description</parameter> argument for
+ <function>sd_event_source_get_description()</function> is
+ <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory to copy the
+ name.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENXIO</constant></term>
+
+ <listitem><para>No name was set for the event
+ source.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_enabled" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_enabled</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_enabled</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_enabled</refname>
+ <refname>sd_event_source_get_enabled</refname>
+ <refname>SD_EVENT_ON</refname>
+ <refname>SD_EVENT_OFF</refname>
+ <refname>SD_EVENT_ONESHOT</refname>
+
+ <refpurpose>Enable or disable event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>enum</token> {
+ <constant>SD_EVENT_OFF</constant> = 0,
+ <constant>SD_EVENT_ON</constant> = 1,
+ <constant>SD_EVENT_ONESHOT</constant> = -1,
+};</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_enabled</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>enabled</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_enabled</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int *<parameter>enabled</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_enabled()</function> may be
+ used to enable or disable the event source object specified as
+ <parameter>source</parameter>. The <parameter>enabled</parameter>
+ parameter takes one of <constant>SD_EVENT_ON</constant> (to
+ enable), <constant>SD_EVENT_OFF</constant> (to disable) or
+ <constant>SD_EVENT_ONESHOT</constant>. If invoked with
+ <constant>SD_EVENT_ONESHOT</constant> the event source will be
+ enabled but automatically reset to
+ <constant>SD_EVENT_OFF</constant> after the event source was
+ dispatched once.</para>
+
+ <para>Event sources that are disabled will not result in event
+ loop wakeups and will not be dispatched, until they are enabled
+ again.</para>
+
+ <para><function>sd_event_source_get_enabled()</function> may be
+ used to query whether the event source object
+ <parameter>source</parameter> is currently enabled or not. It
+ returns the enablement state in
+ <parameter>enabled</parameter>.</para>
+
+ <para>Event source objects are enabled when they are first created
+ with calls such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. However,
+ depending on the event source type they are enabled continuously
+ (<constant>SD_EVENT_ON</constant>) or only for a single invocation
+ of the event source handler
+ (<constant>SD_EVENT_ONESHOT</constant>). For details see the
+ respective manual pages.</para>
+
+ <para>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
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with a prior call to
+ <function>sd_event_source_set_enabled()</function> with
+ <constant>SD_EVENT_OFF</constant>, to ensure the event source is
+ not dispatched again until all other remaining references are dropped.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_set_enabled()</function> and
+ <function>sd_event_source_get_enabled()</function> return a
+ non-negative integer. On failure, they return a negative
+ errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid
+ pointer to an <structname>sd_event_source</structname>
+ object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_prepare" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_prepare</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_prepare</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_prepare</refname>
+
+ <refpurpose>Set a preparation callback for event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_prepare</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>sd_event_handler_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_prepare()</function> may be
+ used to set a preparation callback for the event source object
+ specified as <parameter>source</parameter>. The callback function
+ specified as <parameter>callback</parameter> 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
+ <parameter>callback</parameter> parameter is passed as NULL the
+ callback function is reset. </para>
+
+ <para>Event source objects have no preparation callback associated
+ when they are first created with calls such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+ callback functions are supported for all event source types with
+ the exception of those created with
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+ callback functions are dispatched in the order indicated by the
+ event source's priority field, as set with
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+ callbacks of disabled event sources (see
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ are not invoked.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success,
+ <function>sd_event_source_set_prepare()</function> returns a
+ non-negative integer. On failure, it returns a negative
+ errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid
+ pointer to an <structname>sd_event_source</structname>
+ object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para>The specified event source has been created
+ with
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_priority" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_priority</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_priority</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_priority</refname>
+ <refname>sd_event_source_get_priority</refname>
+ <refname>SD_EVENT_PRIORITY_IMPORTANT</refname>
+ <refname>SD_EVENT_PRIORITY_NORMAL</refname>
+ <refname>SD_EVENT_PRIORITY_IDLE</refname>
+
+ <refpurpose>Set or retrieve the priority of event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>enum</token> {
+ <constant>SD_EVENT_SOURCE_IMPORTANT</constant> = -100,
+ <constant>SD_EVENT_SOURCE_NORMAL</constant> = 0,
+ <constant>SD_EVENT_SOURCE_IDLE</constant> = 100,
+};</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_priority</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int64_t <parameter>priority</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_priority</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int64_t *<parameter>priority</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_priority()</function> may be
+ used to set the priority for the event source object specified as
+ <parameter>source</parameter>. The priority is specified as an
+ arbitrary signed 64bit integer. The priority is initialized to
+ <constant>SD_EVENT_PRIORITY_NORMAL</constant> (0) when the event
+ source is allocated with a call such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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 <constant>SD_EVENT_PRIORITY_IMPORTANT</constant>
+ (-100), <constant>SD_EVENT_PRIORITY_NORMAL</constant> (0) and
+ <constant>SD_EVENT_PRIORITY_IDLE</constant> (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.</para>
+
+ <para>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).</para>
+
+ <para>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.</para>
+
+ <para><function>sd_event_source_get_priority()</function> may be
+ used to query the current priority assigned to the event source
+ object <parameter>source</parameter>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success,
+ <function>sd_event_source_set_priority()</function> and
+ <function>sd_event_source_get_priority()</function> return a
+ non-negative integer. On failure, they return a negative
+ errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid
+ pointer to an <structname>sd_event_source</structname>
+ object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_userdata" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_userdata</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_userdata</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_userdata</refname>
+ <refname>sd_event_source_get_userdata</refname>
+
+ <refpurpose>Set or retrieve user data pointer of event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>void* <function>sd_event_source_set_userdata</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void* <function>sd_event_source_get_userdata</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_userdata()</function> may be
+ used to set an arbitrary user data pointer for the event source
+ object specified as <parameter>source</parameter>. The user data
+ pointer is usually specified when creating an event source object
+ with calls such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ 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 <parameter>userdata</parameter> parameter specifies
+ the new user data pointer to set, the function returns the
+ previous user data pointer. Note that <constant>NULL</constant> is
+ a valid user data pointer.</para>
+
+ <para><function>sd_event_source_get_userdata()</function> may be
+ used to query the current user data pointer assigned to the event
+ source object <parameter>source</parameter>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success,
+ <function>sd_event_source_set_userdata()</function> and
+ <function>sd_event_source_get_userdata()</function> return the
+ previously set user data pointer. On failure, they return
+ NULL.</para>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_unref" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_unref</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_unref</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_unref</refname>
+ <refname>sd_event_source_unrefp</refname>
+ <refname>sd_event_source_ref</refname>
+
+ <refpurpose>Increase or decrease event source reference counters</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>sd_event_source* <function>sd_event_source_unref</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_event_source_unrefp</function></funcdef>
+ <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_event_source* <function>sd_event_source_ref</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_unref()</function> may be used to
+ decrement by one the reference counter of the event source object
+ specified as <parameter>source</parameter>. The reference counter
+ is initially set to one, when the event source is created with calls
+ such as
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. When
+ the reference counter reaches zero it is removed from its event loop
+ object and destroyed.</para>
+
+ <para><function>sd_event_source_unrefp()</function> is similar to
+ <function>sd_event_source_unref()</function> but takes a pointer to a
+ pointer to an <type>sd_event_source</type> object. This call is useful in
+ conjunction with GCC's and LLVM's <ulink
+ url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+ Variable Attribute</ulink>. Note that this function is defined as
+ inline function.</para>
+
+ <para><function>sd_event_source_ref()</function> may be used
+ to increase by one the reference counter of the event source object
+ specified as <parameter>source</parameter>.</para>
+
+ <para><function>sd_event_source_unref()</function>,
+ <function>sd_bus_creds_unrefp()</function> and
+ <function>sd_bus_creds_ref()</function> execute no operation if
+ the passed event source object is
+ <constant>NULL</constant>.</para>
+
+ <para>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
+ <function>sd_event_source_unref()</function> with a prior call to
+ <function>sd_event_source_set_enabled()</function> with
+ <constant>SD_EVENT_OFF</constant>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para><function>sd_event_source_unref()</function> always returns
+ <constant>NULL</constant>.
+ <function>sd_event_source_ref()</function> always returns the
+ event source object passed in.</para>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_event_wait">
+<refentry id="sd_event_wait" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_event_wait</title>
<refname>sd_event_wait</refname>
<refname>sd_event_prepare</refname>
<refname>sd_event_dispatch</refname>
-
- <refpurpose>Run parts of the libsystemd event loop</refpurpose>
+ <refname>sd_event_get_state</refname>
+ <refname>SD_EVENT_INITIAL</refname>
+ <refname>SD_EVENT_PREPARING</refname>
+ <refname>SD_EVENT_ARMED</refname>
+ <refname>SD_EVENT_PENDING</refname>
+ <refname>SD_EVENT_RUNNING</refname>
+ <refname>SD_EVENT_EXITING</refname>
+ <refname>SD_EVENT_FINISHED</refname>
+
+ <refpurpose>Low-level event loop operations</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+ <funcsynopsisinfo><token>enum</token> {
+ <constant>SD_EVENT_INITIAL</constant>,
+ <constant>SD_EVENT_PREPARING</constant>,
+ <constant>SD_EVENT_ARMED</constant>,
+ <constant>SD_EVENT_PENDING</constant>,
+ <constant>SD_EVENT_RUNNING</constant>,
+ <constant>SD_EVENT_EXITING</constant>,
+ <constant>SD_EVENT_FINISHED</constant>,
+};</funcsynopsisinfo>
+
<funcprototype>
<funcdef>int <function>sd_event_prepare</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
<funcprototype>
<funcdef>int <function>sd_event_wait</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
- <paramdef>uint64_t <parameter>timeout</parameter></paramdef>
+ <paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>int <function>sd_event_get_state</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ </funcprototype>
+
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para>Functions described here form parts of an event loop.</para>
-
- <para><function>sd_event_prepare</function> checks for pending
+ <para>The low-level <function>sd_event_prepare()</function>,
+ <function>sd_event_wait()</function> and
+ <function>sd_event_dispatch()</function> functions may be used to
+ execute specific phases of an event loop. See
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>sd_event_loop</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for higher-level functions that execute individual but complete
+ iterations of an event loop or run it continuously.</para>
+
+ <para><function>sd_event_prepare()</function> checks for pending
events and arms necessary timers. If any events are ready to be
- processed, it returns a positive value, and the events should be
- processed with <function>sd_event_dispatch</function>.
- <function>sd_event_dispatch</function> runs a handler for one of
- the events from the sources with the highest priority. On success,
- <function>sd_event_dispatch</function> returns either 0, which
- means that the loop is finished, or a positive value, which means
- that the loop is again in the initial state and
- <function>sd_event_prepare</function> should be called again.
- </para>
+ processed ("pending"), it returns a positive, non-zero value, and the caller
+ should process these events with
+ <function>sd_event_dispatch()</function>.</para>
+
+ <para><function>sd_event_dispatch()</function> dispatches the
+ highest priority event source that has a pending event. On
+ success, <function>sd_event_dispatch()</function> returns either
+ zero, which indicates that no further event sources may be
+ dispatched and exiting of the event loop was requested via
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>;
+ 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
+ <function>sd_event_prepare()</function> again.</para>
+
+ <para>In case <function>sd_event_prepare()</function> returned
+ zero, <function>sd_event_wait()</function> 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
+ <function>sd_event_dispatch()</function>. Otherwise, the event
+ loop returned to its initial state and the next event loop
+ iteration should be initiated by invoking
+ <function>sd_event_prepare()</function> again.</para>
+
+ <para><function>sd_event_get_state()</function> may be used to
+ determine the state the event loop is currently in. It returns one
+ of the states described below.</para>
+
+ <para>All four functions take, as the first argument, the event
+ loop object <parameter>event</parameter> that has been created
+ with <function>sd_event_new()</function>. The timeout for
+ <function>sd_event_wait()</function> is specified in
+ <parameter>usec</parameter> in milliseconds. <constant>(uint64_t)
+ -1</constant> may be used to specify an infinite timeout.</para>
+</refsect1>
+
+ <refsect1>
+ <title>State Machine</title>
+
+ <para>The event loop knows the following states, that may be
+ queried with <function>sd_event_get_state()</function>.</para>
- <para>In case <function>sd_event_prepare</function> returned 0,
- <function>sd_event_wait</function> should be called to wait for
- events or a timeout. If any events are ready to be processed, it
- returns a positive value, and the events should be processed with
- <function>sd_event_dispatch</function>. Otherwise, the loop is
- back in the initial state and <function>sd_event_prepare</function>
- should be called again.</para>
+ <variablelist>
+ <varlistentry>
+ <term><constant>SD_EVENT_INITIAL</constant></term>
+
+ <listitem><para>The initial state the event loop is in,
+ before each event loop iteration. Use
+ <function>sd_event_prepare()</function> to transition the
+ event loop into the <constant>SD_EVENT_ARMED</constant> or
+ <constant>SD_EVENT_PENDING</constant> states.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_PREPARING</constant></term>
+
+ <listitem><para>An event source is currently being prepared,
+ i.e. the preparation handler is currently being executed, as
+ set with
+ <citerefentry><refentrytitle>sd_event_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
+ state is only seen in the event source preparation handler
+ that is invoked from the
+ <function>sd_event_prepare()</function> call and is
+ immediately followed by <constant>SD_EVENT_ARMED</constant> or
+ <constant>SD_EVENT_PENDING</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_ARMED</constant></term>
+
+ <listitem><para><function>sd_event_prepare()</function> has
+ been called and no event sources were ready to be
+ dispatched. Use <function>sd_event_wait()</function> to wait
+ for new events, and transition into
+ <constant>SD_EVENT_PENDING</constant> or back into
+ <constant>SD_EVENT_INITIAL</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_PENDING</constant></term>
+
+ <listitem><para><function>sd_event_prepare()</function> or
+ <function>sd_event_wait()</function> have been called and
+ there were event sources with events pending. Use
+ <function>sd_event_dispatch()</function> to dispatch the
+ highest priority event source and transition back to
+ <constant>SD_EVENT_INITIAL</constant>, or
+ <constant>SD_EVENT_FINISHED</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_RUNNING</constant></term>
+
+ <listitem><para>A regular event source is currently being
+ dispatched. This state is only seen in the event source
+ handler that is invoked from the
+ <function>sd_event_dispatch()</function> call, and is
+ immediately followed by <constant>SD_EVENT_INITIAL</constant>
+ or <constant>SD_EVENT_FINISHED</constant> as soon the event
+ source handler returns. Note that during dispatching of exit
+ event sources the <constant>SD_EVENT_EXITING</constant> state
+ is seen instead.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_EXITING</constant></term>
+
+ <listitem><para>Similar to
+ <constant>SD_EVENT_RUNNING</constant> but is the state in
+ effect while dispatching exit event sources. It is followed by
+ <constant>SD_EVENT_INITIAL</constant> or
+ <constant>SD_EVENT_FINISHED</constant> as soon as the event
+ handler returns.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_EVENT_FINISHED</constant></term>
+
+ <listitem><para>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.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>A simplified flow chart of the states and the calls to
+ transition between them is shown below. Note that
+ <constant>SD_EVENT_PREPARING</constant>,
+ <constant>SD_EVENT_RUNNING</constant> and
+ <constant>SD_EVENT_EXITING</constant> are not shown here.</para>
<programlisting>
- ┌──────────┐
- │ initial ├──←←←←←←←←←←←←←←←←←←←─┐
- └───┬──────┘ ↑
- │ ↑
- sd_event_prepare ┌─────────┐ ↑
- ├ 0 →→→→→→→──┤ armed │ ↑
- 1 └───┬─────┘ ↑
- ↓ │ ↑
- ↓ sd_event_wait ↑
- ├───←←←←←←←─── 1 ┴─ 0 →→→→→→→─┘
- ┌───┴──────┐ ↑
- │ pending │ ↑
- └───┬──────┘ ↑
- │ ↑
- sd_event_dispatch ↑
- ↓ ↑
- ├ 1 ──────────→→→→→→→─────────┘
- 0
- ↓
- ┌───┴──────┐
- │ finished │
- └──────────┘
+ 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
</programlisting>
-
- <para>All three functions take, as the first argument, the event
- loop object <parameter>event</parameter> that is created with
- <function>sd_event_new</function>. The timeout for
- <function>sd_event_wait</function> is specified with
- <parameter>timeout</parameter> in milliseconds.
- <constant>(uint64_t) -1</constant> may be used to specify an
- infinite timeout.</para>
</refsect1>
<refsect1>
<para>On success, these functions return 0 or a positive integer.
On failure, they return a negative errno-style error code. In case
- of <function>sd_event_prepare</function> and
- <function>sd_event_wait</function>, a positive value means that
- events are ready to be processed and 0 means that no events are
- ready. In case of <function>sd_event_dispatch</function>, a
- positive value means that the loop is again in the initial state
- and 0 means the loop is finished. For any of these functions, a
- negative return value means the loop must be aborted.</para>
+ of <function>sd_event_prepare()</function> and
+ <function>sd_event_wait()</function>, 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
+ <function>sd_event_dispatch()</function>, a positive, non-zero
+ return code indicates that the event loop returned to its initial
+ state and zero indicates the event loop has
+ exited. <function>sd_event_get_state()</function> returns a
+ positive or zero state on success.</para>
</refsect1>
<refsect1>
<term><constant>-EINVAL</constant></term>
<listitem><para>The <parameter>event</parameter> parameter is
- <constant>NULL</constant>.</para></listitem>
+ invalid or <constant>NULL</constant>.</para></listitem>
</varlistentry>
<varlistentry>
<para>Other errors are possible, too.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>Functions described here are available
- as a shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
--- /dev/null
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_journal_enumerate_fields">
+
+ <refentryinfo>
+ <title>sd_journal_enumerate_fields</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_journal_enumerate_fields</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_journal_enumerate_fields</refname>
+ <refname>sd_journal_restart_fields</refname>
+ <refname>SD_JOURNAL_FOREACH_FIELD</refname>
+ <refpurpose>Read used field names from the journal</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-journal.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_journal_enumerate_fields</function></funcdef>
+ <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+ <paramdef>const char **<parameter>field</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_journal_restart_fields</function></funcdef>
+ <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef><function>SD_JOURNAL_FOREACH_FIELD</function></funcdef>
+ <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+ <paramdef>const char *<parameter>field</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_journal_enumerate_fields()</function> 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 <function>sd_journal_enumerate_fields()</function>. Note that this call is subject to the data field
+ size threshold as controlled by <function>sd_journal_set_data_threshold()</function>.</para>
+
+ <para><function>sd_journal_restart_fields()</function> resets the field name enumeration index to the beginning of
+ the list. The next invocation of <function>sd_journal_enumerate_fields()</function> will return the first field
+ name again.</para>
+
+ <para>The <function>SD_JOURNAL_FOREACH_FIELD()</function> macro may be used as a handy wrapper around
+ <function>sd_journal_restart_fields()</function> and <function>sd_journal_enumerate_fields()</function>.</para>
+
+ <para>These functions currently are not influenced by matches set with <function>sd_journal_add_match()</function>
+ but this might change in a later version of this software.</para>
+
+ <para>To retrieve the possible values a specific field can take use
+ <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para><function>sd_journal_enumerate_fields()</function> 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.
+ <function>sd_journal_restart_fields()</function> returns
+ nothing.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
+ interfaces are available as a shared library, which can be compiled and linked to with the
+ <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>Use the <function>SD_JOURNAL_FOREACH_FIELD</function> macro to iterate through all field names in use in the
+ current journal.</para>
+
+ <programlisting>#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;
+}</programlisting>
+
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2016 Jan Synáček
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_journal_has_runtime_files">
+
+ <refentryinfo>
+ <title>sd_journal_has_runtime_files</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Jan</firstname>
+ <surname>Synáček</surname>
+ <email>jan.synacek@gmail.com</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_journal_has_runtime_files</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_journal_has_runtime_files</refname>
+ <refname>sd_journal_has_persistent_files</refname>
+ <refpurpose>Query availability of runtime or persistent journal files.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-journal.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_journal_has_runtime_files</function></funcdef>
+ <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_journal_has_persistent_files</function></funcdef>
+ <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_journal_has_runtime_files()</function> returns a positive value
+ if runtime journal files (present in /run/systemd/journal/) have been found.
+ Otherwise returns 0.</para>
+
+ <para><function>sd_journal_has_persistent_files()</function> returns a positive value
+ if persistent journal files (present in /var/log/journal/) have been found.
+ Otherwise returns 0.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return value</title>
+ <para>Both <function>sd_journal_has_runtime_files()</function>
+ and <function>sd_journal_has_persistent_files()</function> return -EINVAL
+ if their argument is NULL.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
<para>Note that these functions currently are not influenced by
matches set with <function>sd_journal_add_match()</function> but
this might change in a later version of this software.</para>
+
+ <para>To enumerate all field names currently in use (and thus all suitable field parameters for
+ <function>sd_journal_query_unique()</function>), use the
+ <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call.</para>
</refsect1>
<refsect1>
#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;
+ 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;
}</programlisting>
</refsect1>
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
<refnamediv>
<refname>sd_login_monitor_new</refname>
<refname>sd_login_monitor_unref</refname>
+ <refname>sd_login_monitor_unrefp</refname>
<refname>sd_login_monitor_flush</refname>
<refname>sd_login_monitor_get_fd</refname>
<refname>sd_login_monitor_get_events</refname>
<paramdef>sd_login_monitor *<parameter>m</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>void <function>sd_login_monitor_unrefp</function></funcdef>
+ <paramdef>sd_login_monitor **<parameter>m</parameter></paramdef>
+ </funcprototype>
+
<funcprototype>
<funcdef>int <function>sd_login_monitor_flush</function></funcdef>
<paramdef>sd_login_monitor *<parameter>m</parameter></paramdef>
descriptor returned by
<function>sd_login_monitor_get_fd()</function>.</para>
+ <para><function>sd_login_monitor_unrefp()</function> is similar to
+ <function>sd_login_monitor_unref()</function> but takes a pointer
+ to a pointer to an <type>sd_login_monitor</type> object. This call
+ is useful in conjunction with GCC's and LLVM's <ulink
+ url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+ Variable Attribute</ulink>. 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:</para>
+
+ <programlisting>{
+ __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));
+ …
+}</programlisting>
+
<para><function>sd_login_monitor_flush()</function> 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
state. If this call is not invoked, the file descriptor will
immediately wake up the event loop again.</para>
+ <para><function>sd_login_monitor_unref()</function> and
+ <function>sd_login_monitor_unrefp()</function> execute no
+ operation if the passed in monitor object is
+ <constant>NULL</constant>.</para>
+
<para><function>sd_login_monitor_get_fd()</function> may be used
to retrieve the file descriptor of the monitor object that may be
integrated in an application defined event loop, based around
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
- seperate invocations of
+ separate invocations of
<function>sd_pid_notify_with_fds()</function>. The name may
consist of any ASCII character, but must not contain control
characters or <literal>:</literal>. It may not be longer than
<function>sd_seat_get_sessions()</function>,
<function>sd_seat_can_multi_session()</function>,
<function>sd_seat_can_tty()</function> and
- <function>sd_seat_can_grapical()</function> interfaces are
+ <function>sd_seat_can_graphical()</function> interfaces are
available as a shared library, which can be compiled and linked to
with the
<constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<varname>WatchdogSec=</varname> in service files. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
+
+ <para>Use
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ to enable automatic watchdog support in
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>-based event loops.</para>
</refsect1>
<refsect1>
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
<para>Start (activate) one or more units specified on the
command line.</para>
- <para>Note that glob patterns operate on a list of currently
- loaded units. Units which are not active and are not in a
- failed state usually are not loaded, and would 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 <command>start</command>
- has limited usefulness.</para>
+ <para>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 <command>start</command> has limited
+ usefulness. Also, secondary alias names of units are not considered.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>Restart one or more units specified on the command
line if the units are running. This does nothing if units are not
- running. Note that, for compatibility with Red Hat init
- scripts, <command>condrestart</command> is equivalent to this
- command.</para>
+ running.</para>
+ <!-- Note that we don't document condrestart here, as that is just compatibility support, and we generally
+ don't document that. -->
</listitem>
</varlistentry>
<varlistentry>
</listitem>
</varlistentry>
<varlistentry>
- <term><command>reload-or-try-restart <replaceable>PATTERN</replaceable>...</command></term>
+ <term><command>try-reload-or-restart <replaceable>PATTERN</replaceable>...</command></term>
<listitem>
<para>Reload one or more units if they support it. If not,
restart them instead. This does nothing if the units are not
- running. Note that, for compatibility with SysV init scripts,
- <command>force-reload</command> is equivalent to this
- command.</para>
+ running.</para>
+ <!-- Note that we don't document force-reload here, as that is just compatibility support, and we generally
+ don't document that. -->
</listitem>
</varlistentry>
<varlistentry>
output. If you are looking for computer-parsable output,
use <command>show</command> instead. By default, this
function only shows 10 lines of output and ellipsizes
- lines to fit in the terminal window. This can be changes
+ lines to fit in the terminal window. This can be changed
with <option>--lines</option> and <option>--full</option>,
see above. In addition, <command>journalctl
--unit=<replaceable>NAME</replaceable></command> or
<para>Example: <command>systemctl set-property foobar.service CPUShares=777</command></para>
+ <para>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.</para>
+
<para>Note that this command allows changing multiple
properties at the same time, which is preferable over
setting them individually. Like unit file configuration
<tbody>
<row>
<entry><literal>enabled</literal></entry>
- <entry morerows='1'>Enabled through a symlink in a <filename>.wants/</filename> or <filename>.requires/</filename> subdirectory of <filename>/etc/systemd/system/</filename> (persistently) or <filename>/run/systemd/system/</filename> (transiently).</entry>
+ <entry morerows='1'>Enabled via <filename>.wants/</filename>, <filename>.requires/</filename> or alias symlinks (permanently in <filename>/etc/systemd/system/</filename>, or transiently in <filename>/run/systemd/system/</filename>).</entry>
<entry morerows='1'>0</entry>
</row>
<row>
</row>
<row>
<entry><literal>bad</literal></entry>
- <entry>Unit file is invalid or another error occured. Note that <command>is-enabled</command> will not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
+ <entry>Unit file is invalid or another error occurred. Note that <command>is-enabled</command> will not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
<entry>> 0</entry>
</row>
</tbody>
<refsect2>
<title>Parameter Syntax</title>
- <para>Unit commands listed above take either a single unit name
- (designated as <replaceable>NAME</replaceable>), or multiple
- unit specifications (designated as
- <replaceable>PATTERN</replaceable>...). In the first case, the
- unit name with or without a suffix must be given. If the suffix
- is not specified, systemctl will append a suitable suffix,
- <literal>.service</literal> by default, and a type-specific
- suffix in case of commands which operate only on specific unit
- types. For example,
+ <para>Unit commands listed above take either a single unit name (designated as <replaceable>NAME</replaceable>),
+ or multiple unit specifications (designated as <replaceable>PATTERN</replaceable>...). 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, <literal>.service</literal> by default, and a type-specific suffix in
+ case of commands which operate only on specific unit types. For example,
<programlisting># systemctl start sshd</programlisting> and
<programlisting># systemctl start sshd.service</programlisting>
are equivalent, as are
<programlisting># systemctl isolate default</programlisting>
and
<programlisting># systemctl isolate default.target</programlisting>
- Note that (absolute) paths to device nodes are automatically
- converted to device unit names, and other (absolute) paths to
- mount unit names.
+ Note that (absolute) paths to device nodes are automatically converted to device unit names, and other (absolute)
+ paths to mount unit names.
<programlisting># systemctl status /dev/sda
# systemctl status /home</programlisting>
are equivalent to:
<programlisting># systemctl status dev-sda.device
# systemctl status home.mount</programlisting>
- In the second case, shell-style globs will be matched against
- 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.</para>
+ 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.</para>
<para>Glob patterns use
<citerefentry project='man-pages'><refentrytitle>fnmatch</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<literal>*</literal>, <literal>?</literal>,
<literal>[]</literal> may be used. See
<citerefentry project='man-pages'><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></citerefentry>
- for more details. The patterns are matched against the names of
+ 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:
<programlisting># systemctl stop sshd@*.service</programlisting>
- will stop all <filename>sshd@.service</filename> instances.
+ will stop all <filename>sshd@.service</filename> instances. Note that alias names of units, and units that aren't
+ loaded are not considered for glob expansion.
</para>
- <para>For unit file commands, the specified
- <replaceable>NAME</replaceable> should be the full name of the
- unit file, or the absolute path to the unit file:
+ <para>For unit file commands, the specified <replaceable>NAME</replaceable> should be the name of the unit file
+ (possibly abbreviated, see above), or the absolute path to the unit file:
<programlisting># systemctl enable foo.service</programlisting>
or
<programlisting># systemctl link /path/to/foo.service</programlisting>
<refsect1>
<title>Description</title>
- <para><command>systemd-activate</command> can be used to
- launch a socket-activated daemon from the command line for
- testing purposes. It can also be used to launch single instances
- of the daemon per connection (inetd-style).
+ <para><command>systemd-activate</command> 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.
</para>
<para>The daemon to launch and its options should be specified
after options intended for <command>systemd-activate</command>.
</para>
- <para>If the <option>-a</option> option is given, file descriptor
- of the connection 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 <varname>$LISTEN_FDS</varname>
- to <command>systemd-activate</command> will be passed through to
- the daemon, in the original positions. Other sockets specified
- with <option>--listen</option> will use consecutive descriptors.
+ <para>If the <option>--inetd</option> 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 <varname>$LISTEN_FDS</varname> to
+ <command>systemd-activate</command> will be passed through to the daemon, in the original positions. Other sockets
+ specified with <option>--listen=</option> will use consecutive descriptors. By default,
+ <command>systemd-activate</command> listens on a stream socket, use <option>--datagram</option> and
+ <option>--seqpacket</option> to listen on datagram or sequential packet sockets instead (see below).
</para>
</refsect1>
<term><option>-a</option></term>
<term><option>--accept</option></term>
- <listitem><para>Launch a separate instance of daemon per
- connection and pass the connection socket as standard input
- and standard output.</para></listitem>
+ <listitem><para>Launch an instance of the service binary for each connection and pass the connection
+ socket.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d</option></term>
+ <term><option>--datagram</option></term>
+
+ <listitem><para>Listen on a datagram socket (<constant>SOCK_DGRAM</constant>), instead of a stream socket
+ (<constant>SOCK_STREAM</constant>). May not be combined with <option>--seqpacket</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--seqpacket</option></term>
+
+ <listitem><para>Listen on a sequential packet socket (<constant>SOCK_SEQPACKET</constant>), instead of a stream
+ socket (<constant>SOCK_STREAM</constant>). May not be combined with
+ <option>--datagram</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--inetd</option></term>
+
+ <listitem><para>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 <varname>$LISTEN_FDS</varname>
+ (see above).</para></listitem>
</varlistentry>
<varlistentry>
<example>
<title>Run an echo server on port 2000</title>
- <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 -a cat</programlisting>
+ <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 --inetd -a cat</programlisting>
</example>
<example>
possible to cache multiple passwords under the same keyname,
in which case they will be stored as NUL-separated list of
passwords. Use
- <citerefentry><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry project='die-net'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to access the cached key via the kernel keyring
directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
</varlistentry>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry project='die-net'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='die-net'><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
<para><command>systemd-detect-virt</command> detects execution in
a virtualized environment. It identifies the virtualization
- technology and can distinguish full VM virtualization from
+ technology and can distinguish full machine virtualization from
container virtualization. <filename>systemd-detect-virt</filename>
exits with a return value of 0 (success) if a virtualization
technology is detected, and non-zero (error) otherwise. By default,
</thead>
<tbody>
<row>
- <entry morerows="9">VM</entry>
+ <entry valign="top" morerows="9">VM</entry>
<entry><varname>qemu</varname></entry>
<entry>QEMU software virtualization</entry>
</row>
</row>
<row>
- <entry morerows="5">Container</entry>
+ <entry valign="top" morerows="5">Container</entry>
<entry><varname>openvz</varname></entry>
<entry>OpenVZ/Virtuozzo</entry>
</row>
</table>
<para>If multiple virtualization solutions are used, only the
- "innermost" is detected and identified. That means if both VM
- virtualization and container virtualization are used in
+ "innermost" is detected and identified. That means if both
+ machine and container virtualization are used in
conjunction, only the latter will be identified (unless
<option>--vm</option> is passed).</para>
</refsect1>
<term><option>-v</option></term>
<term><option>--vm</option></term>
- <listitem><para>Only detects VM virtualization (i.e. full
- hardware virtualization).</para></listitem>
+ <listitem><para>Only detects hardware virtualization).</para></listitem>
</varlistentry>
<varlistentry>
used to escape and to undo escaping of strings.</para>
<para>The command takes any number of strings on the command line,
- and will process them individually, one after the other. It will
+ and will process them individually, one after another. It will
output them separated by spaces to stdout.</para>
<para>By default, this command will escape the strings passed,
</varlistentry>
<varlistentry>
- <term><constant>application/event-stream</constant></term>
+ <term><constant>text/event-stream</constant></term>
<listitem><para>Entries are formatted as JSON data structures,
wrapped in a format suitable for <ulink
</programlisting>
</para>
- <para>Retrieve events from a remote
+ <para>Retrieve all available events from a remote
<citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
instance and store them in
- <filename>/var/log/journal/some.host/remote-some~host.journal</filename>:
+ <filename>/var/log/journal/remote/remote-some.host.journal</filename>:
<programlisting>
systemd-journal-remote --url http://some.host:19531/
</programlisting>
</para>
- </refsect1>
+
+ <para>Retrieve current boot events and wait for new events from a remote
+ <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ instance, and store them in
+ <filename>/var/log/journal/remote/remote-some.host.journal</filename>:
+ <programlisting>
+systemd-journal-remote --url http://some.host:19531/entries?boot&follow
+ </programlisting>
+ </para>
+</refsect1>
<refsect1>
<title>See Also</title>
<programlisting>mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
- <para><filename>systemd-journald</filename> will forward all
- received log messages to the
- <constant>AF_UNIX</constant>/<constant>SOCK_DGRAM</constant>
- socket <filename>/run/systemd/journal/syslog</filename>, if it
- exists, which may be used by Unix syslog daemons to process the
- data further.</para>
-
<para>See
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for information about the configuration of this service.</para>
<option>--ephemeral</option>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-a</option></term>
+ <term><option>--as-pid2</option></term>
+
+ <listitem><para>Invoke the shell or specified program as process ID (PID) 2 instead of PID 1 (init). By
+ default, if neither this option nor <option>--boot</option> 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
+ <command>sysvinit</command> compatible signal handling (specifically: it needs to reboot on SIGINT, reexecute
+ on SIGTERM, reload configuration on SIGHUP, and so on). With <option>--as-pid2</option> 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 <option>--boot</option> or
+ <option>--share-system</option>.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>-b</option></term>
<term><option>--boot</option></term>
- <listitem><para>Automatically search for an init binary and
- invoke it 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 <option>--share-system</option>.
- </para></listitem>
+ <listitem><para>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 <option>--as-pid2</option> or
+ <option>--share-system</option>.</para>
+
+ <para>The following table explains the different modes of invocation and relationship to
+ <option>--as-pid2</option> (see above):</para>
+
+ <table>
+ <title>Invocation Mode</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname="switch" />
+ <colspec colname="explanation" />
+ <thead>
+ <row>
+ <entry>Switch</entry>
+ <entry>Explanation</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Neither <option>--as-pid2</option> nor <option>--boot</option> specified</entry>
+ <entry>The passed parameters are interpreted as command line, which is executed as PID 1 in the container.</entry>
+ </row>
+
+ <row>
+ <entry><option>--as-pid2</option> specified</entry>
+ <entry>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.</entry>
+ </row>
+
+ <row>
+ <entry><option>--boot</option> specified</entry>
+ <entry>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.</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--chdir=</option></term>
+
+ <listitem><para>Change to the specified working directory before invoking the process in the container. Expects
+ an absolute path in the container's file system namespace.</para></listitem>
</varlistentry>
<varlistentry>
<option>yes</option>, full volatile mode is enabled. This
means the root directory is mounted as a mostly unpopulated
<literal>tmpfs</literal> instance, and
- <filename>/usr</filename> from the OS tree is mounted into it,
- read-only (the system thus starts up with read-only OS
+ <filename>/usr</filename> 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 <option>state</option>, the OS tree is
<para><command>systemd-path</command> may be used to query system
and user paths. The tool makes many of the paths described in
<citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>
- queriable.</para>
+ available for querying.</para>
<para>When invoked without arguments, a list of known paths and
their current values is shown. When at least one argument is
--- /dev/null
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ 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 <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="systemd-resolve"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>systemd-resolve</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-resolve</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-resolve</refname>
+ <refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain" rep="repeat"><replaceable>HOSTNAME</replaceable></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain" rep="repeat"><replaceable>ADDRESS</replaceable></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <command> --type=<replaceable>TYPE</replaceable></command>
+ <arg choice="plain" rep="repeat"><replaceable>RRDOMAIN</replaceable></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <command> --service</command>
+ <arg choice="plain"><arg choice="opt"><arg choice="opt"><replaceable>NAME</replaceable></arg>
+ <replaceable>TYPE</replaceable></arg> <replaceable>DOMAIN</replaceable></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <command> --statistics</command>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>systemd-resolve</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <command> --reset-statistics</command>
+ </cmdsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-resolve</command> may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource
+ records and services with the
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ 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.</para>
+
+ <para>The <option>--type=</option> 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 <literal>help</literal> may be used to list known values.</para>
+
+ <para>The <option>--service</option> switch may be used to resolve <ulink
+ url="https://tools.ietf.org/html/rfc2782">SRV</ulink> and <ulink
+ url="https://tools.ietf.org/html/rfc6763">DNS-SD</ulink> 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).</para>
+
+ <para>The <option>--statistics</option> switch may be used to show resolver statistics, including information about
+ the number of succesful and failed DNSSEC validations.</para>
+
+ <para>The <option>--reset-statistics</option> may be used to reset various statistics counters maintained the
+ resolver, including those shown in the <option>--statistics</option> output. This operation requires root
+ privileges.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>-4</option></term>
+ <term><option>-6</option></term>
+
+ <listitem><para>By default, when resolving a hostname, both IPv4 and IPv6
+ addresses are acquired. By specifying <option>-4</option> only IPv4 addresses are requested, by specifying
+ <option>-6</option> only IPv6 addresses are requested.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-i</option> <replaceable>INTERFACE</replaceable></term>
+ <term><option>--interface=</option><replaceable>INTERFACE</replaceable></term>
+
+ <listitem><para>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. <literal>en0</literal>). Note that this option has no
+ effect if system-wide DNS configuration (as configured in <filename>/etc/resolv.conf</filename> or
+ <filename>/etc/systemd/resolve.conf</filename>) in place of per-link configuration is used.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-p</option> <replaceable>PROTOCOL</replaceable></term>
+ <term><option>--protocol=</option><replaceable>PROTOCOL</replaceable></term>
+
+ <listitem><para>Specifies the network protocol for the query. May be one of <literal>dns</literal>
+ (i.e. classic unicast DNS), <literal>llmnr</literal> (<ulink
+ url="https://tools.ietf.org/html/rfc4795">Link-Local Multicast Name Resolution</ulink>),
+ <literal>llmr-ipv4</literal>, <literal>llmnr-ipv6</literal> (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 <literal>llmnr</literal> is identical to specifying this switch once with
+ <literal>llmnr-ipv4</literal> and once via <literal>llmnr-ipv6</literal>. 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 <literal>help</literal> may be used to list known values.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-t</option> <replaceable>TYPE</replaceable></term>
+ <term><option>--type=</option><replaceable>TYPE</replaceable></term>
+ <term><option>-c</option> <replaceable>CLASS</replaceable></term>
+ <term><option>--class=</option><replaceable>CLASS</replaceable></term>
+
+ <listitem><para>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 <literal>help</literal> may be used to list known values.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--service</option></term>
+
+ <listitem><para>Enables service resolution. This enables DNS-SD and simple SRV service resolution, depending
+ on the specified list of parameters (see above).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--service-address=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter. If true (the default), when doing a service lookup with
+ <option>--service</option> the hostnames contained in the SRV resource records are resolved as well.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--service-txt=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter. If true (the default), when doing a DNS-SD service lookup with
+ <option>--service</option> the TXT service metadata record is resolved as well.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--cname=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>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.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--search=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>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.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--legend=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter. If true (the default), column headers and meta information about the
+ query response are shown. Otherwise, this output is suppressed.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--statistics</option></term>
+
+ <listitem><para>If specified general resolver statistics are shown, including information whether DNSSEC is
+ enabled and available, as well as resolution and validation statistics.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--reset-statistics</option></term>
+
+ <listitem><para>Resets the statistics counters shown in <option>--statistics</option> to zero.</para></listitem>
+ </varlistentry>
+
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <example>
+ <title>Retrieve the addresses of the <literal>www.0pointer.net</literal> domain</title>
+
+ <programlisting>$ systemd-resolve www.0pointer.net</programlisting>
+ </example>
+
+ <example>
+ <title>Retrieve the domain of the <literal>85.214.157.71</literal> IP address</title>
+
+ <programlisting>$ systemd-resolve 85.214.157.71</programlisting>
+ </example>
+
+ <example>
+ <title>Retrieve the MX record of the <literal>0pointer.net</literal> domain</title>
+
+ <programlisting>$ systemd-resolve -t MX 0pointer.net</programlisting>
+ </example>
+
+ <example>
+ <title>Resolve an SRV service</title>
+
+ <programlisting>$ systemd-resolve --service _xmpp-server._tcp gmail.com</programlisting>
+ </example>
+
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+</refentry>
<refsect1>
<title>Description</title>
- <para><command>systemd-resolved</command> is a system service that
- manages network name resolution. It implements a caching DNS stub
- resolver and an LLMNR resolver and responder. It also generates
- <filename>/run/systemd/resolve/resolv.conf</filename> for
- compatibility which may be symlinked from
- <filename>/etc/resolv.conf</filename>. The glibc NSS module
- <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- is necessary to allow libc's NSS resolver functions to resolve
- host names via <command>systemd-resolved</command>.</para>
+ <para><command>systemd-resolved</command> 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 <filename>/run/systemd/resolve/resolv.conf</filename> file for
+ compatibility with traditional Linux programs. This file may be symlinked from
+ <filename>/etc/resolv.conf</filename>.</para>
+
+ <para>The glibc NSS module
+ <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry> is required to
+ permit glibc's NSS resolver functions to resolve host names via <command>systemd-resolved</command>.</para>
<para>The DNS servers contacted are determined from the global
settings in <filename>/etc/systemd/resolved.conf</filename>, the
is on the local loopback) and the IPv6 address ::1 (which is the
local host).</para></listitem>
- <listitem><para>The hostname <literal>localhost</literal> is
- resolved to the IP addresses 127.0.0.1 and
- ::1.</para></listitem>
+ <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
+ <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
+ resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
<listitem><para>The hostname <literal>gateway</literal> 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.</para></listitem>
+
+ <listitem><para>The mappings defined in <filename>/etc/hosts</filename> are resolved to their configured
+ addresses and back.</para></listitem>
</itemizedlist>
<para>Lookup requests are routed to the available DNS servers
<itemizedlist>
<listitem><para>Lookups for the special hostname
<literal>localhost</literal> are never routed to the
- network.</para></listitem>
+ network. (A few other, special domains are handled the same way.)</para></listitem>
<listitem><para>Single-label names are routed to all local
interfaces capable of IP multicasting, using the LLMNR
<listitem><para>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 addres range are never routed to
+ link-local address range are never routed to
DNS.</para></listitem>
</itemizedlist>
per-interface domains are exclusively routed to the matching
interfaces.</para>
- <para>Note that
- <filename>/run/systemd/resolve/resolv.conf</filename> should not
- be used directly, but only through a symlink from
- <filename>/etc/resolv.conf</filename>.</para>
+ <para>Note that <filename>/run/systemd/resolve/resolv.conf</filename> should not be used directly by applications,
+ but only through a symlink from <filename>/etc/resolv.conf</filename>.</para>
+
+ <para>See the <ulink url="http://www.freedesktop.org/wiki/Software/systemd/resolved"> resolved D-Bus API
+ Documentation</ulink> for information about the APIs <filename>systemd-resolved</filename> provides.</para>
+
</refsect1>
<refsect1>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-resolve</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>hosts</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
<listitem><para>These settings control various default
resource limits for units. See
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- for details. Use the string <varname>infinity</varname> 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). 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
+ for details. The resource limit is possible to specify in two formats,
+ <option>value</option> to set soft and hard limits to the same value,
+ or <option>soft:hard</option> to set both limits individually (e.g. DefaultLimitAS=4G:16G).
+ Use the string <varname>infinity</varname> 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
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details). Note that if no time unit is specified for
+ <varname>DefaultLimitCPU=</varname> the default unit of seconds is
+ implied, while for <varname>DefaultLimitRTTIME=</varname> 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
+ <varname>DefaultLimitCPU=</varname> 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.</para></listitem>
</varlistentry>
</variablelist>
<listitem><para>These settings set both soft and hard limits
of various resources for executed processes. See
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- for details. Use the string <varname>infinity</varname> to
+ for details. The resource limit is possible to specify in two formats,
+ <option>value</option> to set soft and hard limits to the same value,
+ or <option>soft:hard</option> to set both limits individually (e.g. LimitAS=4G:16G).
+ Use the string <varname>infinity</varname> 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
settings.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>AmbientCapabilities=</varname></term>
+
+ <listitem><para>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
+ <citerefentry project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ e.g. <constant>CAP_SYS_ADMIN</constant>,
+ <constant>CAP_DAC_OVERRIDE</constant>,
+ <constant>CAP_SYS_PTRACE</constant>. This option may appear more than
+ once in which case the ambient capability sets are merged.
+ If the list of capabilities is prefixed with <literal>~</literal>, 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 <literal>~</literal> (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.
+ </para><para>
+ 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 <constant>keep-caps</constant> is
+ automatically added to <varname>SecureBits=</varname> to retain the
+ capabilities over the user change.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>SecureBits=</varname></term>
<listitem><para>Controls the secure bits set for the executed
<varlistentry>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_FDNAMES</varname></term>
<listitem><para>Information about file descriptors passed to a
service for socket activation. See
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>$NOTIFY_SOCKET</varname></term>
+
+ <listitem><para>The socket
+ <function>sd_notify()</function> talks to. See
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$WATCHDOG_PID</varname></term>
+ <term><varname>$WATCHDOG_USEC</varname></term>
+
+ <listitem><para>Information about watchdog keep-alive notifications. See
+ <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>$TERM</varname></term>
<para>Additional variables may be configured by the following
means: for processes spawned in specific units, use the
- <varname>Environment=</varname> and
- <varname>EnvironmentFile=</varname> options above; to specify
+ <varname>Environment=</varname>, <varname>EnvironmentFile=</varname>
+ and <varname>PassEnvironment=</varname> options above; to specify
variables globally, use <varname>DefaultEnvironment=</varname>
(see
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
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
- <citerefentry
- project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
or <command>systemd</command> itself (this means: no
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>!). They
- can however rely on the most basic kernel functionality to
- be available, including a mounted <filename>/sys</filename>,
- <filename>/proc</filename>, <filename>/dev</filename>.
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!.
+ Non-essential file systems like
+ <filename>/var</filename> and <filename>/home</filename>
+ are mounted after generators have run. Generators
+ can however rely on the most basic kernel functionality to be
+ available, including a mounted <filename>/sys</filename>,
+ <filename>/proc</filename>, <filename>/dev</filename>,
+ <filename>/usr</filename>.
</para>
</listitem>
</example>
<example>
- <title>Debuging a generator</title>
+ <title>Debugging a generator</title>
<programlisting>dir=$(mktemp -d)
SYSTEMD_LOG_LEVEL=debug &systemgeneratordir;/systemd-fstab-generator \
configured in a unit file <filename>home-lennart.mount</filename>.
For details about the escaping logic used to convert a file system
path to a unit name, see
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Note that mount units cannot be templated.</para>
<para>Optionally, a mount unit may be accompanied by an automount
unit, to allow on-demand or parallelized mounting. See
VXLAN Group Policy </ulink> document. Defaults to false.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DestinationPort=</varname></term>
+ <listitem>
+ <para>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.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>PortRange=</varname></term>
+ <listitem>
+ <para>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.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<literal>ipv4</literal>, or <literal>ipv6</literal>.</para>
<para>Note that DHCPv6 will by default be triggered by Router
- Advertisment, if that is enabled, regardless of this parameter.
+ 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
<varlistentry>
<term><varname>LLMNR=</varname></term>
<listitem>
- <para>A boolean or <literal>resolve</literal>. When true, enables
- Link-Local Multicast Name Resolution on the link. When set to
- <literal>resolve</literal>, only resolution is enabled, but not
- announcement. Defaults to true.</para>
+ <para>A boolean or <literal>resolve</literal>. When true,
+ enables <ulink
+ url="https://tools.ietf.org/html/rfc4795">Link-Local
+ Multicast Name Resolution</ulink> on the link. When set to
+ <literal>resolve</literal>, only resolution is enabled,
+ but not host registration and announcement. Defaults to
+ true. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>MulticastDNS=</varname></term>
+ <listitem>
+ <para>A boolean or <literal>resolve</literal>. When true,
+ enables <ulink
+ url="https://tools.ietf.org/html/rfc6762">Multicast
+ DNS</ulink> support on the link. When set to
+ <literal>resolve</literal>, only resolution is enabled,
+ but not host or service registration and
+ announcement. Defaults to false. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>DNSSEC=</varname></term>
+ <listitem>
+ <para>A boolean or
+ <literal>allow-downgrade</literal>. When true, enables
+ <ulink
+ url="https://tools.ietf.org/html/rfc4033">DNSSEC</ulink>
+ DNS validation support on the link. When set to
+ <literal>allow-downgrade</literal>, compatibility with
+ non-DNSSEC capable networks is increased, by automatically
+ turning off DNSEC in this case. This option defines a
+ per-interface setting for
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+ global <varname>DNSSEC=</varname> option. Defaults to
+ false. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>DNSSECNegativeTrustAnchors=</varname></term>
+ <listitem><para>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
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<para>A DNS server address, which must be in the format
described in
<citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
- This option may be specified more than once.</para>
+ This option may be specified more than once. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Domains=</varname></term>
<listitem>
- <para>The domains used for DNS resolution over this link.</para>
+ <para>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.</para>
+
+ <para>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 <literal>~</literal>, 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 <literal>~.</literal> (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.</para>
+
+ <para>This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>NTP=</varname></term>
<listitem>
- <para>An NTP server address. This option may be specified more than once.</para>
+ <para>An NTP server address. This option may be specified more than once. This setting is read by
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>UseDomains=</varname></term>
<listitem>
- <para>When true (not the default), the domain name
- received from the DHCP server will be used for DNS
- resolution over this link. When a name cannot be resolved
- as specified, the domain name will be used a suffix and
- name resolution of that will be attempted.</para>
+ <para>Takes a boolean argument, or a the special value <literal>route</literal>. 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 <option>Domains=</option> setting. If set to <literal>route</literal>, 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 <option>Domains=</option> setting when the argument is prefixed with <literal>~</literal>. Defaults to
+ false.</para>
+
+ <para>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.</para>
- <para>This corresponds to the <option>domain</option>
- option in <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- and should not be enabled on untrusted networks.</para>
+ <para>When set to true, this setting corresponds to the <option>domain</option> option in <citerefentry
+ project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseTimezone=</varname></term>
<listitem><para>When true, the timezone received from the
- DHCP server will be set as as timezone of the local
+ DHCP server will be set as timezone of the local
system. Defaults to <literal>no</literal>.</para></listitem>
</varlistentry>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-networkd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
<varlistentry>
<term><varname>Boot=</varname></term>
- <listitem><para>Takes a boolean argument, which defaults to off. If
- enabled, <command>systemd-nspawn</command> will automatically
- search for an <filename>init</filename> executable and invoke
- it. In this case, the specified parameters using
- <varname>Parameters=</varname> are passed as additional
- arguments to the <filename>init</filename> process. This
- setting corresponds to the <option>--boot</option> switch on
- the <command>systemd-nspawn</command> command
- line. </para></listitem>
+ <listitem><para>Takes a boolean argument, which defaults to off. If enabled, <command>systemd-nspawn</command>
+ will automatically search for an <filename>init</filename> executable and invoke it. In this case, the
+ specified parameters using <varname>Parameters=</varname> are passed as additional arguments to the
+ <filename>init</filename> process. This setting corresponds to the <option>--boot</option> switch on the
+ <command>systemd-nspawn</command> command line. This option may not be combined with
+ <varname>ProcessTwo=yes</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ProcessTwo=</varname></term>
+
+ <listitem><para>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 <option>--as-pid2</option> switch
+ on the <command>systemd-nspawn</command> command line. This option may not be combined with
+ <varname>Boot=yes</varname>.</para></listitem>
</varlistentry>
<varlistentry>
switch.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>WorkingDirectory=</varname></term>
+
+ <listitem><para>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 <option>--chdir=</option> command line
+ switch.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>Capability=</varname></term>
<term><varname>DropCapability=</varname></term>
<listitem><para>Takes a space-separated list of Linux process
capabilities (see
- <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details). The <varname>Capability=</varname> setting
specifies additional capabilities to pass on top of the
default set of capabilities. The
</listitem>
</varlistentry>
- <varlistentry>
- <term><varname>NetClass=</varname></term>
- <listitem><para>Configures a network class number to assign to the
- unit. This value will be set to the
- <literal>net_cls.class_id</literal> property of the
- <literal>net_cls</literal> cgroup of the unit. The directive
- accepts a numerical value (for fixed number assignment) and the keyword
- <literal>auto</literal> (for dynamic allocation). Network traffic of
- all processes inside the unit will have the network class ID assigned
- by the kernel. Also see
- the kernel docs for
- <ulink url="https://www.kernel.org/doc/Documentation/cgroups/net_cls.txt">net_cls controller</ulink>
- and
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- </para></listitem>
- </varlistentry>
-
<varlistentry>
<term><varname>Slice=</varname></term>
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.</para>
+
+ <para>Special care should be taken when relying on the default slice assignment in templated service units
+ that have <varname>DefaultDependencies=no</varname> set, see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>, section
+ "Automatic Dependencies" for details.</para>
+
</listitem>
</varlistentry>
involved with early boot or late system shutdown should disable
this option.</para>
+ <para>Instanced service units (i.e. service units with an <literal>@</literal> in their name) are assigned by
+ default a per-template slice unit (see
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>), 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 <varname>DefaultDependencies=no</varname> in the
+ template unit, and either define your own per-template slice unit file that also sets
+ <varname>DefaultDependencies=no</varname>, or set <varname>Slice=system.slice</varname> (or another suitable slice)
+ in the template unit. Also see
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
<para>Additional implicit dependencies may be added as result of
execution and resource control parameters as documented in
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
with a <literal>-</literal> exit successfully.</para>
<para><varname>ExecStartPost=</varname> commands are only run after
- the service has started, as determined by <varname>Type=</varname>
+ the service has started successfully, as determined by <varname>Type=</varname>
(i.e. the process has been started for <varname>Type=simple</varname>
or <varname>Type=idle</varname>, the process exits successfully for
<varname>Type=oneshot</varname>, the initial process exits successfully
used to start long-running processes. All processes forked
off by processes invoked via <varname>ExecStartPre=</varname> will
be killed before the next service process is run.</para>
+
+ <para>Note that if any of the commands specified in <varname>ExecStartPre=</varname>,
+ <varname>ExecStart=</varname>, or <varname>ExecStartPost=</varname> fail (and are not prefixed with
+ <literal>-</literal>, see above) or time out before the service is fully up, execution continues with commands
+ specified in <varname>ExecStopPost=</varname>, the commands in <varname>ExecStop=</varname> are skipped.</para>
</listitem>
</varlistentry>
<constant>SIGKILL</constant> 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.</para></listitem>
+ asynchronous one.</para>
+
+ <para>Note that the commands specified in <varname>ExecStop=</varname> 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 <varname>ExecStart=</varname>,
+ <varname>ExecStartPre=</varname> or <varname>ExecStartPost=</varname> failed (and weren't prefixed with
+ <literal>-</literal>, see above) or timed out. Use <varname>ExecStopPost=</varname> to invoke commands when a
+ service failed to start up correctly and is shut down again.</para>
+
+ <para>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
+ <varname>ExecStopPost=</varname> instead.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ExecStopPost=</varname></term>
- <listitem><para>Additional commands that are executed after
- the service was stopped. This includes cases where the
- commands configured in <varname>ExecStop=</varname> were used,
- where the service does not have any
- <varname>ExecStop=</varname> defined, or where the service
- exited unexpectedly. This argument takes multiple command
- lines, following the same scheme as described for
- <varname>ExecStart=</varname>. Use of these settings is
- optional. Specifier and environment variable substitution is
- supported.</para></listitem>
+ <listitem><para>Additional commands that are executed after the service is stopped. This includes cases where
+ the commands configured in <varname>ExecStop=</varname> were used, where the service does not have any
+ <varname>ExecStop=</varname> defined, or where the service exited unexpectedly. This argument takes multiple
+ command lines, following the same scheme as described for <varname>ExecStart=</varname>. Use of these settings
+ is optional. Specifier and environment variable substitution is supported. Note that – unlike
+ <varname>ExecStop=</varname> – commands specified with this setting are invoked when a service failed to start
+ up correctly and is shut down again.</para>
+
+ <para>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.</para></listitem>
</varlistentry>
<varlistentry>
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
- <literal>0</literal> to disable the timeout logic. Defaults to
+ <literal>infinity</literal> to disable the timeout logic. Defaults to
<varname>DefaultTimeoutStartSec=</varname> from the manager
configuration file, except when
<varname>Type=oneshot</varname> is used, in which case the
<varname>KillMode=</varname> in
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
Takes a unit-less value in seconds, or a time span value such
- as "5min 20s". Pass <literal>0</literal> to disable the
+ as "5min 20s". Pass <literal>infinity</literal> to disable the
timeout logic. Defaults to
<varname>DefaultTimeoutStopSec=</varname> from the manager
configuration file (see
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RuntimeMaxSec=</varname></term>
+
+ <listitem><para>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 <varname>Type=oneshot</varname> services, as they terminate immediately after
+ activation completed. Pass <literal>infinity</literal> (the default) to configure no runtime
+ limit.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>WatchdogSec=</varname></term>
<listitem><para>Configures the watchdog timeout for a service.
larger than the configured time, then the service is placed in
a failed state and it will be terminated with
<constant>SIGABRT</constant>. By setting
- <varname>Restart=</varname> to <option>on-failure</option> or
+ <varname>Restart=</varname> to <option>on-failure</option>,
+ <option>on-watchdog</option>, <option>on-abnormal</option> or
<option>always</option>, the service will be automatically
restarted. The time configured here will be passed to the
executed service process in the
check whether the service manager expects watchdog keep-alive
notifications. See
<citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- for details.
+ for details.
+ <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ may be used to enable automatic watchdog notification support.
</para></listitem>
</varlistentry>
<constant>SIGPIPE</constant>. Exit status definitions can
either be numeric exit codes or termination signal names,
separated by spaces. For example:
- <programlisting>SuccessExitStatus=1 2 8
- SIGKILL</programlisting> ensures that exit codes 1, 2, 8 and
+
+ <programlisting>SuccessExitStatus=1 2 8 SIGKILL</programlisting>
+
+ ensures that exit codes 1, 2, 8 and
the termination signal <constant>SIGKILL</constant> are
considered clean service terminations.
</para>
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:
- <programlisting>RestartPreventExitStatus=1 6
- SIGABRT</programlisting> ensures that exit codes 1 and 6 and
- the termination signal <constant>SIGABRT</constant> 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.</para></listitem>
+
+ <programlisting>RestartPreventExitStatus=1 6 SIGABRT</programlisting>
+
+ ensures that exit codes 1 and 6 and the termination signal
+ <constant>SIGABRT</constant> 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.</para></listitem>
</varlistentry>
<varlistentry>
effect.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><varname>StartLimitInterval=</varname></term>
- <term><varname>StartLimitBurst=</varname></term>
-
- <listitem><para>Configure service start rate limiting. By
- default, services 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
- <varname>StartLimitInterval=</varname> to configure the
- checking interval (defaults to
- <varname>DefaultStartLimitInterval=</varname> in manager
- configuration file, set to 0 to disable any kind of rate
- limiting). Use <varname>StartLimitBurst=</varname> to
- configure how many starts per interval are allowed (defaults
- to <varname>DefaultStartLimitBurst=</varname> in manager
- configuration file). These configuration options are
- particularly useful in conjunction with
- <varname>Restart=</varname>; however, they apply to all kinds
- of starts (including manual), not just those triggered by the
- <varname>Restart=</varname> logic. Note that units which are
- configured for <varname>Restart=</varname> 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 <command>systemctl reset-failed</command>
- will cause the restart rate counter for a service to be
- flushed, which is useful if the administrator wants to
- manually start a service and the start limit interferes with
- that.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>StartLimitAction=</varname></term>
-
- <listitem><para>Configure the action to take if the rate limit
- configured with <varname>StartLimitInterval=</varname> and
- <varname>StartLimitBurst=</varname> is hit. Takes one of
- <option>none</option>,
- <option>reboot</option>,
- <option>reboot-force</option>,
- <option>reboot-immediate</option>,
- <option>poweroff</option>,
- <option>poweroff-force</option> or
- <option>poweroff-immediate</option>. If
- <option>none</option> is set, hitting the rate limit will
- trigger no action besides that the start will not be
- permitted. <option>reboot</option> causes a reboot following
- the normal shutdown procedure (i.e. equivalent to
- <command>systemctl reboot</command>).
- <option>reboot-force</option> causes a forced reboot which
- will terminate all processes forcibly but should cause no
- dirty file systems on reboot (i.e. equivalent to
- <command>systemctl reboot -f</command>) and
- <option>reboot-immediate</option> causes immediate execution
- of the
- <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- system call, which might result in data loss. Similarly,
- <option>poweroff</option>, <option>poweroff-force</option>,
- <option>poweroff-immediate</option> have the effect of
- powering down the system with similar semantics. Defaults to
- <option>none</option>.</para></listitem>
- </varlistentry>
-
<varlistentry>
<term><varname>FailureAction=</varname></term>
- <listitem><para>Configure the action to take when the service
- enters a failed state. Takes the same values as
- <varname>StartLimitAction=</varname> and executes the same
- actions. Defaults to <option>none</option>. </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>RebootArgument=</varname></term>
- <listitem><para>Configure the optional argument for the
- <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- system call if <varname>StartLimitAction=</varname> or
- <varname>FailureAction=</varname> is a reboot action. This
- works just like the optional argument to <command>systemctl
- reboot</command> command.</para></listitem>
+ <listitem><para>Configure the action to take when the service enters a failed state. Takes the same values as
+ the unit setting <varname>StartLimitAction=</varname> and executes the same actions (see
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Defaults to
+ <option>none</option>. </para></listitem>
</varlistentry>
<varlistentry>
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>SocketProtocol=</varname></term>
+ <listitem><para>Takes a one of <option>udplite</option>
+ or <option>sctp</option>. Specifies a socket protocol
+ (<constant>IPPROTO_UDPLITE</constant>) UDP-Lite
+ (<constant>IPPROTO_SCTP</constant>) SCTP socket respectively. </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>BindIPv6Only=</varname></term>
<listitem><para>Takes a one of <option>default</option>,
<filename>shutdown.target</filename>,
<filename>sigpwr.target</filename>,
<filename>sleep.target</filename>,
+ <filename>slices.target</filename>,
<filename>smartcard.target</filename>,
<filename>sockets.target</filename>,
<filename>sound.target</filename>,
<varlistentry>
<term><filename>emergency.target</filename></term>
<listitem>
- <para>A special target unit that starts an emergency shell
- on the main console. This unit is supposed to be used with
- the kernel command line option
- <varname>systemd.unit=</varname> and has otherwise little
- use.
- </para>
+ <para>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
+ <varname>systemd.unit=</varname>; it is also used when a file system check on a required file system fails,
+ and boot-up cannot continue. Compare with <filename>rescue.target</filename>, which serves a similar purpose,
+ but also starts the most basic services and mounts all file systems.</para>
+
+ <para>Use the <literal>systemd.unit=emergency.target</literal> kernel command line option to boot into this
+ mode. A short alias for this kernel command line option is <literal>emergency</literal>, for compatibility
+ with SysV.</para>
+
+ <para>In many ways booting into <filename>emergency.target</filename> is similar to the effect of booting
+ with <literal>init=/bin/sh</literal> 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.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><filename>rescue.target</filename></term>
<listitem>
- <para>A special target unit for setting up the base system
- and a rescue shell.</para>
+ <para>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
+ <filename>emergency.target</filename>, which is much more reduced and does not provide the file systems or
+ most basic services.</para>
- <para><filename>runlevel1.target</filename> is an alias for
- this target unit, for compatibility with SysV.</para>
+ <para><filename>runlevel1.target</filename> is an alias for this target unit, for compatibility with
+ SysV.</para>
+
+ <para>Use the <literal>systemd.unit=rescue.target</literal> kernel command line option to boot into this
+ mode. A short alias for this kernel command line option is <literal>1</literal>, for compatibility with
+ SysV.</para>
</listitem>
</varlistentry>
<varlistentry>
hook units into the sleep state logic.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><filename>slices.target</filename></term>
+ <listitem>
+ <para>A special target unit that sets up all slice units (see
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ details) that shall be active after boot. By default the generic <filename>user.slice</filename>,
+ <filename>system.slice</filename>, <filename>machines.slice</filename> slice units, as well as the the root
+ slice unit <filename>-.slice</filename> are pulled in and ordered before this unit (see below).</para>
+
+ <para>It's a good idea to add <varname>WantedBy=slices.target</varname> lines to the <literal>[Install]</literal>
+ section of all slices units that may be installed dynamically.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><filename>sockets.target</filename></term>
<listitem>
<para>A special target unit that sets up all socket
- units.(see
+ units (see
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details) that shall be active after boot.</para>
<varlistentry>
<term><filename>umount.target</filename></term>
<listitem>
- <para>A special target unit that umounts all mount and
+ <para>A special target unit that unmounts all mount and
automount points on system shutdown.</para>
<para>Mounts that shall be unmounted on system shutdown
the value and all values plus multiples of the repetition value
are matched.</para>
+ <para>The seconds component may contain decimal fractions both in
+ the value and the repetition. All fractions are rounded to 6
+ decimal places.</para>
+
<para>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, <literal>:00</literal> is
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
<varname>OnUnitInactiveSec=</varname> and ending the time
configured with <varname>AccuracySec=</varname> later. Within
this time window, the expiry time will be placed at a
- host-specific, randomized but stable position that is
+ host-specific, randomized, but stable position that is
synchronized between all local timer units. This is done in
- order to distribute the wake-up time in networked
- installations, as well as optimizing 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
+ 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
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
<varname>TimerSlackNSec=</varname> setting. See
<citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
this value as high as possible and as low as
necessary.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>RandomizedDelaySec=</varname></term>
+
+ <listitem><para>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
+ <varname>AccuracySec=</varname> 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
+ <varname>RandomizedDelaySec=</varname> and
+ <varname>AccuracySec=</varname> 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
+ <varname>AccuracySec=</varname> defaults to 1min and
+ <varname>RandomizedDelaySec=</varname> 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
+ <varname>RandomizedDelaySec=</varname> to a higher value, and
+ <varname>AccuracySec=1us</varname>.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>Unit=</varname></term>
</varlistentry>
<varlistentry>
- <term><varname>RemainAfterExit=</varname></term>
+ <term><varname>RemainAfterElapse=</varname></term>
<listitem><para>Takes a boolean argument. If true, an elapsed
- timer will stay loaded, and its state remains
- queriable. Defaults to
+ 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
+ <varname>RemainAfterElapse=</varname> is on, it will not be
+ started again, and is guaranteed to elapse only once. However,
+ if <varname>RemainAfterLeapse=</varname> is off, it might be
+ started again if it is already elapsed, and thus be triggered
+ multiple times. Defaults to
<varname>yes</varname>.</para></listitem>
</varlistentry>
</variablelist>
directory suffix is <filename>.requires/</filename> in this
case.</para>
- <para>Along with a unit file <filename>foo.service</filename>, a
- directory <filename>foo.service.d/</filename> may exist. All files
- with the suffix <literal>.conf</literal> from this directory will
- be parsed after the file itself is parsed. This is useful to alter
- or add configuration settings to a unit, without having to modify
- their unit files. Make sure that the file that is included has the
- appropriate section headers before any directive. Note that, for
- instanced units, this logic will first look for the instance
- <literal>.d/</literal> subdirectory and read its
- <literal>.conf</literal> files, followed by the template
- <literal>.d/</literal> subdirectory and reads its
- <literal>.conf</literal> files.</para>
-
+ <para>Along with a unit file <filename>foo.service</filename>, a "drop-in" directory
+ <filename>foo.service.d/</filename> may exist. All files with the suffix <literal>.conf</literal> 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 <literal>.d/</literal> subdirectory and read its
+ <literal>.conf</literal> files, followed by the template <literal>.d/</literal> subdirectory and the
+ <literal>.conf</literal> files there. Also note that settings from the <literal>[Install]</literal> section are not
+ honoured in drop-in unit files, and have no effect.</para>
+
+ <para>In addition to <filename>/etc/systemd/system</filename>,
+ the drop-in <literal>.conf</literal> files for system services
+ can be placed in <filename>/usr/lib/systemd/system</filename> or
+ <filename>/run/systemd/system</filename> directories. Drop-in
+ files in <filename>/etc</filename> take precedence over those in
+ <filename>/run</filename> which in turn take precedence over
+ those in <filename>/usr/lib</filename>. Drop-in files under any of
+ these directories take precedence over unit files wherever located.
+ (Of course, since <filename>/run</filename> is temporary and
+ <filename>/usr/lib</filename> is for vendors, it is unlikely
+ drop-ins should be used in either of those places.)</para>
<!-- Note that we do not document .include here, as we
consider it mostly obsolete, and want people to
use .d/ drop-ins instead. -->
<term><varname>JobTimeoutAction=</varname></term>
<term><varname>JobTimeoutRebootArgument=</varname></term>
- <listitem><para>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 <literal>failed</literal> mode. This value defaults
- to 0 (job timeouts disabled), except for device units. NB:
- this timeout is independent from any unit-specific timeout
- (for example, the timeout set with
- <varname>TimeoutStartSec=</varname> 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.</para>
+ <listitem><para>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
+ <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts disabled),
+ except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the
+ timeout set with <varname>TimeoutStartSec=</varname> 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.</para>
<para><varname>JobTimeoutAction=</varname>
optionally configures an additional
system call.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>StartLimitInterval=</varname></term>
+ <term><varname>StartLimitBurst=</varname></term>
+
+ <listitem><para>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 <varname>StartLimitInterval=</varname> to configure the
+ checking interval (defaults to <varname>DefaultStartLimitInterval=</varname> in manager configuration file, set
+ to 0 to disable any kind of rate limiting). Use <varname>StartLimitBurst=</varname> to configure how many
+ starts per interval are allowed (defaults to <varname>DefaultStartLimitBurst=</varname> in manager
+ configuration file). These configuration options are particularly useful in conjunction with the service
+ setting <varname>Restart=</varname> (see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>); however,
+ they apply to all kinds of starts (including manual), not just those triggered by the
+ <varname>Restart=</varname> logic. Note that units which are configured for <varname>Restart=</varname> 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
+ <command>systemctl reset-failed</command> 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.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>StartLimitAction=</varname></term>
+
+ <listitem><para>Configure the action to take if the rate limit configured with
+ <varname>StartLimitInterval=</varname> and <varname>StartLimitBurst=</varname> is hit. Takes one of
+ <option>none</option>, <option>reboot</option>, <option>reboot-force</option>,
+ <option>reboot-immediate</option>, <option>poweroff</option>, <option>poweroff-force</option> or
+ <option>poweroff-immediate</option>. If <option>none</option> is set, hitting the rate limit will trigger no
+ action besides that the start will not be permitted. <option>reboot</option> causes a reboot following the
+ normal shutdown procedure (i.e. equivalent to <command>systemctl reboot</command>).
+ <option>reboot-force</option> causes a forced reboot which will terminate all processes forcibly but should
+ cause no dirty file systems on reboot (i.e. equivalent to <command>systemctl reboot -f</command>) and
+ <option>reboot-immediate</option> causes immediate execution of the
+ <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call, which
+ might result in data loss. Similarly, <option>poweroff</option>, <option>poweroff-force</option>,
+ <option>poweroff-immediate</option> have the effect of powering down the system with similar
+ semantics. Defaults to <option>none</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>RebootArgument=</varname></term>
+ <listitem><para>Configure the optional argument for the
+ <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call if
+ <varname>StartLimitAction=</varname> or a service's <varname>FailureAction=</varname> is a reboot action. This
+ works just like the optional argument to <command>systemctl reboot</command> command.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>ConditionArchitecture=</varname></term>
<term><varname>ConditionVirtualization=</varname></term>
useful and probably just
confusing. -->
- <listitem><para>Before starting a unit verify that the
- specified condition is true. If it is not true, the starting
- of the unit will be 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.</para>
+ <listitem><para>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 <varname>AssertArchitecture=</varname>,
+ <varname>AssertVirtualization=</varname>, … options for a similar mechanism that puts the unit in a failure
+ state and logs about the failed check (see below).</para>
<para><varname>ConditionArchitecture=</varname> may be used to
check whether the system is running on a specific
<para><varname>ConditionSecurity=</varname> may be used to
check whether the given security module is enabled on the
- system. Currently, the recognized values values are
+ system. Currently, the recognized values are
<varname>selinux</varname>,
<varname>apparmor</varname>,
<varname>ima</varname>,
<filename>/var</filename> on the next following boot. Units
making use of this condition should order themselves before
<citerefentry><refentrytitle>systemd-update-done.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- to make sure they run before the stamp files's modification
+ to make sure they run before the stamp file's modification
time gets reset indicating a completed update.</para>
<para><varname>ConditionFirstBoot=</varname> takes a boolean
<term><varname>AssertFileNotEmpty=</varname></term>
<term><varname>AssertFileIsExecutable=</varname></term>
- <listitem><para>Similar to the
- <varname>ConditionArchitecture=</varname>,
- <varname>ConditionVirtualization=</varname>, etc., 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 it was triggered
- by.</para></listitem>
+ <listitem><para>Similar to the <varname>ConditionArchitecture=</varname>,
+ <varname>ConditionVirtualization=</varname>, …, 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.</para></listitem>
</varlistentry>
<varlistentry>
<refsect1>
<title>[Install] Section Options</title>
- <para>Unit file may include an <literal>[Install]</literal>
- section, which carries installation information for the unit. This
- section is not interpreted by
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- during runtime. It is used exclusively by the
- <command>enable</command> and <command>disable</command> commands
- of the
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- tool during installation of a unit:</para>
+ <para>Unit files may include an <literal>[Install]</literal> section, which carries installation information for
+ the unit. This section is not interpreted by
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> during runtime; it is
+ used by the <command>enable</command> and <command>disable</command> commands of the
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> tool during
+ installation of a unit. Note that settings in the <literal>[Install]</literal> section may not appear in
+ <filename>.d/*.conf</filename> unit file drop-ins (see above).</para>
<variablelist class='unit-directives'>
<varlistentry>
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.</para>
+
</example>
</refsect1>
<option>inherit</option>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--machine-id=</option></term>
+
+ <listitem><para>Override the machine-id set on the hard drive,
+ useful for network booting or for containers. May not be set
+ to all zeros.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
script runlevel link farms.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>$SYSTEMD_COLORS</varname></term>
+
+ <listitem><para>Controls whether colorized output should be generated.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>$LISTEN_PID</varname></term>
<term><varname>$LISTEN_FDS</varname></term>
than once to set multiple variables.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>systemd.machine_id=</varname></term>
+
+ <listitem><para>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.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>quiet</varname></term>
<varlistentry>
<term><varname>m</varname></term>
<listitem><para>Add a user to a group. If the user or group
- are not existing yet, they will be implicitly
+ do not exist yet, they will be implicitly
created.</para></listitem>
</varlistentry>
<refsect1>
<title>Options</title>
+ <para>The following settings are configured in the <literal>[Time]</literal> section:</para>
+
<variablelist class='network-directives'>
<varlistentry>
be removed and be replaced by the symlink. If the argument
is omitted, symlinks to files with the same name residing in
the directory <filename>/usr/share/factory/</filename> are
- created.</para></listitem>
+ created. Note that permissions and ownership on symlinks
+ are ignored.</para></listitem>
</varlistentry>
<varlistentry>
<command>systemd-tmpfiles</command> 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 explictly specified. The mask will be added if not
+ 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
a <filename>uevent</filename> file. <function>udev_device_new_from_devnum</function>
takes a device type, which can be <constant>b</constant> for block devices or
<constant>c</constant> for character devices, as well as a devnum (see
- <citerefentry><refentrytitle>makedev</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
+ <citerefentry project='man-pages'><refentrytitle>makedev</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
<function>udev_device_new_from_subsystem_sysname</function> looks up devices based
on the provided subsystem and sysname
(see <citerefentry><refentrytitle>udev_device_get_subsystem</refentrytitle><manvolnum>3</manvolnum></citerefentry>
<para><function>udev_device_new_from_environment</function>
creates a device from the current environment (see
- <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
+ <citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
Each key-value pair is interpreted in the same way as if it was
received in an uevent (see
<citerefentry><refentrytitle>udev_monitor_receive_device</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
<function>udev_device_new_from_device_id()</function> and
<function>udev_device_new_from_environment()</function> return a
pointer to the allocated udev device. On failure,
- <constant>NULL</constant> is returned.
+ <constant>NULL</constant> is returned,
+ and <varname>errno</varname> is set appropriately.
<function>udev_device_ref()</function> returns the argument
that it was passed, unmodified.
<function>udev_device_unref()</function> always returns
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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 (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>\n"
"Language-Team: team@lists.gnome.gr\n"
"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 ""
msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
+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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
#, fuzzy
msgid ""
"Authentication is required to manage local virtual machine and container "
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 "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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 <alex94puchades@gmail.com>\n"
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
"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"
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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
"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 "
# Hungarian translation of systemd
-# Copyright (C) 2015. Free Software Foundation, Inc.
+# Copyright (C) 2015, 2016. Free Software Foundation, Inc.
# This file is distributed under the same license as the systemd package.
#
-# Gabor Kelemen <kelemeng at gnome dot hu>, 2015.
+# Gabor Kelemen <kelemeng at gnome dot hu>, 2015, 2016.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-01-02 22:58+0100\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 <kelemeng at ubuntu dot com>\n"
"Language-Team: Hungarian <openscope at googlegroups dot com>\n"
"Language: hu\n"
"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
-#, fuzzy
msgid "Manage system services or other units"
-msgstr "Rendszerszolgáltatások vagy -egységek kezelése"
+msgstr "Rendszerszolgáltatások vagy más egységek kezelése"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
msgid "Authentication is required to manage system services or other units."
msgstr ""
-"Hitelesítés szükséges a rendszerszolgáltatások vagy -egységek kezeléséhez."
+"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"
#: ../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
-#, fuzzy
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr ""
-"Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez."
+"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"
#: ../src/import/org.freedesktop.import1.policy.in.h:1
msgid "Import a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép importálása"
#: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
msgid "Authentication is required to import a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+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 ""
+msgstr "VM vagy konténer lemezkép exportálása"
#: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
msgid "Authentication is required to export a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+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 ""
+msgstr "VM vagy konténer lemezkép letöltése"
#: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
msgid "Authentication is required to download a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+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"
#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése"
#: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+"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 ""
+msgstr "Aktív munkamenetek zárolása vagy feloldása"
#: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+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 ""
+msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja"
#: ../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 "Hitelesítés szükséges a helyi gépnév beállításához."
+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
-#, fuzzy
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 "Manage local virtual machines and containers"
-msgstr ""
+msgid "Log into the local host"
+msgstr "Bejelentkezés a helyi gépre"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
+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 a helyi gép információinak beállításához."
+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:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Helyi virtuális gép és konténer lemezképek kezelése"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../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 gép információinak beállításához."
+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"
"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)”."
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-06-10 23:10+0100\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 <dmedri@gmail.com>\n"
"Language-Team: Italian\n"
"Language: it\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.6\n"
+"X-Generator: Poedit 1.8.5\n"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
msgid "Send passphrase back to system"
"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"
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:4
+#: ../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:5
+#: ../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:6
+#: ../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 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)'."
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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 <rafael.f.f1@gmail.com>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"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"
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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
#, fuzzy
msgid ""
"Authentication is required to manage local virtual machine and container "
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."
# translation of ru.po to Rissian
# Julia Dronova <juliette.tux@gmail.com>, 2013.
-# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2015.
+# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2016.
#
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-03-22 21:53+0300\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"
msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию."
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
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/login/org.freedesktop.login1.policy.in.h:53
msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+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 "Чтобы настроить имя компьютера, необходимо пройти аутентификацию."
+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: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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
"Чтобы включить или выключить синхронизацию времени по сети, необходимо "
"пройти аутентификацию."
+#: ../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"
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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 <sebras@gmail.com>\n"
"Language-Team: Swedish\n"
"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"
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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
"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."
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Eugene Melnik <jeka7js@gmail.com>, 2014.
-# Daniel Korostil <ted.korostiled@gmail.com>, 2014.
+# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2014-07-16 19:13+0300\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 <ted.korostiled@gmail.com>\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"
+"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
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
msgid "Manage system services or other units"
-msgstr ""
+msgstr "Керувати системними службами й іншими одиницями"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
msgid "Authentication is required to manage system services or other units."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й іншими одиницями."
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
msgid "Manage system service or unit files"
-msgstr ""
+msgstr "Керувати системними службами й файлами одиниць"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
-#, fuzzy
msgid "Authentication is required to manage system service or unit files."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й файлами одиниць."
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
-#, fuzzy
msgid "Set or unset system and service manager environment variables"
-msgstr "Привілейований доступ до менеджера системи і служб"
+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 "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб установити або забрати змінні середовища з "
+"керування службами і системою."
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
-#, fuzzy
msgid "Reload the systemd state"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83"
+msgstr "Ð\9fеÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми"
#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
-#, fuzzy
msgid "Authentication is required to reload the systemd state."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об вказаÑ\82и Ñ\81иÑ\81Ñ\82емний Ñ\87аÑ\81."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об пеÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми."
#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
msgid "Set host name"
#: ../src/import/org.freedesktop.import1.policy.in.h:1
msgid "Import a VM or container image"
-msgstr ""
+msgstr "Імпортувати образ контейнера або віртуальної машини"
#: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
msgid "Authentication is required to import a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини"
#: ../src/import/org.freedesktop.import1.policy.in.h:3
msgid "Export a VM or container image"
-msgstr ""
+msgstr "Експортувати образ контейнера або віртуальної машини"
#: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
msgid "Authentication is required to export a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної "
+"машини"
#: ../src/import/org.freedesktop.import1.policy.in.h:5
msgid "Download a VM or container image"
-msgstr ""
+msgstr "Звантажити образ контейнера або віртуальної машини"
#: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
msgid "Authentication is required to download a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини"
#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
msgid "Set system locale"
#: ../src/login/org.freedesktop.login1.policy.in.h:27
msgid "Power off the system while other users are logged in"
-msgstr "Ð\92имикнÑ\83Ñ\82и Ñ\81иÑ\81Ñ\82емÑ\83, коли Ñ\96нÑ\88Ñ\96 коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87Ñ\96 Ñ\89е в нÑ\96й"
+msgstr "Вимкнути систему, коли інші користувачі ще в ній"
#: ../src/login/org.freedesktop.login1.policy.in.h:28
msgid ""
#: ../src/login/org.freedesktop.login1.policy.in.h:29
msgid "Power off the system while an application asked to inhibit it"
-msgstr "Вимкнути систему, коли програми намагаються першкодити цьому"
+msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому"
#: ../src/login/org.freedesktop.login1.policy.in.h:30
msgid ""
"asked to inhibit it."
msgstr ""
"Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
#: ../src/login/org.freedesktop.login1.policy.in.h:31
msgid "Reboot the system"
#: ../src/login/org.freedesktop.login1.policy.in.h:33
msgid "Reboot the system while other users are logged in"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\89і користувачі в системі"
+msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\88і користувачі в системі"
#: ../src/login/org.freedesktop.login1.policy.in.h:34
msgid ""
#: ../src/login/org.freedesktop.login1.policy.in.h:35
msgid "Reboot the system while an application asked to inhibit it"
-msgstr "Перезапустити систему, коли програми намагаються першкодити цьому"
+msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому"
#: ../src/login/org.freedesktop.login1.policy.in.h:36
msgid ""
"asked to inhibit it."
msgstr ""
"Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
#: ../src/login/org.freedesktop.login1.policy.in.h:37
msgid "Suspend the system"
#: ../src/login/org.freedesktop.login1.policy.in.h:41
msgid "Suspend the system while an application asked to inhibit it"
-msgstr "Призупинити систему, коли програми намагаються першкодити цьому"
+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 ""
-"Засвідчення потрібно, щоб призупнити систему, коли програми намагаються "
-"першкодити цьому."
+"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об пÑ\80изÑ\83пиниÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83, коли пÑ\80огÑ\80ами намагаÑ\8eÑ\82Ñ\8cÑ\81Ñ\8f "
+"перешкодити цьому."
#: ../src/login/org.freedesktop.login1.policy.in.h:43
msgid "Hibernate the system"
#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Приспати систему, коли програми намагаються першкодити цьому"
+msgstr "Приспати систему, коли програми намагаються перешкодити цьому"
#: ../src/login/org.freedesktop.login1.policy.in.h:48
msgid ""
"asked to inhibit it."
msgstr ""
"Засвідчення потрібно, щоб приспати систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Керувати сеансами, користувачами і робочими місцями"
#: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
msgid ""
"Authentication is required for managing active sessions, users and seats."
-msgstr "Засвідчення потрібно, щоб під'єднувати пристрої до місць."
+msgstr ""
+"Засвідчення потрібно, щоб керувати сеансами, користувачами і робочими "
+"місцями."
#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Заблокувати або розблокувати сеанси"
#: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об вказаÑ\82и локалÑ\8cнÑ\83 Ñ\96нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e пÑ\80о маÑ\88ини."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об заблокÑ\83ваÑ\82и або Ñ\80озблокÑ\83ваÑ\82и Ñ\81еанÑ\81и."
#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+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 "Засвідчення потрібне, щоб встановити назву локального вузла."
+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 ""
+msgstr "Увійти в локальний контейнер"
#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
msgid "Authentication is required to log into a local container."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер."
#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
-msgstr ""
+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
+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 "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними віртуальними машинами і "
+"контейнерами."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Керувати локальними образами віртуальних машин і контейнерів"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і "
+"контейнерів."
#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
msgid "Set system time"
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)»."
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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 <s8321414@gmail.com>\n"
"Language-Team: chinese-l10n <chinese-l10n@googlegroups.com>\n"
"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 "登入到本機容器"
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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
"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 "設定系統時間需要驗證。"
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
--utc -x --catalog --no-full --force --dump-catalog
--flush --rotate --sync'
[ARG]='-b --boot --this-boot -D --directory --file -F --field
- -o --output -u --unit --user-unit -p --priority
+ -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 -M --machine'
+ --root'
)
if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then
;;
--field|-F)
comps=${__journal_fields[*]}
+ ;;
+ --machine|-M)
+ comps=$( __get_machines )
;;
--priority|-p)
comps=${__syslog_priorities[*]}
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
--signal|-s)
- comps=$(compgen -A signal)
+ _signals
+ return
;;
--kill-who)
comps='all leader'
)
local -A VERBS=(
- [STANDALONE]='list list-images pull-tar pull-raw pull-dkr import-tar import-raw export-tar export-raw list-transfers cancel-transfer'
+ [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'
)
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
--signal|-s)
- comps=$(compgen -A signal)
+ _signals
+ return
;;
--kill-who)
comps='all leader'
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
--signal|-s)
- comps=$(compgen -A signal)
+ _signals
+ return
;;
--type|-t)
comps=$(__systemctl $mode -t help)
[STARTABLE_UNITS]='start'
[STOPPABLE_UNITS]='stop condstop kill try-restart condrestart'
[ISOLATABLE_UNITS]='isolate'
- [RELOADABLE_UNITS]='reload condreload reload-or-try-restart force-reload'
+ [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'
[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'
+ --network-macvlan --kill-signal'
)
_init_completion || return
compopt -o nospace
comps=$( compgen -A file -- "$cur" )
;;
+ --kill-signal)
+ _signals
+ return
+ ;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
#compdef busctl
-# hostnamectl(1) completion -*- shell-script -*-
+# busctl(1) completion -*- shell-script -*-
#
# This file is part of systemd.
#
_journal_fields() {
local -a _fields cmd
cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" )
- _fields=( ${(f)"$(_call_program fields $cmd[@])"} )
+ _fields=$(_call_program fields $cmd[@])
+ _fields=${_fields//'\'/'\\'}
+ _fields=${_fields//':'/'\:'}
+ _fields=( ${(f)_fields} )
typeset -U _fields
_describe 'possible values' _fields
}
"pull-tar:Download a TAR container image"
"pull-raw:Download a RAW container or VM image"
- "pull-dkr:Download a DKR container image"
"list-transfers:Show list of downloads in progress"
"cancel-transfer:Cancel a download"
)
if (( $#cmd )); then
if (( CURRENT == 2 )); then
case $cmd in
- list*|cancel-transfer|pull-tar|pull-raw|pull-dkr)
+ list*|cancel-transfer|pull-tar|pull-raw)
msg="no options" ;;
start)
_available_machines ;;
{-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.]' \
- '--dkr-index-url=[Specify the index URL to use for DKR image downloads.]' \
'*::machinectl command:_machinectl_command'
"force-reload:Reload one or more units if possible, otherwise restart if active"
"hibernate:Hibernate the system"
"hybrid-sleep:Hibernate and suspend the system"
- "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active"
+ "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"
# Deal with any aliases
case $cmd in
condrestart) cmd="try-restart";;
- force-reload) cmd="reload-or-try-restart";;
+ force-reload) cmd="try-reload-or-restart";;
esac
if (( $#cmd )); then
}
# Completion functions for RELOADABLE_UNITS
-for fun in reload reload-or-try-restart force-reload ; do
+for fun in reload try-reload-or-restart force-reload ; do
(( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
{
local _sys_active_units; _systemctl_active_units
'--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 net_cls blkio)'
+ ':cgroups:(cpuset cpu cpuacct memory devices freezer blkio)'
;;
systemd-cgtop)
_arguments \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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 = {
*/
STRV_FOREACH(address, arg_listen) {
-
- fd = make_socket_fd(LOG_DEBUG, *address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC));
+ 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);
return count;
}
-static int launch(char* name, char **argv, char **env, int fds) {
+static int exec_process(const char* name, char **argv, char **env, int start_fd, int n_fds) {
- static const char* tocopy[] = {"TERM=", "PATH=", "USER=", "HOME="};
_cleanup_strv_free_ char **envp = NULL;
- _cleanup_free_ char *tmp = NULL;
+ _cleanup_free_ char *joined = NULL;
unsigned n_env = 0, length;
- char **s;
+ 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);
return log_oom();
STRV_FOREACH(s, arg_setenv) {
- if (strchr(*s, '='))
- envp[n_env++] = *s;
- else {
+
+ 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();
- envp[n_env] = strv_find_prefix(env, p);
- if (envp[n_env])
- n_env ++;
+
+ n = strv_find_prefix(env, p);
+ if (!n)
+ continue;
+
+ envp[n_env] = strdup(n);
+ if (!envp[n_env])
+ return log_oom();
+
+ n_env ++;
}
}
- for (i = 0; i < ELEMENTSOF(tocopy); i++) {
- envp[n_env] = strv_find_prefix(env, tocopy[i]);
- if (envp[n_env])
- 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 ((asprintf((char**)(envp + n_env++), "LISTEN_FDS=%d", fds) < 0) ||
- (asprintf((char**)(envp + n_env++), "LISTEN_PID=%d", getpid()) < 0))
- return log_oom();
+ 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");
- if (arg_fdname) {
- char *e;
+ 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");
- e = strappend("LISTEN_FDNAMES=", arg_fdname);
- if (!e)
+ 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();
- for (i = 1; i < (unsigned) fds; i++) {
- char *c;
+ if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT, getpid()) < 0)
+ return log_oom();
- c = strjoin(e, ":", arg_fdname, NULL);
- if (!c) {
- free(e);
+ 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;
}
- free(e);
- e = c;
+ envp[n_env++] = e;
}
-
- envp[n_env++] = e;
}
- tmp = strv_join(argv, " ");
- if (!tmp)
+ joined = strv_join(argv, " ");
+ if (!joined)
return log_oom();
- log_info("Execing %s (%s)", name, tmp);
+ log_info("Execing %s (%s)", name, joined);
execvpe(name, argv, envp);
- return log_error_errno(errno, "Failed to execp %s (%s): %m", name, tmp);
+ return log_error_errno(errno, "Failed to execp %s (%s): %m", name, joined);
}
-static int launch1(const char* child, char** argv, char **env, int fd) {
- _cleanup_free_ char *tmp = NULL;
+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;
- int r;
- tmp = strv_join(argv, " ");
- if (!tmp)
+ joined = strv_join(argv, " ");
+ if (!joined)
return log_oom();
parent_pid = getpid();
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
- r = dup2(fd, STDIN_FILENO);
- if (r < 0) {
- log_error_errno(errno, "Failed to dup connection to stdin: %m");
- _exit(EXIT_FAILURE);
- }
-
- r = dup2(fd, STDOUT_FILENO);
- if (r < 0) {
- log_error_errno(errno, "Failed to dup connection to stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
- r = close(fd);
- if (r < 0) {
- log_error_errno(errno, "Failed to close dupped connection: %m");
- _exit(EXIT_FAILURE);
- }
-
/* Make sure the child goes away when the parent dies */
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
_exit(EXIT_FAILURE);
if (getppid() != parent_pid)
_exit(EXIT_SUCCESS);
- execvp(child, argv);
- log_error_errno(errno, "Failed to exec child %s: %m", child);
+ exec_process(child, argv, env, fd, 1);
_exit(EXIT_FAILURE);
}
- log_info("Spawned %s (%s) as PID %d", child, tmp, child_pid);
-
+ 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 fd2 = -1;
+ _cleanup_close_ int fd_accepted = -1;
- fd2 = accept(fd, NULL, NULL);
- if (fd2 < 0) {
- log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd);
- return fd2;
- }
+ 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(fd2, &local);
- getpeername_pretty(fd2, &peer);
+ getsockname_pretty(fd_accepted, &local);
+ getpeername_pretty(fd_accepted, true, &peer);
log_info("Connection from %s to %s", strna(peer), strna(local));
- return launch1(name, argv, envp, fd2);
+ return fork_and_exec_process(name, argv, envp, fd_accepted);
}
/* SIGCHLD handler. */
PROTECT_ERRNO;
log_info("Child %d died with code %d", t->si_pid, t->si_status);
+
/* Wait for a dead child. */
- waitpid(t->si_pid, NULL, 0);
+ (void) waitpid(t->si_pid, NULL, 0);
}
static int install_chld_handler(void) {
- int r;
- struct sigaction act = {
+ static const struct sigaction act = {
.sa_flags = SA_SIGINFO,
.sa_sigaction = sigchld_hdl,
};
+ int r;
+
r = sigaction(SIGCHLD, &act, 0);
if (r < 0)
- log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
- return r;
+ 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"
- " -h --help Show this help and exit\n"
" -E --setenv=NAME[=VALUE] Pass an environment variable to children\n"
- " --version Print version string and exit\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);
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 },
{}
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hl:aE:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0)
switch(c) {
case 'h':
help();
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;
arg_fdname = optarg;
break;
+ case ARG_INETD:
+ arg_inetd = true;
+ break;
+
case '?':
return -EINVAL;
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 */;
log_info("Communication attempt on fd %i.", event.data.fd);
if (arg_accept) {
- r = do_accept(argv[optind], argv + optind, envp,
- event.data.fd);
+ r = do_accept(argv[optind], argv + optind, envp, event.data.fd);
if (r < 0)
return EXIT_FAILURE;
} else
break;
}
- launch(argv[optind], argv + optind, envp, n);
+ exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, n);
return EXIT_SUCCESS;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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;
}
static int verify_unit(Unit *u, bool check_man) {
- _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
int r, k;
assert(u);
}
int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man) {
- _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
Manager *m = NULL;
FILE *serial = NULL;
FDSet *fdset = NULL;
log_debug("Loading remaining units from the command line...");
STRV_FOREACH(filename, filenames) {
- char fname[UNIT_NAME_MAX + 2 + 1] = "./";
+ _cleanup_free_ char *prepared = NULL;
log_debug("Handling %s...", *filename);
- /* manager_load_unit does not like pure basenames, so prepend
- * the local directory, but only for valid names. manager_load_unit
- * will print the error for other ones. */
- if (!strchr(*filename, '/') && strlen(*filename) <= UNIT_NAME_MAX) {
- strncat(fname + 2, *filename, UNIT_NAME_MAX);
- k = manager_load_unit(m, NULL, fname, &err, &units[count]);
- } else
- k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
+ 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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
}
static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info*, free_host_info);
static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
{}
};
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(free_host_infop) struct host_info *host;
int r;
int r;
const char *id;
_cleanup_free_ char *path = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_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);
int r;
STRV_FOREACH(pattern, patterns) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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)
}
static int dot(sd_bus *bus, char* patterns[]) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int dump(sd_bus *bus, char **args) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int set_log_level(sd_bus *bus, char **args) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
}
static int set_log_target(sd_bus *bus, char **args) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
arg_user ? MANAGER_USER : MANAGER_SYSTEM,
arg_man);
else {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
device = udev_device_new_from_subsystem_sysname(udev, ss, sysname);
if (!device) {
- if (errno != 0)
+ if (errno > 0)
log_error_errno(errno, "Failed to get backlight or LED device '%s:%s': %m", ss, sysname);
else
log_oom();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <sys/socket.h>
#include "af-list.h"
-#include "util.h"
+#include "macro.h"
static const struct af_name* lookup_af(register const char *str, register unsigned int len);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdint.h>
+#include <string.h>
+
#include "alloc-util.h"
+#include "macro.h"
#include "util.h"
void* memdup(const void *p, size_t l) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <alloca.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <string.h>
#include "arphrd-list.h"
-#include "util.h"
+#include "macro.h"
static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <pthread.h>
+#include <stddef.h>
#include <unistd.h>
#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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <linux/netlink.h>
#include <stdio.h>
+#include <sys/socket.h>
#include "alloc-util.h"
#include "audit-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "user-util.h"
-#include "util.h"
int audit_session_from_pid(pid_t pid, uint32_t *id) {
_cleanup_free_ char *s = NULL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include <sys/types.h>
#define AUDIT_SESSION_INVALID ((uint32_t) -1)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "barrier.h"
#include "fd-util.h"
#include "macro.h"
-#include "util.h"
/**
* Barriers
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));
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+#include <stdint.h>
#include <sys/types.h>
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "alloc-util.h"
#include "bitmap.h"
-#include "util.h"
+#include "hashmap.h"
+#include "macro.h"
struct Bitmap {
uint64_t *bitmaps;
bool bitmap_isclear(Bitmap *b) {
unsigned i;
- assert(b);
+ if (!b)
+ return true;
for (i = 0; i < b->n_bitmaps; i++)
if (b->bitmaps[i] != 0)
}
void bitmap_clear(Bitmap *b) {
- assert(b);
+
+ if (!b)
+ return;
b->bitmaps = mfree(b->bitmaps);
b->n_bitmaps = 0;
Bitmap *c;
unsigned i;
- if (!a ^ !b)
+ if (a == b)
+ return true;
+
+ if (!a != !b)
return false;
if (!a)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "macro.h"
+#include <stdbool.h>
+
#include "hashmap.h"
+#include "macro.h"
typedef struct Bitmap Bitmap;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/loop.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
#ifdef HAVE_LINUX_BTRFS_H
#include <linux/btrfs.h>
#endif
#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
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;
args.key.nr_items = 256;
if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
+ return negative_errno();
if (args.key.nr_items <= 0)
break;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#pragma once
#include <stdbool.h>
+#include <stdint.h>
#include <sys/types.h>
+#include "sd-id128.h"
+
#include "time-util.h"
typedef struct BtrfsSubvolInfo {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-label.h"
#include "hexdecoct.h"
#include "macro.h"
-#include "util.h"
char *bus_label_escape(const char *s) {
char *r, *t;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+/*
+ * 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 <assert.h>
+#include <stddef.h>
+#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);
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+/*
+ * 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#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
free_chain(c->day);
free_chain(c->hour);
free_chain(c->minute);
- free_chain(c->second);
+ free_chain(c->microsecond);
free(c);
}
sort_chain(&c->day);
sort_chain(&c->hour);
sort_chain(&c->minute);
- sort_chain(&c->second);
+ sort_chain(&c->microsecond);
return 0;
}
if (!chain_valid(c->minute, 0, 59))
return false;
- if (!chain_valid(c->second, 0, 59))
+ if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1))
return false;
return true;
}
}
-static void format_chain(FILE *f, int space, const CalendarComponent *c) {
+static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) {
assert(f);
if (!c) {
}
assert(c->value >= 0);
- fprintf(f, "%0*i", space, c->value);
-
- if (c->repeat > 0)
- fprintf(f, "/%i", c->repeat);
+ 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);
+ format_chain(f, space, c->next, usec);
}
}
fputc(' ', f);
}
- format_chain(f, 4, c->year);
+ format_chain(f, 4, c->year, false);
fputc('-', f);
- format_chain(f, 2, c->month);
+ format_chain(f, 2, c->month, false);
fputc('-', f);
- format_chain(f, 2, c->day);
+ format_chain(f, 2, c->day, false);
fputc(' ', f);
- format_chain(f, 2, c->hour);
+ format_chain(f, 2, c->hour, false);
fputc(':', f);
- format_chain(f, 2, c->minute);
+ format_chain(f, 2, c->minute, false);
fputc(':', f);
- format_chain(f, 2, c->second);
+ format_chain(f, 2, c->microsecond, true);
if (c->utc)
fputs(" UTC", f);
}
}
-static int prepend_component(const char **p, CalendarComponent **c) {
- unsigned long value, repeat = 0;
- char *e = NULL, *ee = NULL;
- CalendarComponent *cc;
-
- assert(p);
- assert(c);
+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, &e, 10);
+ value = strtoul(*p, &ee, 10);
if (errno > 0)
return -errno;
- if (e == *p)
+ if (ee == *p)
return -EINVAL;
if ((unsigned long) (int) value != value)
return -ERANGE;
+ e = ee;
- if (*e == '/') {
- repeat = strtoul(e+1, &ee, 10);
- if (errno > 0)
- return -errno;
- if (ee == e+1)
- return -EINVAL;
- if ((unsigned long) (int) repeat != repeat)
- return -ERANGE;
- if (repeat <= 0)
+ if (usec) {
+ if (value * USEC_PER_SEC / USEC_PER_SEC != value)
return -ERANGE;
- e = ee;
+ 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 != ':')
if (*e ==',') {
*p += 1;
- return prepend_component(p, c);
+ return prepend_component(p, usec, c);
}
return 0;
}
-static int parse_chain(const char **p, CalendarComponent **c) {
+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;
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;
- *c = NULL;
return 0;
}
- r = prepend_component(&t, &cc);
+ r = prepend_component(&t, usec, &cc);
if (r < 0) {
free_chain(cc);
return r;
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_date(const char **p, CalendarSpec *c) {
const char *t;
int r;
if (*t == 0)
return 0;
- r = parse_chain(&t, &first);
+ r = parse_chain(&t, false, &first);
if (r < 0)
return r;
}
t++;
- r = parse_chain(&t, &second);
+ r = parse_chain(&t, false, &second);
if (r < 0) {
free_chain(first);
return r;
}
t++;
- r = parse_chain(&t, &third);
+ r = parse_chain(&t, false, &third);
if (r < 0) {
free_chain(first);
free_chain(second);
goto finish;
}
- r = parse_chain(&t, &h);
+ r = parse_chain(&t, false, &h);
if (r < 0)
goto fail;
}
t++;
- r = parse_chain(&t, &m);
+ r = parse_chain(&t, false, &m);
if (r < 0)
goto fail;
}
t++;
- r = parse_chain(&t, &s);
+ r = parse_chain(&t, true, &s);
if (r < 0)
goto fail;
*p = t;
c->hour = h;
c->minute = m;
- c->second = s;
+ c->microsecond = s;
+
return 0;
fail:
}
if (strcaseeq(p, "minutely")) {
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
return (weekdays_bits & (1 << k));
}
-static int find_next(const CalendarSpec *spec, struct tm *tm) {
+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 */
if (r > 0) {
c.tm_mon = 0;
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
}
if (r < 0 || tm_out_of_bounds(&c, spec->utc))
return r;
if (r > 0) {
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 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_year ++;
c.tm_mon = 0;
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ 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 = 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 = 0;
+ 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 = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
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 = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
c.tm_sec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_hour ++;
- c.tm_min = c.tm_sec = 0;
+ c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
- r = find_matching_component(spec->second, &c.tm_sec);
+ 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 = 0;
+ c.tm_sec = tm_usec = 0;
continue;
}
-
*tm = c;
+ *usec = tm_usec;
return 0;
}
}
struct tm tm;
time_t t;
int r;
+ usec_t tm_usec;
assert(spec);
assert(next);
- t = (time_t) (usec / USEC_PER_SEC) + 1;
+ 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);
+ r = find_next(spec, &tm, &tm_usec);
if (r < 0)
return r;
if (t == (time_t) -1)
return -EINVAL;
- *next = (usec_t) t * USEC_PER_SEC;
+ *next = (usec_t) t * USEC_PER_SEC + tm_usec;
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
* time, a la cron */
#include <stdbool.h>
+
+#include "time-util.h"
#include "util.h"
typedef struct CalendarComponent {
CalendarComponent *hour;
CalendarComponent *minute;
- CalendarComponent *second;
+ CalendarComponent *microsecond;
} CalendarSpec;
void calendar_spec_free(CalendarSpec *c);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <string.h>
#include "cap-list.h"
+#include "macro.h"
#include "missing.h"
#include "parse-util.h"
#include "util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <grp.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <unistd.h>
return p;
}
-int capability_bounding_set_drop(uint64_t drop, bool right_now) {
+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;
for (i = 0; i <= cap_last_cap(); i++) {
- if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
+ if (!(keep & (UINT64_C(1) << i))) {
cap_value_t v;
/* Drop it from the bounding set */
return r;
}
-static int drop_from_file(const char *fn, uint64_t drop) {
+static int drop_from_file(const char *fn, uint64_t keep) {
int r, k;
uint32_t hi, lo;
uint64_t current, after;
return -EIO;
current = (uint64_t) lo | ((uint64_t) hi << 32ULL);
- after = current & ~drop;
+ after = current & keep;
if (current == after)
return 0;
return r;
}
-int capability_bounding_set_drop_usermode(uint64_t drop) {
+int capability_bounding_set_drop_usermode(uint64_t keep) {
int r;
- r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", drop);
+ r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep);
if (r < 0)
return r;
- r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", drop);
+ r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep);
if (r < 0)
return r;
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);
+ r = capability_bounding_set_drop(keep_capabilities, true);
if (r < 0)
return log_error_errno(r, "Failed to drop capabilities: %m");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stdint.h>
#include <sys/capability.h>
+#include <sys/types.h>
+#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 drop, bool right_now);
-int capability_bounding_set_drop_usermode(uint64_t drop);
+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);
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <dirent.h>
#include <errno.h>
#include <ftw.h>
+#include <limits.h>
#include <signal.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/statfs.h>
#include <sys/types.h>
#include <unistd.h>
#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 "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"
-#include "util.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
_cleanup_free_ char *fs = NULL;
if (feof(f))
return 0;
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
}
if (ul <= 0)
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) {
if (errno == ENOENT)
r = 0;
- else if (errno != 0)
+ else if (errno > 0)
r = -errno;
else
r = -EIO;
if (pid == 0)
pid = getpid();
- snprintf(c, sizeof(c), PID_FMT"\n", pid);
+ xsprintf(c, PID_FMT "\n", pid);
return write_string_file(fs, c, 0);
}
if (feof(f))
break;
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EBADMSG;
else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
unified_cache = false;
else
- return -ENOEXEC;
+ return -ENOMEDIUM;
return unified_cache;
}
[CGROUP_CONTROLLER_MEMORY] = "memory",
[CGROUP_CONTROLLER_DEVICES] = "devices",
[CGROUP_CONTROLLER_PIDS] = "pids",
- [CGROUP_CONTROLLER_NET_CLS] = "net_cls",
};
DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-#include <stdio.h>
#include <dirent.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
-#include "set.h"
#include "def.h"
+#include "hashmap.h"
+#include "macro.h"
+#include "set.h"
/* An enum of well known cgroup controllers */
typedef enum CGroupController {
CGROUP_CONTROLLER_MEMORY,
CGROUP_CONTROLLER_DEVICES,
CGROUP_CONTROLLER_PIDS,
- CGROUP_CONTROLLER_NET_CLS,
_CGROUP_CONTROLLER_MAX,
_CGROUP_CONTROLLER_INVALID = -1,
} CGroupController;
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_NET_CLS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_NET_CLS),
_CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
} CGroupMask;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include "chattr-util.h"
#include "fd-util.h"
-#include "util.h"
+#include "macro.h"
int chattr_fd(int fd, unsigned value, unsigned mask) {
unsigned old_attr, new_attr;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <time.h>
#include <linux/rtc.h>
#include <stdio.h>
#include <sys/ioctl.h>
* have read from the RTC.
*/
if (settimeofday(tv_null, &tz) < 0)
- return -errno;
+ return negative_errno();
+
if (min)
*min = minutesdelta;
return 0;
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <dirent.h>
#include <errno.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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);
return -errno;
}
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT(de, dir, return -errno) {
char *p;
- errno = 0;
- de = readdir(dir);
- if (!de && errno != 0)
- return -errno;
-
- if (!de)
- break;
-
if (!dirent_is_file_with_suffix(de, suffix))
continue;
STRV_FOREACH(p, dirs) {
r = files_add(fh, root, *p, suffix);
- if (r == -ENOMEM) {
+ if (r == -ENOMEM)
return r;
- } else if (r < 0)
- log_debug_errno(r, "Failed to search for files in %s: %m",
- *p);
+ if (r < 0)
+ log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p);
}
files = hashmap_get_strv(fh);
- if (files == NULL) {
+ if (!files)
return -ENOMEM;
- }
qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp);
*strv = files;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/sendfile.h>
+#include <sys/stat.h>
#include <sys/xattr.h>
+#include <time.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "btrfs-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 "util.h"
#include "xattr-util.h"
#define COPY_BUFFER_SIZE (16*1024)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <inttypes.h>
#include <stdbool.h>
+#include <stdint.h>
#include <sys/types.h>
int copy_file_fd(const char *from, int to, bool try_reflink);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stddef.h>
+#include <syslog.h>
+
#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"
-#include "util.h"
cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
cpu_set_t *c;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stdio.h>
+#include <string.h>
#include "device-nodes.h"
#include "utf8.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
#include <sys/types.h>
int encode_devnode_name(const char *str, char *str_enc, size_t len);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <fcntl.h>
#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
#include "dirent-util.h"
+#include "path-util.h"
#include "string-util.h"
int dirent_ensure_type(DIR *d, struct dirent *de) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
+#include "macro.h"
#include "path-util.h"
int dirent_ensure_type(DIR *d, struct dirent *de);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "alloc-util.h"
-#include "def.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"
-#include "util.h"
#define VALID_CHARS_ENV_NAME \
DIGITS LETTERS \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <string.h>
#include "errno-list.h"
-#include "util.h"
+#include "macro.h"
static const struct errno_name* lookup_errno(register const char *str,
- register unsigned int len);
+ register unsigned int len);
#include "errno-from-name.h"
#include "errno-to-name.h"
sc = lookup_errno(name, strlen(name));
if (!sc)
- return 0;
+ return -EINVAL;
+ assert(sc->id > 0);
return sc->id;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "alloc-util.h"
#include "escape.h"
#include "hexdecoct.h"
-#include "string-util.h"
+#include "macro.h"
#include "utf8.h"
-#include "util.h"
size_t cescape_char(char c, char *buf) {
char * buf_old = buf;
return buf - buf_old;
}
-char *cescape(const char *s) {
- char *r, *t;
+char *cescape_length(const char *s, size_t n) {
const char *f;
+ char *r, *t;
- assert(s);
+ assert(s || n == 0);
/* Does C style string escaping. May be reversed with
* cunescape(). */
- r = new(char, strlen(s)*4 + 1);
+ r = new(char, n*4 + 1);
if (!r)
return NULL;
- for (f = s, t = r; *f; f++)
+ for (f = s, t = r; f < s + n; f++)
t += cescape_char(*f, t);
*t = 0;
return r;
}
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
+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,
- * unless we encountered a \u sequence in which case the full
- * unicode character is returned in ret_unicode, instead. */
+ /* 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;
if (a == 0 && b == 0)
return -EINVAL;
- *ret = (char) ((a << 4U) | b);
+ *ret = (a << 4U) | b;
+ *eight_bit = true;
r = 3;
break;
}
if (c == 0)
return -EINVAL;
- if (c < 128)
- *ret = c;
- else {
- if (!ret_unicode)
- return -EINVAL;
-
- *ret = 0;
- *ret_unicode = c;
- }
-
+ *ret = c;
r = 5;
break;
}
int a[8];
unsigned i;
- uint32_t c;
+ char32_t c;
if (length != (size_t) -1 && length < 9)
return -EINVAL;
if (!unichar_is_valid(c))
return -EINVAL;
- if (c < 128)
- *ret = c;
- else {
- if (!ret_unicode)
- return -EINVAL;
-
- *ret = 0;
- *ret_unicode = c;
- }
-
+ *ret = c;
r = 9;
break;
}
case '7': {
/* octal encoding */
int a, b, c;
- uint32_t m;
+ char32_t m;
if (length != (size_t) -1 && length < 3)
return -EINVAL;
return -EINVAL;
*ret = m;
+ *eight_bit = true;
r = 3;
break;
}
for (f = s, t = r + pl; f < s + length; f++) {
size_t remaining;
- uint32_t u;
- char c;
+ bool eight_bit = false;
+ char32_t u;
int k;
remaining = s + length - f;
return -EINVAL;
}
- k = cunescape_one(f + 1, remaining - 1, &c, &u);
+ 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 */
return k;
}
- if (c != 0)
- /* Non-Unicode? Let's encode this directly */
- *(t++) = c;
+ f += k;
+ if (eight_bit)
+ /* One byte? Set directly as specified */
+ *(t++) = u;
else
- /* Unicode? Then let's encode this in UTF-8 */
+ /* Otherwise encode as multi-byte UTF-8 */
t += utf8_encode_unichar(t, u);
-
- f += k;
}
*t = 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <uchar.h>
+
+#include "string-util.h"
+#include "missing.h"
/* What characters are special in the shell? */
/* must be escaped outside and inside double-quotes */
} 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, char *ret, uint32_t *ret_unicode);
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
char *xescape(const char *s, const char *bad);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <net/ethernet.h>
#include <stdio.h>
+#include <sys/types.h>
#include "ether-addr-util.h"
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
+#include "hashmap.h"
+#include "macro.h"
#include "set.h"
typedef enum ExitStatus {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
#include "alloc-util.h"
#include "escape.h"
#include "extract-word.h"
+#include "log.h"
+#include "macro.h"
#include "string-util.h"
#include "utf8.h"
-#include "util.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
_cleanup_free_ char *s = NULL;
}
if (flags & EXTRACT_CUNESCAPE) {
- uint32_t u;
+ bool eight_bit = false;
+ char32_t u;
- r = cunescape_one(*p, (size_t) -1, &c, &u);
+ r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
if (r < 0) {
if (flags & EXTRACT_CUNESCAPE_RELAX) {
s[sz++] = '\\';
} else {
(*p) += r - 1;
- if (c != 0)
- s[sz++] = c; /* normal explicit char */
+ if (eight_bit)
+ s[sz++] = u;
else
- sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
+ sz += utf8_encode_unichar(s + sz, u);
}
} else
s[sz++] = c;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "dirent-util.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
+#include <stdio.h>
#include <sys/socket.h>
#include "macro.h"
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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <stddef.h>
#include "sd-daemon.h"
-#include "dirent-util.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"
-#include "util.h"
#define MAKE_SET(s) ((Set*) s)
#define MAKE_FDSET(s) ((FDSet*) s)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
+#include "hashmap.h"
+#include "macro.h"
#include "set.h"
typedef struct FDSet FDSet;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sys/stat.h>
+
#include "fileio-label.h"
+#include "fileio.h"
#include "selinux-util.h"
-#include "util.h"
int write_string_file_atomic_label(const char *fn, const char *line) {
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdio.h>
+
#include "fileio.h"
int write_string_file_atomic_label(const char *fn, const char *line);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include "alloc-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"
-#include "util.h"
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
if (!fgets(t, sizeof(t), f)) {
if (ferror(f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
t[0] = 0;
}
fflush(f);
if (ferror(f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
*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);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
#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"
if (parents)
mkdir_parents(path, 0755);
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+ fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
+ (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
if (fd < 0)
return -errno;
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
break;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <unistd.h>
-#include <limits.h>
#include "time-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <glob.h>
#include "glob-util.h"
-#include "string-util.h"
+#include "macro.h"
#include "strv.h"
-#include "util.h"
int glob_exists(const char *path) {
_cleanup_globfree_ glob_t g = {};
if (k == GLOB_NOSPACE)
return -ENOMEM;
if (k != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return !strv_isempty(g.gl_pathv);
}
if (k == GLOB_NOSPACE)
return -ENOMEM;
if (k != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
if (strv_isempty(g.gl_pathv))
return -ENOENT;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
#include <string.h>
#include "macro.h"
* Copyright 2000, 2005 Red Hat, Inc.
*/
+#include <stdlib.h>
+
#include "gunicode.h"
#define unichar uint32_t
#pragma once
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
char *utf8_prev_char (const char *p);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
-#include <pthread.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include "alloc-util.h"
#include "hashmap.h"
#include "util.h"
#ifdef ENABLE_DEBUG_HASHMAP
+#include <pthread.h>
#include "list.h"
#endif
},
};
-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
-
static unsigned n_buckets(HashmapBase *h) {
return h->has_indirect ? h->indirect.n_buckets
: hashmap_type_info[h->type].n_direct_buckets;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <limits.h>
#include <stdbool.h>
+#include <stddef.h>
+#include "hash-funcs.h"
#include "macro.h"
-#include "siphash24.h"
#include "util.h"
/*
#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
-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 embedd 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
-
/* Macros for type checking */
#define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
(__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <ctype.h>
-#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
#include "alloc-util.h"
#include "hexdecoct.h"
-#include "util.h"
+#include "macro.h"
char octchar(int x) {
return '0' + (x & 7);
return -EINVAL;
}
-char *base64mem(const void *p, size_t l) {
+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 NULL;
+ 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 = 0;
- return r;
+ *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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
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);
-char *base64mem(const void *p, size_t l);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <ctype.h>
+#include <bits/local_lim.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/utsname.h>
+#include <unistd.h>
#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
+#include "macro.h"
#include "string-util.h"
-#include "util.h"
bool hostname_is_set(void) {
struct utsname u;
* 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_domain_is_valid().
+ * dns_name_is_valid().
*/
bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
unsigned n_dots = 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <arpa/inet.h>
+#include <endian.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
#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);
assert(u);
if (family == AF_INET)
- return (be32toh(u->in.s_addr) & 0xFFFF0000) == (169U << 24 | 254U << 16);
+ 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);
errno = 0;
if (!inet_ntop(family, u, x, l)) {
free(x);
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
}
*ret = x;
errno = 0;
if (inet_pton(family, s, ret) <= 0)
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <netinet/in.h>
+#include <stddef.h>
+#include <sys/socket.h>
#include "macro.h"
#include "util.h"
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <limits.h>
#include <poll.h>
+#include <stdio.h>
+#include <time.h>
#include <unistd.h>
#include "io-util.h"
+#include "time-util.h"
int flush_fd(int fd) {
struct pollfd pollfd = {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
#include <sys/types.h>
#include <sys/uio.h>
+#include "macro.h"
#include "time-util.h"
int flush_fd(int fd);
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);
+
+}
/* This is minimal version of Linux' linux/ioprio.h header file, which
* is licensed GPL2 */
-#include <unistd.h>
#include <sys/syscall.h>
+#include <unistd.h>
/*
* Gives us 8 prio classes with 13-bits of data for each class
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include "alloc-util.h"
else if (*c == 't')
ch = '\t';
else if (*c == 'u') {
- uint16_t x;
+ char16_t x;
int r;
r = unhex_ucs2(c + 1, &x);
return -ENOMEM;
if (!utf16_is_surrogate(x))
- n += utf8_encode_unichar(s + n, x);
+ n += utf8_encode_unichar(s + n, (char32_t) x);
else if (utf16_is_trailing_surrogate(x))
return -EINVAL;
else {
- uint16_t y;
+ char16_t y;
if (c[0] != '\\' || c[1] != 'u')
return -EINVAL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "macro.h"
#include "util.h"
enum {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
#include "label.h"
+#include "macro.h"
#include "selinux-util.h"
#include "smack-util.h"
-#include "util.h"
int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r, q;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <langinfo.h>
+#include <libintl.h>
#include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include "dirent-util.h"
#include "fd-util.h"
+#include "hashmap.h"
#include "locale-util.h"
#include "path-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
-#include "util.h"
static int add_locales_from_archive(Set *locales) {
/* Stolen from glibc... */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
+#include <fcntl.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
+#include <sys/stat.h>
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "lockfile-util.h"
+#include "macro.h"
#include "path-util.h"
-#include "util.h"
int make_lock_file(const char *p, int operation, LockFile *ret) {
_cleanup_close_ int fd = -1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
+
#include "macro.h"
#include "missing.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
-#include <printf.h>
+#include <inttypes.h>
+#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/signalfd.h>
#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
#include <sys/un.h>
+#include <time.h>
#include <unistd.h>
#include "sd-messages.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)
highlight = LOG_PRI(level) <= LOG_ERR && show_color;
if (show_location) {
- snprintf(location, sizeof(location), "(%s:%i) ", file, line);
+ xsprintf(location, "(%s:%i) ", file, line);
IOVEC_SET_STRING(iovec[n++], location);
}
return;
DISABLE_WARNING_FORMAT_NONLITERAL;
- snprintf(buffer, sizeof(buffer), format, text, file, line, func);
+ xsprintf(buffer, format, text, file, line, func);
REENABLE_WARNING;
log_abort_msg = buffer;
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,
char header[LINE_MAX];
struct iovec iovec[17] = {};
unsigned n = 0, i;
+ int r;
struct msghdr mh = {
.msg_iov = iovec,
};
- static const char nl = '\n';
bool fallback = false;
/* If the journal is available do structured logging */
IOVEC_SET_STRING(iovec[n++], header);
va_start(ap, format);
- while (format && n + 1 < ELEMENTSOF(iovec)) {
- va_list aq;
- char *m;
-
- /* 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);
- if (vasprintf(&m, format, aq) < 0) {
- va_end(aq);
- fallback = true;
- goto finish;
- }
- va_end(aq);
-
- /* Now, jump enough ahead, so that we point to
- * the next format string */
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iovec[n++], m);
-
- iovec[n].iov_base = (char*) &nl;
- iovec[n].iov_len = 1;
- n++;
-
- format = va_arg(ap, char *);
+ 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);
}
- mh.msg_iovlen = n;
-
- (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
-
- finish:
va_end(ap);
for (i = 1; i < n; i += 2)
free(iovec[i].iov_base);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
#include <stdlib.h>
#include <sys/signalfd.h>
+#include <sys/socket.h>
#include <syslog.h>
#include "sd-id128.h"
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,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "def.h"
+#include <string.h>
+
#include "login-util.h"
#include "string-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
-#define IN_SET(x, y, ...) \
- ({ \
- static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \
- const typeof(y) _x = (x); \
- unsigned _i; \
- bool _found = false; \
- for (_i = 0; _i < ELEMENTSOF(_array); _i++) \
- if (_array[_i] == _x) { \
- _found = true; \
- break; \
- } \
- _found; \
+#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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
#ifdef HAVE_LINUX_MEMFD_H
#include <linux/memfd.h>
#endif
#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"
-#include "util.h"
int memfd_new(const char *name) {
_cleanup_free_ char *g = NULL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
int memfd_new(const char *name);
int memfd_new_and_map(const char *name, size_t sz, void **p);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdint.h>
+#include <stdlib.h>
+
#include "macro.h"
#include "mempool.h"
#include "util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/syscall.h>
+#include <uchar.h>
#include <unistd.h>
#ifdef HAVE_AUDIT
#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);
#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 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <stdio.h>
+#include <sys/types.h>
#include <unistd.h>
#include "label.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <stdbool.h>
#include <string.h>
+#include <sys/stat.h>
#include "fs-util.h"
+#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
#include "stat-util.h"
#include "user-util.h"
-#include "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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
+#include <sys/stat.h>
#include <sys/statvfs.h>
+#include <unistd.h>
#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"
-#include "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)];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <fcntl.h>
#include <mntent.h>
#include <stdbool.h>
+#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include "macro.h"
#include "missing.h"
int fd_is_mount_point(int fd, const char *filename, int flags);
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <grp.h>
+#include <netdb.h>
+#include <nss.h>
+#include <pwd.h>
+#include <resolv.h>
+
+#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_
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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;
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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xlocale.h>
+
#include "alloc-util.h"
#include "extract-word.h"
+#include "macro.h"
#include "parse-util.h"
#include "string-util.h"
-#include "util.h"
int parse_boolean(const char *v) {
assert(v);
errno = 0;
l = strtol(s, &x, 8);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtoull(p, &e, 10);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (e == p)
return -EINVAL;
char *e2;
l2 = strtoull(e, &e2, 10);
- if (errno != 0)
+ if (errno > 0)
return -errno;
/* Ignore failure. E.g. 10.M is valid */
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtol(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtoull(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtoll(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
l = strtol(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
errno = 0;
d = strtod_l(s, &x, loc);
- if (errno != 0) {
+ if (errno > 0) {
freelocale(loc);
return -errno;
}
*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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <inttypes.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
#include <sys/types.h>
#include "macro.h"
#endif
int safe_atod(const char *s, double *ret_d);
+
+int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
-#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/statvfs.h>
+#include <sys/stat.h>
#include <unistd.h>
/* When we include libgen.h because we need dirname() we immediately
#undef basename
#include "alloc-util.h"
-#include "fd-util.h"
-#include "fileio.h"
+#include "extract-word.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
-#include "parse-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
-#include "util.h"
+#include "time-util.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
cwd = get_current_dir_name();
if (!cwd)
- return -errno;
+ return negative_errno();
c = strjoin(cwd, "/", p, NULL);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
#include <stdbool.h>
+#include <stddef.h>
#include "macro.h"
#include "time-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
* The underlying algorithm used in this implementation is a Heap.
*/
+#include <errno.h>
+#include <stdlib.h>
+
#include "alloc-util.h"
+#include "hashmap.h"
#include "prioq.h"
-#include "util.h"
struct prioq_item {
void *data;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
#include "hashmap.h"
+#include "macro.h"
typedef struct Prioq Prioq;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
#include "alloc-util.h"
#include "extract-word.h"
#include "fileio.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <ctype.h>
#include <errno.h>
+#include <limits.h>
+#include <linux/oom.h>
#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <syslog.h>
#include <unistd.h>
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
#include "alloc-util.h"
#include "escape.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"
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;
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",
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
-#include <sys/types.h>
#include <alloca.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
#include <stdio.h>
#include <string.h>
-#include <signal.h>
+#include <sys/types.h>
#include "formats-util.h"
#include "macro.h"
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);
#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
+
+void valgrind_summary_hack(void);
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <elf.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/time.h>
#include <linux/random.h>
#include <stdint.h>
+
#ifdef HAVE_SYS_AUXV_H
#include <sys/auxv.h>
#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
#include "fd-util.h"
#include "io-util.h"
#include "missing.h"
#include "random-util.h"
#include "time-util.h"
-#include "util.h"
int dev_urandom(void *p, size_t n) {
static int have_syscall = -1;
if (srand_called)
return;
- x = 0;
-
#ifdef HAVE_SYS_AUXV_H
- /* The kernel provides us with a bit of entropy in auxv, so
- * let's try to make use of that to seed the pseudo-random
- * generator. It's better than nothing... */
+ /* 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)
- x ^= *(unsigned*) auxv;
+ if (auxv) {
+ assert_cc(sizeof(x) < 16);
+ memcpy(&x, auxv, sizeof(x));
+ } else
#endif
+ x = 0;
+
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
#include <stdint.h>
int dev_urandom(void *p, size_t n);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
+#include <sys/time.h>
+
+#include "macro.h"
#include "ratelimit.h"
/* Modelled after Linux' lib/ratelimit.c by Dave Young
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
+#include "time-util.h"
#include "util.h"
typedef struct RateLimit {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "macro.h"
#include "replace-var.h"
#include "string-util.h"
-#include "util.h"
/*
* Generic infrastructure for replacing @FOO@ style variables in
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <sys/resource.h>
+
+#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 "util.h"
+#include "time-util.h"
int setrlimit_closest(int resource, const struct rlimit *rlim) {
struct rlimit highest, fixed;
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",
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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 })
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <unistd.h>
+
#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"
-#include "util.h"
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
_cleanup_closedir_ DIR *d = NULL;
errno = 0;
de = readdir(d);
if (!de) {
- if (errno != 0 && ret == 0)
+ if (errno > 0 && ret == 0)
ret = -errno;
return ret;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <malloc.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
#include <sys/un.h>
+#include <syslog.h>
#ifdef HAVE_SELINUX
#include <selinux/context.h>
#endif
#include "alloc-util.h"
+#include "log.h"
+#include "macro.h"
#include "path-util.h"
#include "selinux-util.h"
-#include "strv.h"
+#include "time-util.h"
+#include "util.h"
#ifdef HAVE_SELINUX
DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
#endif
-bool mac_selinux_use(void) {
+bool mac_selinux_have(void) {
#ifdef HAVE_SELINUX
if (cached_use < 0)
cached_use = is_selinux_enabled() > 0;
#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;
assert(exe);
assert(label);
- if (!mac_selinux_use())
+ if (!mac_selinux_have())
return -EOPNOTSUPP;
r = getcon_raw(&mycon);
assert(label);
#ifdef HAVE_SELINUX
- if (!mac_selinux_use())
+ if (!mac_selinux_have())
return -EOPNOTSUPP;
r = getcon_raw(label);
assert(exe);
assert(label);
- if (!mac_selinux_use())
+ if (!mac_selinux_have())
return -EOPNOTSUPP;
r = getcon_raw(&mycon);
if (!label)
return NULL;
- if (!mac_selinux_use())
+ if (!mac_selinux_have())
return NULL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <signal.h>
+#include <stddef.h>
#include <sys/mman.h>
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "macro.h"
#include "parse-util.h"
#include "signal-util.h"
+#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
-#include "util.h"
int reset_all_signal_handlers(void) {
static const struct sigaction sa = {
return name;
if (signo >= SIGRTMIN && signo <= SIGRTMAX)
- snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
+ xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
else
- snprintf(buf, sizeof(buf), "%d", signo);
+ xsprintf(buf, "%d", signo);
return buf;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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; \
+ })
coding style)
*/
+#include "macro.h"
#include "siphash24.h"
-#include "sparse-endian.h"
#include "unaligned.h"
-#include "util.h"
static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
assert(b < 64);
#pragma once
#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
#include <sys/types.h>
struct siphash {
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]);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
#include <sys/xattr.h>
+#include <unistd.h>
#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 "util.h"
#include "xattr-util.h"
#ifdef HAVE_SMACK
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <sys/types.h>
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <netinet/in.h>
+#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <unistd.h>
#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"
-#include "util.h"
int socket_address_listen(
const SocketAddress *a,
return r;
}
-int make_socket_fd(int log_level, const char* address, int flags) {
+int make_socket_fd(int log_level, const char* address, int type, int flags) {
SocketAddress a;
int fd, r;
if (r < 0)
return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address);
- fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <arpa/inet.h>
#include <errno.h>
+#include <limits.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <unistd.h>
#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"
}
bool socket_ipv6_is_supported(void) {
- _cleanup_free_ char *l = NULL;
-
- if (access("/sys/module/ipv6", F_OK) != 0)
+ if (access("/proc/net/sockstat6", F_OK) != 0)
return false;
- /* If we can't check "disable" parameter, assume enabled */
- if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
- return true;
-
- /* If module was loaded with disable=1 no IPv6 available */
- return l[0] == '0';
+ return true;
}
bool socket_address_matches_fd(const SocketAddress *a, int fd) {
return 0;
}
-int getpeername_pretty(int fd, char **ret) {
+int getpeername_pretty(int fd, bool include_port, char **ret) {
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
int r;
/* For remote sockets we translate IPv6 addresses back to IPv4
* if applicable, since that's nicer. */
- return sockaddr_pretty(&sa.sa, salen, true, true, ret);
+ return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
}
int getsockname_pretty(int fd, char **ret) {
return 0;
}
-int send_one_fd(int transport_fd, int fd, int flags) {
+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),
};
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <sys/un.h>
#include <linux/netlink.h>
#include <linux/if_packet.h>
mode_t directory_mode,
mode_t socket_mode,
const char *label);
-int make_socket_fd(int log_level, const char* address, int flags);
+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);
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, 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 getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
-int send_one_fd(int transport_fd, int fd, int flags);
+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) \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <linux/magic.h>
#include <sys/statvfs.h>
#include <unistd.h>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
#include <sys/stat.h>
+#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/vfs.h>
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 use our own type we know is sufficiently
- * larger to store the possible values. */
-typedef long statfs_f_type_t;
+ * 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "strbuf.h"
-#include "util.h"
/*
* Strbuf stores given strings in a single continuous allocated memory
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
#include <stdint.h>
+#include <sys/types.h>
struct strbuf {
char *buf;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
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) { \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#include "alloc-util.h"
#include "gunicode.h"
+#include "macro.h"
#include "string-util.h"
#include "utf8.h"
#include "util.h"
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++)
- if (*p >= 'A' && *p <= 'Z')
- *p = *p - 'A' + 'a';
+ *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;
char *e;
const char *i, *j;
unsigned k, len, len2;
+ int r;
assert(s);
assert(percent <= 100);
k = 0;
for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
- int c;
+ char32_t c;
- c = utf8_encoded_to_unichar(i);
- if (c < 0)
+ r = utf8_encoded_to_unichar(i, &c);
+ if (r < 0)
return NULL;
k += unichar_iswide(c) ? 2 : 1;
}
x ++;
for (j = s + old_length; k < new_length && j > i; ) {
- int c;
+ char32_t c;
j = utf8_prev_char(j);
- c = utf8_encoded_to_unichar(j);
- if (c < 0)
+ r = utf8_encoded_to_unichar(j, &c);
+ if (r < 0)
return NULL;
k += unichar_iswide(c) ? 2 : 1;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
#include <stdbool.h>
+#include <stddef.h>
#include <string.h>
#include "macro.h"
char *delete_chars(char *s, const char *bad);
char *truncate_nl(char *s);
-char *ascii_strlower(char *path);
+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_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <fnmatch.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "escape.h"
+#include "extract-word.h"
+#include "fileio.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <fnmatch.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stddef.h>
+#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_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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
* Returns the * remaining size, and 0 if the string was truncated.
*/
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
+#include <stddef.h>
+
#include "macro.h"
size_t strpcpy(char **dest, size_t size, const char *src);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <string.h>
#include <syslog.h>
-#include "assert.h"
#include "hexdecoct.h"
+#include "macro.h"
#include "string-table.h"
#include "syslog-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
+#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/socket.h>
+#include <sys/sysmacros.h>
+#include <sys/time.h>
#include <linux/kd.h>
#include <linux/tiocl.h>
#include <linux/vt.h>
#include <poll.h>
#include <signal.h>
#include <sys/ioctl.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
-#include <time.h>
#include <unistd.h>
#include "alloc-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "io-util.h"
+#include "log.h"
+#include "macro.h"
#include "parse-util.h"
-#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
errno = 0;
if (!fgets(line, sizeof(line), f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
truncate_nl(line);
errno = 0;
if (!fgets(line, sizeof(line), stdin))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
if (!endswith(line, "\n"))
putchar('\n');
}
const char *default_term_for_tty(const char *tty) {
- assert(tty);
-
- return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
+ return tty && tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
}
int fd_columns(int fd) {
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;
+}
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
+#include <sys/types.h>
#include "macro.h"
#include "time-util.h"
void columns_lines_cache_reset(int _unused_ signum);
bool on_tty(void);
+bool colors_enabled(void);
static inline const char *ansi_underline(void) {
- return on_tty() ? ANSI_UNDERLINE : "";
+ return colors_enabled() ? ANSI_UNDERLINE : "";
}
static inline const char *ansi_highlight(void) {
- return on_tty() ? ANSI_HIGHLIGHT : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT : "";
}
static inline const char *ansi_highlight_underline(void) {
- return on_tty() ? ANSI_HIGHLIGHT_UNDERLINE : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : "";
}
static inline const char *ansi_highlight_red(void) {
- return on_tty() ? ANSI_HIGHLIGHT_RED : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_RED : "";
}
static inline const char *ansi_highlight_green(void) {
- return on_tty() ? ANSI_HIGHLIGHT_GREEN : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : "";
}
static inline const char *ansi_highlight_yellow(void) {
- return on_tty() ? ANSI_HIGHLIGHT_YELLOW : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : "";
}
static inline const char *ansi_highlight_blue(void) {
- return on_tty() ? ANSI_HIGHLIGHT_BLUE : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : "";
}
static inline const char *ansi_normal(void) {
- return on_tty() ? ANSI_NORMAL : "";
+ return colors_enabled() ? ANSI_NORMAL : "";
}
int get_ctty_devnr(pid_t pid, dev_t *d);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
#include <sys/timerfd.h>
#include <sys/timex.h>
+#include <sys/types.h>
+#include <unistd.h>
#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"
-#include "util.h"
+
+static nsec_t timespec_load_nsec(const struct timespec *ts);
usec_t now(clockid_t clock_id) {
struct timespec ts;
ts->realtime = u;
delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- if ((int64_t) ts->monotonic > delta)
- ts->monotonic -= delta;
- else
- ts->monotonic = 0;
+ ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
return ts;
}
ts->monotonic = u;
delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u;
-
- ts->realtime = now(CLOCK_REALTIME);
- if ((int64_t) ts->realtime > delta)
- ts->realtime -= delta;
- else
- ts->realtime = 0;
+ ts->realtime = usec_sub(now(CLOCK_REALTIME), delta);
return ts;
}
ts->realtime = ts->monotonic = USEC_INFINITY;
return ts;
}
- ts->realtime = now(CLOCK_REALTIME);
- ts->monotonic = now(CLOCK_MONOTONIC);
+ dual_timestamp_get(ts);
delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
-
- if ((int64_t) ts->realtime > delta)
- ts->realtime -= delta;
- else
- ts->realtime = 0;
-
- if ((int64_t) ts->monotonic > delta)
- ts->monotonic -= delta;
- else
- ts->monotonic = 0;
+ 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);
(usec_t) ts->tv_nsec / NSEC_PER_USEC;
}
-nsec_t timespec_load_nsec(const struct timespec *ts) {
+static nsec_t timespec_load_nsec(const struct timespec *ts) {
assert(ts);
if (ts->tv_sec == (time_t) -1 &&
return tv;
}
-static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc) {
+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);
sec = (time_t) (t / USEC_PER_SEC);
localtime_or_gmtime_r(&sec, &tm, utc);
- if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm) <= 0)
+ 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);
+ 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);
-}
-
-static char *format_timestamp_internal_us(char *buf, size_t l, usec_t t, bool utc) {
- struct tm tm;
- time_t sec;
-
- 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 (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0)
- return NULL;
- 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;
+ 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_us(buf, l, t, false);
+ 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_us(buf, l, t, true);
+ return format_timestamp_internal(buf, l, t, true, true);
}
char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
parse_usec:
{
- char *end;
- unsigned long long val;
- size_t l;
+ unsigned add;
k++;
- if (*k < '0' || *k > '9')
+ r = parse_fractional_part_u(&k, 6, &add);
+ if (r < 0)
return -EINVAL;
- /* base 10 instead of base 0, .09 is not base 8 */
- errno = 0;
- val = strtoull(k, &end, 10);
- if (*end || errno)
+ if (*k)
return -EINVAL;
- l = end-k;
-
- /* val has l digits, make them 6 */
- for (; l < 6; l++)
- val *= 10;
- for (; l > 6; l--)
- val /= 10;
+ x_usec = add;
- x_usec = val;
}
from_tm:
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <time.h>
#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
#define FORMAT_TIMESPAN_MAX 64
-#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
+#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 timeval_load(const struct timeval *tv) _pure_;
struct timeval *timeval_store(struct timeval *tv, usec_t u);
-nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
-
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);
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "bus-label.h"
-#include "def.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"
-#include "util.h"
+/* Characters valid in a unit name. */
#define VALID_CHARS \
- DIGITS LETTERS \
+ 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;
/* We'll only escape the obvious characters here, to play
* safe. */
- valid_chars = allow_globs == UNIT_NAME_GLOB ? "@" VALID_CHARS "[]!-*?" : "@" VALID_CHARS;
+ valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
for (; *f; f++) {
if (*f == '/')
if (!unit_suffix_is_valid(suffix))
return -EINVAL;
- if (unit_name_is_valid(name, UNIT_NAME_ANY)) {
- /* No mangling necessary... */
- s = strdup(name);
- if (!s)
- return -ENOMEM;
+ /* Already a fully valid unit name? If so, no mangling is necessary... */
+ if (unit_name_is_valid(name, UNIT_NAME_ANY))
+ goto good;
- *ret = s;
- return 0;
- }
+ /* 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);
t = do_escape_mangle(name, allow_globs, s);
*t = 0;
- if (unit_name_to_type(s) < 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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
+#include <errno.h>
+#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
#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"
-#include "util.h"
bool uid_is_valid(uid_t uid) {
if (!uid_is_valid(uid))
return -ENXIO; /* we return ENXIO instead of EINVAL
* here, to make it easy to distuingish
- * invalid numeric uids invalid
+ * invalid numeric uids from invalid
* strings. */
if (ret)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
bool uid_is_valid(uid_t uid);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
*/
#include <errno.h>
-#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "hexdecoct.h"
+#include "macro.h"
#include "utf8.h"
-#include "util.h"
-bool unichar_is_valid(uint32_t ch) {
+bool unichar_is_valid(char32_t ch) {
if (ch >= 0x110000) /* End of unicode space */
return false;
return true;
}
-static bool unichar_is_control(uint32_t ch) {
+static bool unichar_is_control(char32_t ch) {
/*
0 to ' '-1 is the C0 range.
}
/* decode one unicode char */
-int utf8_encoded_to_unichar(const char *str) {
- int unichar, len, i;
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
+ char32_t unichar;
+ int len, i;
assert(str);
switch (len) {
case 1:
- return (int)str[0];
+ *ret_unichar = (char32_t)str[0];
+ return 0;
case 2:
unichar = str[0] & 0x1f;
break;
case 3:
- unichar = (int)str[0] & 0x0f;
+ unichar = (char32_t)str[0] & 0x0f;
break;
case 4:
- unichar = (int)str[0] & 0x07;
+ unichar = (char32_t)str[0] & 0x07;
break;
case 5:
- unichar = (int)str[0] & 0x03;
+ unichar = (char32_t)str[0] & 0x03;
break;
case 6:
- unichar = (int)str[0] & 0x01;
+ unichar = (char32_t)str[0] & 0x01;
break;
default:
return -EINVAL;
}
for (i = 1; i < len; i++) {
- if (((int)str[i] & 0xc0) != 0x80)
+ if (((char32_t)str[i] & 0xc0) != 0x80)
return -EINVAL;
unichar <<= 6;
- unichar |= (int)str[i] & 0x3f;
+ unichar |= (char32_t)str[i] & 0x3f;
}
- return unichar;
+ *ret_unichar = unichar;
+
+ return 0;
}
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
assert(str);
for (p = str; length;) {
- int encoded_len, val;
+ 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;
- val = utf8_encoded_to_unichar(p);
- if (val < 0 ||
+ r = utf8_encoded_to_unichar(p, &val);
+ if (r < 0 ||
unichar_is_control(val) ||
(!newline && val == '\n'))
return false;
* Returns: The length in bytes that the UTF-8 representation does or would
* occupy.
*/
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
+size_t utf8_encode_unichar(char *out_utf8, char32_t g) {
if (g < (1 << 7)) {
if (out_utf8)
t = r;
while (f < (const uint8_t*) s + length) {
- uint16_t w1, w2;
+ char16_t w1, w2;
/* see RFC 2781 section 2.2 */
}
/* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(int unichar) {
+static int utf8_unichar_to_encoded_len(char32_t unichar) {
if (unichar < 0x80)
return 1;
/* validate one encoded unicode char and return its length */
int utf8_encoded_valid_unichar(const char *str) {
- int len, unichar, i;
+ int len, i, r;
+ char32_t unichar;
assert(str);
if ((str[i] & 0x80) != 0x80)
return -EINVAL;
- unichar = utf8_encoded_to_unichar(str);
+ 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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <uchar.h>
#include "macro.h"
+#include "missing.h"
#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
-bool unichar_is_valid(uint32_t c);
+bool unichar_is_valid(char32_t c);
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
char *utf8_escape_invalid(const char *s);
char *utf8_escape_non_printable(const char *str);
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g);
+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);
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
-static inline bool utf16_is_surrogate(uint16_t c) {
+static inline bool utf16_is_surrogate(char16_t c) {
return (0xd800 <= c && c <= 0xdfff);
}
-static inline bool utf16_is_trailing_surrogate(uint16_t c) {
+static inline bool utf16_is_trailing_surrogate(char16_t c) {
return (0xdc00 <= c && c <= 0xdfff);
}
-static inline uint32_t utf16_surrogate_pair_to_unichar(uint16_t lead, uint16_t trail) {
+static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <ctype.h>
+#include <alloca.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <grp.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <limits.h>
-#include <linux/magic.h>
-#include <linux/oom.h>
-#include <linux/sched.h>
-#include <locale.h>
-#include <poll.h>
-#include <pwd.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/personality.h>
#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h>
+#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
-#include <sys/utsname.h>
-#include <sys/vfs.h>
-#include <sys/wait.h>
-#include <syslog.h>
#include <unistd.h>
-/* 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 <libgen.h>
-#undef basename
-
-#ifdef HAVE_SYS_AUXV_H
-#include <sys/auxv.h>
-#endif
-
-/* We include linux/fs.h as last of the system headers, as it
- * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
-#include <linux/fs.h>
-
#include "alloc-util.h"
#include "build.h"
#include "def.h"
-#include "device-nodes.h"
#include "dirent-util.h"
-#include "env-util.h"
-#include "escape.h"
-#include "exit-status.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
-#include "gunicode.h"
#include "hashmap.h"
-#include "hexdecoct.h"
#include "hostname-util.h"
-#include "ioprio.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 "random-util.h"
+#include "set.h"
#include "signal-util.h"
-#include "sparse-endian.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 "user-util.h"
-#include "utf8.h"
#include "util.h"
-#include "virt.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <alloca.h>
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/stat.h>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "log.h"
+#include "macro.h"
#include "string-util.h"
-#include "util.h"
#include "verbs.h"
+#include "virt.h"
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
const Verb *verb;
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 {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#define VERB_ANY ((unsigned) -1)
-#define VERB_DEFAULT 1
+#define VERB_DEFAULT 1U
+#define VERB_NOCHROOT 2U
typedef struct {
const char *verb;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.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 "util.h"
#include "virt.h"
static int detect_vm_cpuid(void) {
if (cached_found >= 0)
return cached_found;
- r = detect_vm_cpuid();
+ /* 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_dmi();
+ r = detect_vm_cpuid();
if (r < 0)
return r;
if (r != VIRTUALIZATION_NONE)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
#include <sys/xattr.h>
#include "alloc-util.h"
#include "fd-util.h"
+#include "macro.h"
#include "sparse-endian.h"
#include "stdio-util.h"
-#include "util.h"
+#include "time-util.h"
#include "xattr-util.h"
int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
#include <sys/types.h>
#include "time-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stddef.h>
#include <string.h>
+#include "macro.h"
#include "string-util.h"
-#include "util.h"
#include "xml.h"
enum {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "blkid-util.h"
+#include "dirent-util.h"
#include "efivars.h"
#include "fd-util.h"
#include "fileio.h"
return log_error_errno(errno, "Failed to read \"%s\": %m", p);
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
_cleanup_close_ int fd = -1;
_cleanup_free_ char *v = NULL;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
if (r < 0)
return r;
if (r > 0)
- printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v);
+ printf(" File: %s/%s/%s (%s)\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name, v);
else
- printf(" File: └─/%s/%s\n", path, de->d_name);
+ printf(" File: %s/%s/%s\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name);
c++;
}
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\n", path);
+ printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), path);
printf("\n");
return 0;
if (!d)
return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
int k;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
_cleanup_close_ int fd = -1;
_cleanup_free_ char *v = NULL;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+
#include "list.h"
#define MAXCPUS 16
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <dirent.h>
+
#include "bootchart.h"
double gettime_ns(void);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "fileio.h"
#include "list.h"
#include "macro.h"
+#include "stdio-util.h"
#include "store.h"
#include "svg.h"
#include "utf8.h"
strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
rootbdev[3] = '\0';
- snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
+ xsprintf(filename, "/sys/block/%s/device/model", rootbdev);
r = read_one_line_file(filename, &model);
if (r < 0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <pthread.h>
-#include "list.h"
#include "hashmap.h"
+#include "list.h"
typedef enum PolicyItemType {
_POLICY_ITEM_TYPE_UNSET = 0,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
int r;
assert(bus);
}
static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
ProxyActivation *activation = userdata;
/*
return synthetic_reply_method_return(m, NULL);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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"));
return synthetic_driver_send(m->bus, reply);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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"));
return synthetic_driver_send(m->bus, reply);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_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"));
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_bus_creds_unref_ sd_bus_creds *creds = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_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"));
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
const char *name;
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_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"));
};
struct kdbus_info *name_list, *name;
_cleanup_strv_free_ char **owners = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *arg0;
int err = 0;
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_bus_message_unref_ sd_bus_message *msg = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
ProxyActivation *activation;
const char *name;
uint64_t cookie;
return 1;
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
- _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+ _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_return(m, NULL);
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "bus-xml-policy.h"
#include "proxy.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "util.h"
static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
- _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
int r;
r = sd_bus_new(&b);
(void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
- _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
+ _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
}
if (to->is_kernel) {
- _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
+ _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;
}
static int process_hello(Proxy *p, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
bool is_hello;
int r;
}
static int proxy_process_destination_to_local(Proxy *p) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
bool matched, matched_synthetic;
int r;
}
static int proxy_process_local_to_destination(Proxy *p) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(p);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int rename_service(sd_bus *a, sd_bus *b) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_free_ char *p = NULL, *name = NULL;
const char *comm;
char **cmdline;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
}
int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
va_list ap;
va_start(ap, format);
}
int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
assert(call);
}
int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
va_list ap;
assert(call);
}
int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
}
int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(call);
}
int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
const char *name, *old_owner, *new_owner;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int get_cgroup_root(char **ret) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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)
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "log.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
if (argc != 2) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
}
if (arg_cpu_type == CPU_PERCENT)
- snprintf(buffer, sizeof(buffer), "%6s", "%CPU");
+ xsprintf(buffer, "%6s", "%CPU");
else
- snprintf(buffer, sizeof(buffer), "%*s", maxtcpu, "CPU Time");
+ xsprintf(buffer, "%*s", maxtcpu, "CPU Time");
rows = lines();
if (rows <= 10)
}
static int get_cgroup_root(char **ret) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static void automount_enter_runnning(Automount *a) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
struct stat st;
int r;
if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
log_unit_info(UNIT(a), "Automount point already active?");
else {
- r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
+ 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;
static int automount_start(Unit *u) {
Automount *a = AUTOMOUNT(u);
+ Unit *trigger;
assert(a);
assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
return -EEXIST;
}
- if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+ 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);
}
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
break;
}
- r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct BusEndpoint BusEndpoint;
typedef struct BusEndpointPolicy BusEndpointPolicy;
-#include "hashmap.h"
#include "bus-policy.h"
+#include "hashmap.h"
struct BusEndpointPolicy {
char *name;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "kdbus.h"
#include "list.h"
#include "macro.h"
-#include "kdbus.h"
typedef struct BusNamePolicy BusNamePolicy;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
n->timer_event_source = sd_event_source_unref(n->timer_event_source);
}
-static int busname_arm_timer(BusName *n) {
+static int busname_arm_timer(BusName *n, usec_t usec) {
int r;
assert(n);
- if (n->timeout_usec <= 0) {
- n->timer_event_source = sd_event_source_unref(n->timer_event_source);
- return 0;
- }
-
if (n->timer_event_source) {
- r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
+ 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,
- now(CLOCK_MONOTONIC) + n->timeout_usec, 0,
+ usec, 0,
busname_dispatch_timer, n);
if (r < 0)
return r;
if (r < 0)
return r;
- r = busname_arm_timer(n);
+ r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec));
if (r < 0)
return r;
}
pid_t pid;
int r;
- r = busname_arm_timer(n);
+ r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
if (r < 0)
goto fail;
}
if (r > 0) {
- r = busname_arm_timer(n);
+ 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;
}
static void busname_enter_running(BusName *n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool pending = false;
Unit *other;
Iterator i;
static void busname_trigger_notify(Unit *u, Unit *other) {
BusName *n = BUSNAME(u);
- Service *s;
assert(n);
assert(other);
if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
return;
- if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+ if (other->start_limit_hit) {
+ busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT);
return;
+ }
- s = SERVICE(other);
+ if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+ return;
- if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
- busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
- else if (IN_SET(s->state,
- SERVICE_DEAD, SERVICE_FAILED,
- SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
- SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
- SERVICE_AUTO_RESTART))
+ 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, uint64_t *timeout) {
+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, timeout);
+ 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;
}
[BUSNAME_FAILURE_EXIT_CODE] = "exit-code",
[BUSNAME_FAILURE_SIGNAL] = "signal",
[BUSNAME_FAILURE_CORE_DUMP] = "core-dump",
- [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
+ [BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
BUSNAME_FAILURE_EXIT_CODE,
BUSNAME_FAILURE_SIGNAL,
BUSNAME_FAILURE_CORE_DUMP,
- BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT,
+ BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT,
_BUSNAME_RESULT_MAX,
_BUSNAME_RESULT_INVALID = -1
} BusNameResult;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
c->tasks_max = (uint64_t) -1;
-
- c->netclass_type = CGROUP_NETCLASS_TYPE_NONE;
}
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
return -errno;
}
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) {
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
bool is_root;
int r;
log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set pids.max on %s: %m", path);
}
-
- if (mask & CGROUP_MASK_NET_CLS) {
- char buf[DECIMAL_STR_MAX(uint32_t)];
-
- sprintf(buf, "%" PRIu32, netclass);
-
- r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
- if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
- "Failed to set net_cls.classid on %s: %m", path);
- }
}
CGroupMask cgroup_context_get_mask(CGroupContext *c) {
c->tasks_max != (uint64_t) -1)
mask |= CGROUP_MASK_PIDS;
- if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE)
- mask |= CGROUP_MASK_NET_CLS;
-
return mask;
}
return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
}
-static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) {
-
- uint32_t start, i;
- Manager *m;
-
- assert(u);
-
- m = u->manager;
-
- i = start = m->cgroup_netclass_registry_last;
-
- do {
- i++;
-
- if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) {
- m->cgroup_netclass_registry_last = i;
- *ret = i;
- return 0;
- }
-
- if (i == UINT32_MAX)
- i = CGROUP_NETCLASS_FIXED_MAX;
-
- } while (i != start);
-
- return -ENOBUFS;
-}
-
-int unit_add_to_netclass_cgroup(Unit *u) {
-
- CGroupContext *cc;
- Unit *first;
- void *key;
- int r;
-
- assert(u);
-
- cc = unit_get_cgroup_context(u);
- if (!cc)
- return 0;
-
- switch (cc->netclass_type) {
- case CGROUP_NETCLASS_TYPE_NONE:
- return 0;
-
- case CGROUP_NETCLASS_TYPE_FIXED:
- u->cgroup_netclass_id = cc->netclass_id;
- break;
-
- case CGROUP_NETCLASS_TYPE_AUTO:
- /* Allocate a new ID in case it was requested and not done yet */
- if (u->cgroup_netclass_id == 0) {
- r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id);
- if (r < 0)
- return r;
-
- log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id);
- }
-
- break;
- }
-
- r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops);
- if (r < 0)
- return r;
-
- key = UINT32_TO_PTR(u->cgroup_netclass_id);
- first = hashmap_get(u->manager->cgroup_netclass_registry, key);
-
- if (first) {
- LIST_PREPEND(cgroup_netclass, first, u);
- return hashmap_replace(u->manager->cgroup_netclass_registry, key, u);
- }
-
- return hashmap_put(u->manager->cgroup_netclass_registry, key, u);
-}
-
-int unit_remove_from_netclass_cgroup(Unit *u) {
-
- Unit *head;
- void *key;
-
- assert(u);
-
- key = UINT32_TO_PTR(u->cgroup_netclass_id);
-
- LIST_FIND_HEAD(cgroup_netclass, u, head);
- LIST_REMOVE(cgroup_netclass, head, u);
-
- if (head)
- return hashmap_replace(u->manager->cgroup_netclass_registry, key, head);
-
- hashmap_remove(u->manager->cgroup_netclass_registry, key);
-
- return 0;
-}
-
/* Check if necessary controllers and attributes for a unit are in place.
*
* If so, do nothing.
return r;
/* Finally, apply the necessary attributes. */
- cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state);
+ cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state);
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "list.h"
#include "time-util.h"
-/* Maximum value for fixed (manual) net class ID assignment,
- * and also the value at which the range of automatic assignments starts
- */
-#define CGROUP_NETCLASS_FIXED_MAX UINT32_C(65535)
-
typedef struct CGroupContext CGroupContext;
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
_CGROUP_DEVICE_POLICY_INVALID = -1
} CGroupDevicePolicy;
-typedef enum CGroupNetClassType {
- /* Default - do not assign a net class */
- CGROUP_NETCLASS_TYPE_NONE,
-
- /* Automatically assign a net class */
- CGROUP_NETCLASS_TYPE_AUTO,
-
- /* Assign the net class that was provided by the user */
- CGROUP_NETCLASS_TYPE_FIXED,
-} CGroupNetClassType;
-
struct CGroupDeviceAllow {
LIST_FIELDS(CGroupDeviceAllow, device_allow);
char *path;
CGroupDevicePolicy device_policy;
LIST_HEAD(CGroupDeviceAllow, device_allow);
- CGroupNetClassType netclass_type;
- uint32_t netclass_id;
-
uint64_t tasks_max;
bool delegate;
};
-#include "unit.h"
#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, uint32_t netclass_id, ManagerState state);
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state);
CGroupMask cgroup_context_get_mask(CGroupContext *c);
int unit_attach_pids_to_cgroup(Unit *u);
-int unit_add_to_netclass_cgroup(Unit *u);
-int unit_remove_from_netclass_cgroup(Unit *u);
-
int manager_setup_cgroup(Manager *m);
void manager_shutdown_cgroup(Manager *m, bool delete);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
else {
errno = 0;
n = getpriority(PRIO_PROCESS, 0);
- if (errno != 0)
+ if (errno > 0)
n = 0;
}
assert(reply);
assert(c);
- /* We store this negated internally, to match the kernel, but
- * we expose it normalized. */
- return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
+ 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_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("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),
UnitSetPropertiesMode mode,
sd_bus_error *error) {
- int r;
+ const char *soft = NULL;
+ int r, ri;
assert(u);
assert(c);
dirs = &c->read_write_dirs;
else if (streq(name, "ReadOnlyDirectories"))
dirs = &c->read_only_dirs;
- else if (streq(name, "InaccessibleDirectories"))
+ else /* "InaccessibleDirectories" */
dirs = &c->inaccessible_dirs;
if (strv_length(l) == 0) {
return 1;
- } else if (rlimit_from_string(name) >= 0) {
+ }
+
+ 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;
}
if (mode != UNIT_CHECK) {
- int z;
-
- z = rlimit_from_string(name);
+ _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[z]) {
- c->rlimit[z] = new(struct rlimit, 1);
- if (!c->rlimit[z])
+ if (c->rlimit[ri])
+ *c->rlimit[ri] = nl;
+ else {
+ c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
+ if (!c->rlimit[ri])
return -ENOMEM;
}
- c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
-
- if (x == RLIM_INFINITY)
- unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
- else
- unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, f);
}
return 1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
};
static int send_new_signal(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Job *j = userdata;
int r;
}
static int send_removed_signal(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Job *j = userdata;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-bus.h"
-#include "unit.h"
#include "kill.h"
+#include "unit.h"
extern const sd_bus_vtable bus_kill_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
if (r < 0)
return r;
- return log_set_max_level_from_string(t);
+ 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(
return r;
if (isempty(name)) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
if (pid == 0) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
if (isempty(name)) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
- 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);
+ 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 list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
const char *k;
Iterator i;
}
static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Iterator i;
Job *j;
}
static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
UnitFileList *item;
Hashmap *h;
}
static int send_unit_files_changed(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
int r;
assert(bus);
UnitFileChange *changes,
unsigned n_changes) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
unsigned i;
int r;
if (r < 0)
goto fail;
+ unit_file_changes_free(changes, n_changes);
return sd_bus_send(NULL, reply, NULL);
fail:
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)
+ 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);
}
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),
};
static int send_finished(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
usec_t *times = userdata;
int r;
}
static int send_reloading(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
int r;
assert(bus);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int bus_scope_send_request_stop(Scope *s) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_scope_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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),
- SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
+ /* 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),
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,
asynchronous_close(s->stderr_fd);
s->stderr_fd = copy;
}
+
+ s->exec_context.stdio_as_fds = true;
}
return 1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_service_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_slice_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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),
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_socket_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_swap_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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),
return 1;
- } else if (streq(name, "AccuracySec")) {
-
+ } 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) {
- char time[FORMAT_TIMESPAN_MAX];
-
t->accuracy_usec = u;
- unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_timer_vtable[];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
void *userdata,
sd_bus_error *error) {
- _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
Unit *u = userdata;
assert(bus);
assert(u);
assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
- r = mac_selinux_unit_access_check(u, message, job_type == JOB_STOP ? "stop" : "start", error);
+ r = mac_selinux_unit_access_check(
+ u, message,
+ job_type_to_access_method(job_type),
+ error);
if (r < 0)
return r;
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),
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("NetClass", "u", NULL, offsetof(Unit, cgroup_netclass_id), 0),
+ 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),
};
static int send_new_signal(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Unit *u = userdata;
int r;
}
static int send_removed_signal(sd_bus *bus, void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Unit *u = userdata;
int r;
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_RELOAD;
+ type = JOB_TRY_RELOAD;
}
- r = mac_selinux_unit_access_check(
- u, message,
- (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
- type == JOB_STOP ? "stop" : "reload", error);
- if (r < 0)
- return r;
if (type == JOB_STOP &&
(u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
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);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "unit.h"
extern const sd_bus_vtable bus_unit_vtable[];
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *cgroup, *me;
Manager *m = userdata;
uid_t sender_uid;
}
static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
assert(path);
if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
pid_t pid;
}
static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int nfd = -1;
Manager *m = userdata;
sd_id128_t id;
return 0;
}
-static int bus_list_names(Manager *m, sd_bus *bus) {
+int manager_sync_bus_names(Manager *m, sd_bus *bus) {
_cleanup_strv_free_ char **names = NULL;
- char **i;
+ const char *name;
+ Iterator i;
+ Unit *u;
int r;
assert(m);
if (r < 0)
return log_error_errno(r, "Failed to get initial list of names: %m");
- /* This is a bit hacky, we say the owner of the name is the
- * name itself, because we don't want the extra traffic to
- * figure out the real owner. */
- STRV_FOREACH(i, names) {
- Unit *u;
+ /* 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);
- u = hashmap_get(m->watch_bus, *i);
- if (u)
- UNIT_VTABLE(u)->bus_name_owner_change(u, *i, NULL, *i);
+ 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;
if (r < 0)
return log_error_errno(r, "Failed to register name: %m");
- bus_list_names(m, bus);
+ 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_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
if (m->api_bus)
}
static int bus_init_system(Manager *m) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
if (m->system_bus)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(u);
assert(dev);
- property = u->manager->running_as == MANAGER_USER ? "MANAGER_USER_WANTS" : "SYSTEMD_WANTS";
+ property = u->manager->running_as == MANAGER_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
wants = udev_device_get_property_value(dev, property);
if (!wants)
return 0;
u = manager_get_unit(m, e);
- if (u &&
- sysfs &&
- DEVICE(u)->sysfs &&
- !path_equal(DEVICE(u)->sysfs, sysfs)) {
- log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
- return -EEXIST;
+ /* 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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return 0;
}
-_pure_ static const char *tty_path(const ExecContext *context) {
+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) {
+static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
+ const char *path;
+
assert(context);
- if (context->tty_vhangup)
- terminal_vhangup(tty_path(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)
- reset_terminal(tty_path(context));
+ 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 && context->tty_path)
- vt_disallocate(context->tty_path);
+ if (context->tty_vt_disallocate && path)
+ (void) vt_disallocate(path);
}
static bool is_terminal_output(ExecOutput o) {
case EXEC_INPUT_TTY_FAIL: {
int fd, r;
- fd = acquire_terminal(tty_path(context),
+ fd = acquire_terminal(exec_context_tty_path(context),
i == EXEC_INPUT_TTY_FAIL,
i == EXEC_INPUT_TTY_FORCE,
false,
} 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(tty_path(context), O_WRONLY, fileno);
+ 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;
/* We don't reset the terminal if this is just about output */
- return open_terminal_as(tty_path(context), O_WRONLY, fileno);
+ return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
case EXEC_OUTPUT_SYSLOG:
case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
/* Sets (but doesn't lookup) the uid and make sure we keep the
* capabilities while doing so. */
- if (context->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 */
- };
+ 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
/* Second step: set the capabilities. This will reduce
* the capabilities to the minimum we need. */
- d = cap_dup(context->capabilities);
- if (!d)
- return -errno;
+ if (context->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 */
+ };
- 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;
+ d = cap_dup(context->capabilities);
+ if (!d)
+ return -errno;
- if (cap_set_proc(d) < 0)
- 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 */
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
pam_handle_t *handle = NULL;
sigset_t old_ss;
- int pam_code = PAM_SUCCESS;
- int err = 0;
+ int pam_code = PAM_SUCCESS, r;
char **e = NULL;
bool close_session = false;
pid_t pam_pid = 0, parent_pid;
* daemon. We do things this way to ensure that the main PID
* of the daemon is the one we initially fork()ed. */
- err = barrier_create(&barrier);
- if (err < 0)
+ r = barrier_create(&barrier);
+ if (r < 0)
goto fail;
if (log_get_max_level() < LOG_DEBUG)
parent_pid = getpid();
pam_pid = fork();
- if (pam_pid < 0)
+ if (pam_pid < 0) {
+ r = -errno;
goto fail;
+ }
if (pam_pid == 0) {
- int sig;
- int r = EXIT_PAM;
+ int sig, ret = EXIT_PAM;
/* The child's job is to reset the PAM session on
* termination */
goto child_finish;
}
- r = 0;
+ ret = 0;
child_finish:
pam_end(handle, pam_code | flags);
- _exit(r);
+ _exit(ret);
}
barrier_set_role(&barrier, BARRIER_PARENT);
fail:
if (pam_code != PAM_SUCCESS) {
log_error("PAM failed: %s", pam_strerror(handle, pam_code));
- err = -EPERM; /* PAM errors do not map to errno */
- } else {
- err = log_error_errno(err < 0 ? err : errno, "PAM failed: %m");
- }
+ r = -EPERM; /* PAM errors do not map to errno */
+ } else
+ log_error_errno(r, "PAM failed: %m");
if (handle) {
if (close_session)
}
strv_free(e);
-
closelog();
- if (pam_pid > 1) {
- kill(pam_pid, SIGTERM);
- kill(pam_pid, SIGCONT);
- }
-
- return err;
+ return r;
}
#endif
static int build_environment(
const ExecContext *c,
+ const ExecParameters *p,
unsigned n_fds,
- char ** fd_names,
- usec_t watchdog_usec,
const char *home,
const char *username,
const char *shell,
return -ENOMEM;
our_env[n_env++] = x;
- joined = strv_join(fd_names, ":");
+ joined = strv_join(p->fd_names, ":");
if (!joined)
return -ENOMEM;
our_env[n_env++] = x;
}
- if (watchdog_usec > 0) {
+ 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, watchdog_usec) < 0)
+ if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, p->watchdog_usec) < 0)
return -ENOMEM;
our_env[n_env++] = x;
}
c->std_error == EXEC_OUTPUT_TTY ||
c->tty_path) {
- x = strdup(default_term_for_tty(tty_path(c)));
+ x = strdup(default_term_for_tty(exec_context_tty_path(c)));
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
return -errno;
}
- exec_context_tty_reset(context);
+ exec_context_tty_reset(context, params);
if (params->confirm_spawn) {
char response;
if (params->apply_permissions) {
+ int secure_bits = context->secure_bits;
+
for (i = 0; i < _RLIMIT_MAX; i++) {
if (!context->rlimit[i])
continue;
}
}
- if (context->capability_bounding_set_drop) {
- r = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
+ 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) {
*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<<SECURE_KEEP_CAPS;
+ }
}
/* PR_GET_SECUREBITS is not privileged, while
* PR_SET_SECUREBITS is. So to suppress
* potential EPERMs we'll try not to call
* PR_SET_SECUREBITS unless necessary. */
- if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
- if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
+ if (prctl(PR_GET_SECUREBITS) != secure_bits)
+ if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
*exit_status = EXIT_SECUREBITS;
return -errno;
}
#endif
}
- r = build_environment(context, n_fds, params->fd_names, params->watchdog_usec, home, username, shell, &our_env);
+ r = build_environment(context, params, n_fds, home, username, shell, &our_env);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return r;
NULL);
pid = fork();
if (pid < 0)
- return log_unit_error_errno(unit, r, "Failed to fork: %m");
+ return log_unit_error_errno(unit, errno, "Failed to fork: %m");
if (pid == 0) {
int exit_status;
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) {
continue;
strv_free(r);
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
}
count = pglob.gl_pathc;
if (count == 0) {
_cleanup_free_ char *active = NULL;
char *console;
+ if (!tty)
+ return true;
+
if (startswith(tty, "/dev/"))
tty += 5;
}
bool exec_context_may_touch_console(ExecContext *ec) {
- return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
+
+ 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(tty_path(ec));
+ tty_may_match_dev_console(exec_context_tty_path(ec));
}
static void strv_fprintf(FILE *f, char **l) {
prefix, c->oom_score_adjust);
for (i = 0; i < RLIM_NLIMITS; i++)
- if (c->rlimit[i])
- fprintf(f, "%s%s: "RLIM_FMT"\n",
+ 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;
(c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
(c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
- if (c->capability_bounding_set_drop) {
+ if (c->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_drop & ((uint64_t) 1ULL << (uint64_t) 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);
fputc('\n', f);
}
- if (c->syscall_errno != 0)
+ if (c->syscall_errno > 0)
fprintf(f,
"%sSystemCallErrorNumber: %s\n",
prefix, strna(errno_to_name(c->syscall_errno)));
if (context->utmp_id)
utmp_put_dead_process(context->utmp_id, pid, code, status);
- exec_context_tty_reset(context);
+ exec_context_tty_reset(context, NULL);
}
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct ExecRuntime ExecRuntime;
typedef struct ExecParameters ExecParameters;
-#include <sys/capability.h>
+#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
-#include <sched.h>
+#include <sys/capability.h>
-#include "list.h"
+#include "bus-endpoint.h"
#include "fdset.h"
+#include "list.h"
#include "missing.h"
#include "namespace.h"
-#include "bus-endpoint.h"
typedef enum ExecUtmpMode {
EXEC_UTMP_INIT,
nsec_t timer_slack_nsec;
+ bool stdio_as_fds;
+
char *tty_path;
bool tty_reset;
char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
unsigned long mount_flags;
- uint64_t capability_bounding_set_drop;
+ uint64_t capability_bounding_set;
+
+ uint64_t capability_ambient_set;
cap_t capabilities;
int secure_bits;
BusEndpoint *bus_endpoint;
};
-#include "cgroup.h"
#include "cgroup-util.h"
+#include "cgroup.h"
struct ExecParameters {
char **argv;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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;
DISABLE_WARNING_FORMAT_NONLITERAL;
- snprintf(buf, sizeof(buf), format, unit_description(u));
+ xsprintf(buf, format, unit_description(u));
REENABLE_WARNING;
switch (t) {
j->begin_usec = now(CLOCK_MONOTONIC);
- if (j->unit->job_timeout <= 0)
+ if (j->unit->job_timeout == USEC_INFINITY)
return 0;
r = sd_event_add_time(
j->manager->event,
&j->timer_event_source,
CLOCK_MONOTONIC,
- j->begin_usec + j->unit->job_timeout, 0,
+ usec_add(j->begin_usec, j->unit->job_timeout), 0,
job_dispatch_timer, j);
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 == 0)
+ if (j->begin_usec == 0 || j->unit->job_timeout == USEC_INFINITY)
return 0;
- if (j->timer_event_source)
- j->timer_event_source = sd_event_source_unref(j->timer_event_source);
+ 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,
- j->begin_usec + j->unit->job_timeout, 0,
+ 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");
asynchronous_sync();
}
-int job_get_timeout(Job *j, uint64_t *timeout) {
+int job_get_timeout(Job *j, usec_t *timeout) {
+ usec_t x = USEC_INFINITY, y = USEC_INFINITY;
Unit *u = j->unit;
- uint64_t x = -1, y = -1;
- int r = 0, q = 0;
+ int r;
assert(u);
r = sd_event_source_get_time(j->timer_event_source, &x);
if (r < 0)
return r;
- r = 1;
}
if (UNIT_VTABLE(u)->get_timeout) {
- q = UNIT_VTABLE(u)->get_timeout(u, &y);
- if (q < 0)
- return q;
+ r = UNIT_VTABLE(u)->get_timeout(u, &y);
+ if (r < 0)
+ return r;
}
- if (r == 0 && q == 0)
+ if (x == USEC_INFINITY && y == USEC_INFINITY)
return 0;
*timeout = MIN(x, y);
-
return 1;
}
[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_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";
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-event.h"
#include "list.h"
+#include "unit-name.h"
typedef struct Job Job;
typedef struct JobDependency JobDependency;
* 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
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_result_to_string(JobResult t) _const_;
JobResult job_result_from_string(const char *s) _pure_;
-int job_get_timeout(Job *j, uint64_t *timeout) _pure_;
+const char* job_type_to_access_method(JobType t);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#define TIMEOUT_USEC (10 * USEC_PER_SEC)
-static bool ignore_proc(pid_t pid) {
+static bool ignore_proc(pid_t pid, bool warn_rootfs) {
_cleanup_fclose_ FILE *f = NULL;
char c;
const char *p;
* spree.
*
* http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
- if (count == 1 && c == '@')
+ 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;
if (parse_pid(d->d_name, &pid) < 0)
continue;
- if (ignore_proc(pid))
+ if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
continue;
if (sig == SIGKILL) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
}
+ u->dropin_paths = strv_free(u->dropin_paths);
r = unit_find_dropin_paths(u, &u->dropin_paths);
if (r <= 0)
return 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unit.h"
#include "dropin.h"
+#include "unit.h"
/* Read service data supplementary drop-in directories */
$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_bounding_set, 0, offsetof($1, exec_context.capability_bounding_set_drop)
+$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.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_sec_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE, config_parse_bytes_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
-$1.LimitDATA, config_parse_bytes_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
-$1.LimitSTACK, config_parse_bytes_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
-$1.LimitCORE, config_parse_bytes_limit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
-$1.LimitRSS, config_parse_bytes_limit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
+$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_bytes_limit, RLIMIT_AS, 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_bytes_limit, RLIMIT_MEMLOCK, 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_bytes_limit, RLIMIT_MSGQUEUE, 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_usec_limit, RLIMIT_RTTIME, 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.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_netclass, 0, offsetof($1, cgroup_context)'
+$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.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, 0, offsetof(Unit, job_timeout)
+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)
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, offsetof(Service, timeout_start_usec)
-Service.TimeoutStartSec, config_parse_service_timeout, 0, offsetof(Service, timeout_start_usec)
-Service.TimeoutStopSec, config_parse_service_timeout, 0, offsetof(Service, timeout_stop_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(Service, start_limit.interval)
-Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Service, start_limit.burst)
-Service.StartLimitAction, config_parse_failure_action, 0, offsetof(Service, start_limit_action)
-Service.RebootArgument, config_parse_string, 0, offsetof(Service, reboot_arg)
+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)
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
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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 "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
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,
void *data,
void *userdata) {
+ _cleanup_free_ char *cmd = NULL;
ExecCommand **e = data;
+ Unit *u = userdata;
const char *p;
bool semicolon;
int r;
assert(lvalue);
assert(rvalue);
assert(e);
+ assert(u);
e += ltype;
rvalue += strspn(rvalue, WHITESPACE);
return 0;
}
- p = rvalue;
+ 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;
return 0;
}
-int config_parse_bounding_set(
+int config_parse_capability_set(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
- uint64_t *capability_bounding_set_drop = data;
- uint64_t capability_bounding_set, sum = 0;
+ uint64_t *capability_set = data;
+ uint64_t sum = 0, initial = 0;
bool invert = false;
const char *p;
rvalue++;
}
- /* Note that we store this inverted internally, since the
- * kernel wants it like this. But we actually expose it
- * non-inverted everywhere to have a fully normalized
- * interface. */
+ if (strcmp(lvalue, "CapabilityBoundingSet") == 0)
+ initial = CAP_ALL; /* initialized to all bits on */
+ /* else "AmbientCapabilities" initialized to all bits off */
p = rvalue;
for (;;) {
cap = capability_from_name(word);
if (cap < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding/ambient set, ignoring: %s", word);
continue;
}
sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap;
}
- capability_bounding_set = invert ? ~sum : sum;
- if (*capability_bounding_set_drop != 0 && capability_bounding_set != 0)
- *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set);
+ sum = invert ? ~sum : sum;
+
+ if (sum == 0 || *capability_set == initial)
+ /* "" or uninitialized data -> replace */
+ *capability_set = sum;
else
- *capability_bounding_set_drop = ~capability_bounding_set;
+ /* previous data -> merge */
+ *capability_set |= sum;
return 0;
}
void *data,
void *userdata) {
- struct rlimit **rl = data;
- rlim_t v;
+ struct rlimit **rl = data, d = {};
int r;
assert(filename);
assert(rvalue);
assert(data);
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- v = RLIM_INFINITY;
- else {
- uint64_t u;
-
- /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
- assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
-
- r = safe_atou64(rvalue, &u);
- if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
- r = -ERANGE;
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- v = (rlim_t) u;
- }
-
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
- }
-
- (*rl)->rlim_cur = (*rl)->rlim_max = v;
- return 0;
-}
-
-int config_parse_bytes_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;
- rlim_t bytes;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- bytes = RLIM_INFINITY;
- else {
- uint64_t u;
-
- r = parse_size(rvalue, 1024, &u);
- if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
- r = -ERANGE;
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- bytes = (rlim_t) u;
+ 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 (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
}
- (*rl)->rlim_cur = (*rl)->rlim_max = bytes;
- return 0;
-}
-
-int config_parse_sec_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;
- rlim_t seconds;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- seconds = RLIM_INFINITY;
+ if (rl[ltype])
+ *rl[ltype] = d;
else {
- usec_t t;
-
- r = parse_sec(rvalue, &t);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (t == USEC_INFINITY)
- seconds = RLIM_INFINITY;
- else
- seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
- }
-
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
+ rl[ltype] = newdup(struct rlimit, &d, 1);
+ if (!rl[ltype])
return log_oom();
}
- (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
- return 0;
-}
-
-
-int config_parse_usec_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;
- rlim_t useconds;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- useconds = RLIM_INFINITY;
- else {
- usec_t t;
-
- r = parse_time(rvalue, &t, 1);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (t == USEC_INFINITY)
- useconds = RLIM_INFINITY;
- else
- useconds = (rlim_t) t;
- }
-
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
- }
-
- (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
return 0;
}
void *data,
void *userdata) {
- ExecContext *c = data;
- const char *word, *state;
- size_t l;
+
unsigned long flags = 0;
+ ExecContext *c = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
- _cleanup_free_ char *t;
-
- t = strndup(word, l);
- if (!t)
- return log_oom();
-
- if (streq(t, "shared"))
- flags = MS_SHARED;
- else if (streq(t, "slave"))
- flags = MS_SLAVE;
- else if (streq(t, "private"))
- flags = MS_PRIVATE;
- else {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
- return 0;
- }
+ 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;
}
- if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
c->mount_flags = flags;
+
return 0;
}
void *data,
void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *p = NULL;
Socket *s = data;
Unit *x;
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) {
+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(rvalue);
assert(s);
- r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
- rvalue, data, userdata);
- if (r < 0)
- return r;
+ /* This is called for three cases: TimeoutSec=, TimeoutStopSec= and TimeoutStartSec=. */
- if (streq(lvalue, "TimeoutSec")) {
- s->start_timeout_defined = true;
- s->timeout_stop_usec = s->timeout_start_usec;
- } else if (streq(lvalue, "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;
}
void *data,
void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
BusName *n = data;
int r;
Unit *x;
return 0;
}
-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) {
-
- CGroupContext *c = data;
- unsigned v;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- if (streq(rvalue, "auto")) {
- c->netclass_type = CGROUP_NETCLASS_TYPE_AUTO;
- return 0;
- }
-
- r = safe_atou32(rvalue, &v);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Netclass '%s' invalid. Ignoring.", rvalue);
- return 0;
- }
-
- if (v > CGROUP_NETCLASS_FIXED_MAX)
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Fixed netclass %" PRIu32 " out of allowed range (0-%d). Applying anyway.", v, (uint32_t) CGROUP_NETCLASS_FIXED_MAX);
-
- c->netclass_id = v;
- c->netclass_type = CGROUP_NETCLASS_TYPE_FIXED;
-
- return 0;
-}
-
DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
int config_parse_job_mode_isolate(
{ config_parse_log_level, "LEVEL" },
{ config_parse_exec_capabilities, "CAPABILITIES" },
{ config_parse_exec_secure_bits, "SECUREBITS" },
- { config_parse_bounding_set, "BOUNDINGSET" },
+ { config_parse_capability_set, "BOUNDINGSET" },
{ config_parse_limit, "LIMIT" },
{ config_parse_unit_deps, "UNIT [...]" },
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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_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_bounding_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_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_bytes_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_sec_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_usec_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_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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "netlink-util.h"
static int start_loopback(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, LOOPBACK_IFINDEX);
}
static bool check_loopback(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
unsigned flags;
int r;
}
int loopback_setup(void) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int r;
r = sd_netlink_open(&rtnl);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return 0;
}
-int machine_id_setup(const char *root) {
+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;
}
}
- if (read_machine_id(fd, id) >= 0)
- return 0;
+ /* 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 */
+ /* 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;
+ r = generate_machine_id(id, root);
+ if (r < 0)
+ return r;
+ }
if (writable)
if (write_machine_id(fd, id) >= 0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
int machine_id_commit(const char *root);
-int machine_id_setup(const char *root);
+int machine_id_setup(const char *root, sd_id128_t machine_id);
fi \
%{nil}
-%systemd_user_post() %systemd_post --user --global %{?*}
+%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}}
%systemd_preun() \
if [ $1 -eq 0 ] ; then \
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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_drop = 0;
+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 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 (pid < 0)
log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig));
else if (pid == 0) {
- struct rlimit rl = {
- .rlim_cur = RLIM_INFINITY,
- .rlim_max = RLIM_INFINITY,
- };
-
/* Enable default signal handler for core dump */
+
sa = (struct sigaction) {
.sa_handler = SIG_DFL,
};
(void) sigaction(sig, &sa, NULL);
- /* Don't limit the core dump size */
- (void) setrlimit(RLIMIT_CORE, &rl);
+ /* Don't limit the coredump size */
+ (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY));
/* Just to be sure... */
(void) chdir("/");
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;
} 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)
{ "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_bounding_set, 0, &arg_capability_bounding_set_drop },
+ { "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", "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_sec_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
- { "Manager", "DefaultLimitFSIZE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
- { "Manager", "DefaultLimitDATA", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
- { "Manager", "DefaultLimitSTACK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
- { "Manager", "DefaultLimitCORE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_CORE] },
- { "Manager", "DefaultLimitRSS", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_RSS] },
- { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE] },
- { "Manager", "DefaultLimitAS", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_AS] },
- { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC] },
- { "Manager", "DefaultLimitMEMLOCK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK] },
- { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS] },
- { "Manager", "DefaultLimitSIGPENDING", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING] },
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
- { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE] },
- { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO] },
- { "Manager", "DefaultLimitRTTIME", config_parse_usec_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
+ { "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 },
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);
+ 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;
}
ARG_DESERIALIZE,
ARG_SWITCHED_ROOT,
ARG_DEFAULT_STD_OUTPUT,
- ARG_DEFAULT_STD_ERROR
+ ARG_DEFAULT_STD_ERROR,
+ ARG_MACHINE_ID
};
static const struct option options[] = {
{ "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 },
{}
};
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)
initrd_timestamp = userspace_timestamp;
if (!skip_setup) {
- mount_setup_early();
+ 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";
* saving time change. All kernel local time concepts will be treated
* as UTC that way.
*/
- clock_reset_timewarp();
+ (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
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) {
status_welcome();
hostname_setup();
- machine_id_setup(NULL);
+ machine_id_setup(NULL, arg_machine_id);
loopback_setup();
bump_unix_max_dgram_qlen();
if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
log_error_errno(errno, "Failed to adjust timer slack: %m");
- if (arg_capability_bounding_set_drop) {
- r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
+ 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_drop, true);
+ 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";
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_warning_errno(r, "Failed to populate /etc with preset unit settings, ignoring: %m");
+ 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.");
}
arg_serialization = safe_fclose(arg_serialization);
if (queue_default_job) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *target = NULL;
Job *default_unit_job;
(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);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
de = readdir(dir);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
return false;
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. */
m->have_ask_password = -EINVAL; /* we don't know */
m->first_boot = -1;
- m->cgroup_netclass_registry_last = CGROUP_NETCLASS_FIXED_MAX;
-
m->test_run = test_run;
/* Reboot immediately if the user hits C-A-D more often than 7x per 2s */
hashmap_free(m->cgroup_unit);
set_free_free(m->unit_path_cache);
- hashmap_free(m->cgroup_netclass_registry);
-
free(m->switch_root);
free(m->switch_root_init);
for (i = 0; i < _RLIMIT_MAX; i++)
- free(m->rlimit[i]);
+ m->rlimit[i] = mfree(m->rlimit[i]);
assert(hashmap_isempty(m->units_requiring_mounts_for));
hashmap_free(m->units_requiring_mounts_for);
}
int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
}
static int manager_start_target(Manager *m, const char *name, JobMode mode) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
log_debug("Activating special unit %s", name);
switch (sfsi.ssi_signo - SIGRTMIN) {
case 20:
- log_debug("Enabling showing of status.");
manager_set_show_status(m, SHOW_STATUS_YES);
break;
case 21:
- log_debug("Disabling showing of status.");
manager_set_show_status(m, SHOW_STATUS_NO);
break;
case 22:
log_set_max_level(LOG_DEBUG);
- log_notice("Setting log level to debug.");
+ log_info("Setting log level to debug.");
break;
case 23:
log_set_max_level(LOG_INFO);
- log_notice("Setting log level to info.");
+ log_info("Setting log level to info.");
break;
case 24:
/* 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--;
assert(m);
for (i = 0; i < _RLIMIT_MAX; i++) {
+ m->rlimit[i] = mfree(m->rlimit[i]);
+
if (!default_rlimit[i])
continue;
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)
/* 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_TRY_RESTART, JOB_RELOAD_OR_START))
+ 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_TRY_RESTART, JOB_RELOAD_OR_START))))
+ (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_TRY_RESTART, JOB_RELOAD_OR_START))))
+ (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 */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <libmount.h>
#include <stdbool.h>
#include <stdio.h>
-#include <libmount.h>
#include "sd-bus.h"
#include "sd-event.h"
+
#include "cgroup-util.h"
#include "fdset.h"
#include "hashmap.h"
const char *unit_log_format_string;
int first_boot;
-
- /* Used for NetClass=auto units */
- Hashmap *cgroup_netclass_registry;
- uint32_t cgroup_netclass_registry_last;
};
int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/* Relabel first, just in case */
if (relabel)
- label_fix(p->where, true, true);
+ (void) label_fix(p->where, true, true);
r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
- if (r < 0 && r != -ENOENT)
- return r;
+ 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;
/* The access mode here doesn't really matter too much, since
* the mounted file system will take precedence anyway. */
if (relabel)
- mkdir_p_label(p->where, 0755);
+ (void) mkdir_p_label(p->where, 0755);
else
- mkdir_p(p->where, 0755);
+ (void) mkdir_p(p->where, 0755);
log_debug("Mounting %s to %s of type %s with options %s.",
p->what,
p->type,
p->flags,
p->options) < 0) {
- log_full((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, "Failed to mount %s at %s: %m", p->type, p->where);
+ 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)
- label_fix(p->where, false, false);
+ (void) label_fix(p->where, false, false);
return 1;
}
-int mount_setup_early(void) {
+static int mount_points_setup(unsigned n, bool loaded_policy) {
unsigned i;
int r = 0;
- 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 */
- for (i = 0; i < N_EARLY_MOUNT; i ++) {
+ for (i = 0; i < n; i ++) {
int j;
- j = mount_one(mount_table + i, false);
+ 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;
return log_oom();
r = symlink(options, t);
- if (r < 0 && errno != EEXIST)
- return log_error_errno(errno, "Failed to create symlink %s: %m", t);
+ if (r >= 0) {
#ifdef SMACK_RUN_LABEL
- r = mac_smack_copy(t, options);
- if (r < 0 && r != -EOPNOTSUPP)
- return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t);
+ _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);
}
}
}
#endif
int mount_setup(bool loaded_policy) {
- unsigned i;
int r = 0;
- for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
- int j;
-
- j = mount_one(mount_table + i, loaded_policy);
- if (j != 0 && r >= 0)
- r = j;
- }
+ r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy);
if (r < 0)
return r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
u->ignore_on_isolate = true;
}
-static int mount_arm_timer(Mount *m) {
+static int mount_arm_timer(Mount *m, usec_t usec) {
int r;
assert(m);
- if (m->timeout_usec <= 0) {
- m->timer_event_source = sd_event_source_unref(m->timer_event_source);
- return 0;
- }
-
if (m->timer_event_source) {
- r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
+ 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,
- now(CLOCK_MONOTONIC) + m->timeout_usec, 0,
+ usec, 0,
mount_dispatch_timer, m);
if (r < 0)
return r;
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);
+ 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;
if (r < 0)
return r;
- r = mount_arm_timer(m);
+ r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec));
if (r < 0)
return r;
}
r = unit_setup_exec_runtime(UNIT(m));
if (r < 0)
- goto fail;
+ return r;
- r = mount_arm_timer(m);
+ r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
if (r < 0)
- goto fail;
+ return r;
exec_params.environment = UNIT(m)->manager->environment;
exec_params.confirm_spawn = UNIT(m)->manager->confirm_spawn;
m->exec_runtime,
&pid);
if (r < 0)
- goto fail;
+ return r;
r = unit_watch_pid(UNIT(m), pid);
if (r < 0)
/* FIXME: we need to do something here */
- goto fail;
+ return r;
*_pid = pid;
return 0;
-
-fail:
- m->timer_event_source = sd_event_source_unref(m->timer_event_source);
-
- return r;
}
static void mount_enter_dead(Mount *m, MountResult f) {
goto fail;
if (r > 0) {
- r = mount_arm_timer(m);
+ r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
if (r < 0)
goto fail;
m->mount_monitor = NULL;
}
-static int mount_get_timeout(Unit *u, uint64_t *timeout) {
+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, timeout);
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Mount Mount;
-#include "kill.h"
#include "execute.h"
+#include "kill.h"
typedef enum MountExecCommand {
MOUNT_EXEC_MOUNT,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static void path_enter_running(Path *p) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ Unit *trigger;
int r;
assert(p);
if (unit_stop_pending(UNIT(p)))
return;
- r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)), JOB_REPLACE, &error, NULL);
+ 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;
static int path_start(Unit *u) {
Path *p = PATH(u);
+ Unit *trigger;
assert(p);
assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
- if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+ 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
}
-static int scope_arm_timer(Scope *s) {
+static int scope_arm_timer(Scope *s, usec_t usec) {
int r;
assert(s);
- if (s->timeout_stop_usec <= 0) {
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- return 0;
- }
-
if (s->timer_event_source) {
- r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
+ 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,
- now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0,
+ usec, 0,
scope_dispatch_timer, s);
if (r < 0)
return r;
assert(s);
assert(s->state == SCOPE_DEAD);
- if (s->deserialized_state != s->state) {
-
- if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
- r = scope_arm_timer(s);
- if (r < 0)
- return r;
- }
-
- if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
- unit_watch_all_pids(UNIT(s));
+ if (s->deserialized_state == s->state)
+ return 0;
- scope_set_state(s, s->deserialized_state);
+ 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;
}
r = 1;
if (r > 0) {
- r = scope_arm_timer(s);
+ r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
if (r < 0)
goto fail;
return unit_kill_common(u, who, signo, -1, -1, error);
}
-static int scope_get_timeout(Unit *u, uint64_t *timeout) {
+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, timeout);
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#endif
va_start(ap, fmt);
- log_internalv(LOG_AUTH | callback_type_to_priority(type),
- 0, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
+ log_internalv(LOG_AUTH | callback_type_to_priority(type), 0, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
va_end(ap);
return 0;
}
-/*
- Function must be called once to initialize the SELinux AVC environment.
- Sets up callbacks.
- If you want to cleanup memory you should need to call selinux_access_finish.
-*/
-static int access_init(void) {
- int r = 0;
+static int access_init(sd_bus_error *error) {
- if (avc_open(NULL, 0))
- return log_error_errno(errno, "avc_open() failed: %m");
+ if (!mac_selinux_use())
+ return 0;
- selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
- selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
+ if (initialized)
+ return 1;
- if (security_getenforce() < 0){
- r = -errno;
- avc_destroy();
- }
+ if (avc_open(NULL, 0) != 0) {
+ int enforce, saved_errno = errno;
- return r;
-}
-
-static int mac_selinux_access_init(sd_bus_error *error) {
- int r;
+ enforce = security_getenforce();
+ log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m");
- if (initialized)
- return 0;
+ /* 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;
- if (!mac_selinux_use())
- 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));
+ }
- r = access_init();
- if (r < 0)
- return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
+ 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 0;
+ return 1;
}
-#endif
/*
This function communicates with the kernel to check whether or not it should
const char *permission,
sd_bus_error *error) {
-#ifdef HAVE_SELINUX
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
assert(permission);
assert(error);
- if (!mac_selinux_use())
- return 0;
-
- r = mac_selinux_access_init(error);
- if (r < 0)
+ r = access_init(error);
+ if (r <= 0)
return r;
r = sd_bus_query_sender_creds(
}
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
}
+
+#endif
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-bus.h"
+
#include "bus-util.h"
#include "manager.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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;
- RATELIMIT_INIT(s->start_limit, u->manager->default_start_limit_interval, u->manager->default_start_limit_burst);
-
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
}
return;
if (s->watchdog_event_source) {
- r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
+ 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;
UNIT(s)->manager->event,
&s->watchdog_event_source,
CLOCK_MONOTONIC,
- s->watchdog_timestamp.monotonic + s->watchdog_usec, 0,
+ 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");
s->pid_file = mfree(s->pid_file);
s->status_text = mfree(s->status_text);
- s->reboot_arg = mfree(s->reboot_arg);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
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);
assert(s);
if (s->timer_event_source) {
- r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + usec);
+ 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,
- now(CLOCK_MONOTONIC) + usec, 0,
+ usec, 0,
service_dispatch_timer, s);
if (r < 0)
return r;
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;
}
/* Oneshot services have disabled start timeout by default */
if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
- s->timeout_start_usec = 0;
+ s->timeout_start_usec = USEC_INFINITY;
service_fix_output(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,
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;
if (s->deserialized_state == s->state)
return 0;
- if (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)) {
-
- usec_t k;
-
- k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec;
-
- /* For the start/stop timeouts 0 means off */
- if (k > 0) {
- r = service_arm_timer(s, k);
- if (r < 0)
- return r;
- }
- }
-
- if (s->deserialized_state == SERVICE_AUTO_RESTART) {
-
- /* The restart timeouts 0 means immediately */
- r = service_arm_timer(s, s->restart_usec);
- if (r < 0)
- return r;
- }
+ 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) &&
r = unit_setup_exec_runtime(UNIT(s));
if (r < 0)
- goto fail;
+ return r;
if (pass_fds ||
s->exec_context.std_input == EXEC_INPUT_SOCKET ||
r = service_collect_fds(s, &fds, &fd_names);
if (r < 0)
- goto fail;
+ return r;
n_fds = r;
}
- if (timeout > 0) {
- r = service_arm_timer(s, timeout);
- if (r < 0)
- goto fail;
- } else
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+ 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)
- goto fail;
+ return r;
our_env = new0(char*, 6);
- if (!our_env) {
- r = -ENOMEM;
- goto fail;
- }
+ 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) {
- r = -ENOMEM;
- goto fail;
- }
+ 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) {
- r = -ENOMEM;
- goto fail;
- }
+ 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) {
- r = -ENOMEM;
- goto fail;
- }
+ 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) {
- r = -errno;
- goto fail;
- }
+ if (r < 0)
+ return -errno;
if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) {
_cleanup_free_ char *addr = NULL;
r = sockaddr_pretty(&sa.sa, salen, true, false, &addr);
if (r < 0)
- goto fail;
+ return r;
t = strappend("REMOTE_ADDR=", addr);
- if (!t) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!t)
+ return -ENOMEM;
our_env[n_env++] = t;
port = sockaddr_port(&sa.sa);
- if (port < 0) {
- r = port;
- goto fail;
- }
+ if (port < 0)
+ return port;
- if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) {
- r = -ENOMEM;
- goto fail;
- }
+ 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) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!final_env)
+ return -ENOMEM;
if (is_control && UNIT(s)->cgroup_path) {
path = strjoina(UNIT(s)->cgroup_path, "/control");
r = bus_kernel_create_endpoint(UNIT(s)->manager->running_as == MANAGER_SYSTEM ? "system" : "user",
UNIT(s)->id, &bus_endpoint_path);
if (r < 0)
- goto fail;
+ 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
s->exec_runtime,
&pid);
if (r < 0)
- goto fail;
+ return r;
r = unit_watch_pid(UNIT(s), pid);
if (r < 0)
/* FIXME: we need to do something here */
- goto fail;
+ return r;
*_pid = pid;
return 0;
-
-fail:
- if (timeout)
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-
- return r;
}
static int main_pid_good(Service *s) {
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, s->reboot_arg);
+ failure_action(UNIT(s)->manager, s->failure_action, UNIT(s)->reboot_arg);
}
if (allow_restart && service_shall_restart(s)) {
- r = service_arm_timer(s, s->restart_usec);
+ r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
if (r < 0)
goto fail;
* out-of-date, and some software might be confused by it, so
* let's remove it. */
if (s->pid_file)
- unlink_noerrno(s->pid_file);
+ (void) unlink(s->pid_file);
return;
goto fail;
if (r > 0) {
- if (s->timeout_stop_usec > 0) {
- r = service_arm_timer(s, s->timeout_stop_usec);
- if (r < 0)
- goto fail;
- }
+ 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)
unit_watch_all_pids(UNIT(s));
- if (s->timeout_stop_usec > 0)
- service_arm_timer(s, s->timeout_stop_usec);
+ 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);
if (f != SERVICE_SUCCESS)
s->result = f;
+ service_unwatch_control_pid(s);
+
if (service_good(s)) {
/* If there are any queued up sd_notify()
service_enter_reload_by_notify(s);
else if (s->notify_state == NOTIFY_STOPPING)
service_enter_stop_by_notify(s);
- else
+ 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);
static void service_enter_start(Service *s) {
ExecCommand *c;
+ usec_t timeout;
pid_t pid;
int r;
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,
- IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_ONESHOT) ? s->timeout_start_usec : 0,
+ timeout,
true,
true,
true,
if (r < 0)
goto fail;
- if (s->type == SERVICE_SIMPLE || s->type == SERVICE_IDLE) {
+ if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) {
/* For simple services we immediately start
* the START_POST binaries. */
s->control_pid = pid;
service_set_state(s, SERVICE_START);
- } else if (s->type == SERVICE_ONESHOT ||
- s->type == SERVICE_DBUS ||
- s->type == SERVICE_NOTIFY) {
+ } 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. */
}
static void service_enter_restart(Service *s) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(s);
/* 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, s->restart_usec);
+ r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
if (r < 0)
goto fail;
static void service_enter_reload_by_notify(Service *s) {
assert(s);
- if (s->timeout_start_usec > 0)
- service_arm_timer(s, s->timeout_start_usec);
-
+ service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec));
service_set_state(s, SERVICE_RELOAD);
}
}
static void service_run_next_control(Service *s) {
+ usec_t timeout;
int r;
assert(s);
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,
- IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec,
+ timeout,
false,
!s->permissions_start_only,
!s->root_directory_start_only,
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
-static int service_start_limit_test(Service *s) {
- assert(s);
-
- if (ratelimit_test(&s->start_limit))
- return 0;
-
- log_unit_warning(UNIT(s), "Start request repeated too quickly.");
-
- return failure_action(UNIT(s)->manager, s->start_limit_action, s->reboot_arg);
-}
-
static int service_start(Unit *u) {
Service *s = SERVICE(u);
- int r;
assert(s);
assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
- /* Make sure we don't enter a busy loop of some kind. */
- r = service_start_limit_test(s);
- if (r < 0) {
- service_enter_dead(s, SERVICE_FAILURE_START_LIMIT, false);
- return r;
- }
-
s->result = SERVICE_SUCCESS;
s->reload_result = SERVICE_SUCCESS;
s->main_pid_known = false;
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)
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;
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;
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;
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);
case SERVICE_START_POST:
if (f != SERVICE_SUCCESS) {
- service_enter_stop(s, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
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. Stopping.");
- service_unwatch_control_pid(s);
+ 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);
unit_add_to_dbus_queue(u);
}
-static int service_get_timeout(Unit *u, uint64_t *timeout) {
+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, timeout);
+ 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;
}
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
s->state == SERVICE_RUNNING ||
s->state == SERVICE_RELOAD)) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
/* Try to acquire PID from bus service */
if (s->state != SERVICE_DEAD)
return -EAGAIN;
- if (getpeername_pretty(fd, &peer) >= 0) {
+ if (getpeername_pretty(fd, true, &peer) >= 0) {
if (UNIT(s)->description) {
_cleanup_free_ char *a;
s->result = SERVICE_SUCCESS;
s->reload_result = SERVICE_SUCCESS;
-
- RATELIMIT_RESET(s->start_limit);
}
static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
[SERVICE_FAILURE_SIGNAL] = "signal",
[SERVICE_FAILURE_CORE_DUMP] = "core-dump",
[SERVICE_FAILURE_WATCHDOG] = "watchdog",
- [SERVICE_FAILURE_START_LIMIT] = "start-limit"
};
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Service Service;
typedef struct ServiceFDStore ServiceFDStore;
+#include "exit-status.h"
+#include "kill.h"
#include "path.h"
#include "ratelimit.h"
-#include "kill.h"
-#include "exit-status.h"
typedef enum ServiceRestart {
SERVICE_RESTART_NO,
SERVICE_FAILURE_SIGNAL,
SERVICE_FAILURE_CORE_DUMP,
SERVICE_FAILURE_WATCHDOG,
- SERVICE_FAILURE_START_LIMIT,
_SERVICE_RESULT_MAX,
_SERVICE_RESULT_INVALID = -1
} ServiceResult;
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;
bool reset_cpu_usage:1;
char *bus_name;
+ char *bus_name_owner; /* unique name of the current owner */
char *status_text;
int status_errno;
- RateLimit start_limit;
- FailureAction start_limit_action;
FailureAction failure_action;
- char *reboot_arg;
UnitRef accept_socket;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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 SMACK_RUN_LABEL
r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
- if (r)
- log_warning_errno(r, "Failed to set SMACK label \"%s\" on self: %m", SMACK_RUN_LABEL);
+ 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/");
return 0;
case ENOENT:
log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found");
- return 0;
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <linux/sctp.h>
#include "sd-event.h"
-
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
s->tcp_congestion = mfree(s->tcp_congestion);
s->bind_to_device = mfree(s->bind_to_device);
- free(s->smack);
- free(s->smack_ip_in);
- free(s->smack_ip_out);
+ 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);
- free(s->user);
- free(s->group);
+ 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) {
+static int socket_arm_timer(Socket *s, usec_t usec) {
int r;
assert(s);
- if (s->timeout_usec <= 0) {
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- return 0;
- }
-
if (s->timer_event_source) {
- r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+ 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,
- now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
+ usec, 0,
socket_dispatch_timer, s);
if (r < 0)
return r;
return 0;
t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device);
- return unit_add_node_link(UNIT(s), t, false);
+ return unit_add_node_link(UNIT(s), t, false, UNIT_BINDS_TO);
}
static int socket_add_default_dependencies(Socket *s) {
if (s->no_delay) {
int b = s->no_delay;
- if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
- log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m");
+
+ 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) {
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,
if (r < 0)
return r;
- r = socket_arm_timer(s);
+ r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
if (r < 0)
return r;
}
SOCKET_STOP_PRE,
SOCKET_STOP_PRE_SIGTERM,
SOCKET_STOP_PRE_SIGKILL)) {
+
r = socket_open_fds(s);
if (r < 0)
return r;
r = unit_setup_exec_runtime(UNIT(s));
if (r < 0)
- goto fail;
+ return r;
- r = socket_arm_timer(s);
+ r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
- goto fail;
+ return r;
r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
if (r < 0)
- goto fail;
+ return r;
exec_params.argv = argv;
exec_params.environment = UNIT(s)->manager->environment;
s->exec_runtime,
&pid);
if (r < 0)
- goto fail;
+ return r;
r = unit_watch_pid(UNIT(s), pid);
if (r < 0)
/* FIXME: we need to do something here */
- goto fail;
+ return r;
*_pid = pid;
return 0;
-
-fail:
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- return r;
}
static int socket_chown(Socket *s, pid_t *_pid) {
pid_t pid;
int r;
- r = socket_arm_timer(s);
+ r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
goto fail;
if (r > 0) {
- r = socket_arm_timer(s);
+ r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
}
static void socket_enter_running(Socket *s, int cfd) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(s);
s->result = SOCKET_SUCCESS;
}
-static void socket_notify_service_dead(Socket *s, bool failed_permanent) {
- assert(s);
-
- /* The service is dead. Dang!
- *
- * This is strictly for one-instance-for-all-connections
- * services. */
-
- if (s->state == SOCKET_RUNNING) {
- log_unit_debug(UNIT(s), "Got notified about service death (failed permanently: %s)", yes_no(failed_permanent));
- if (failed_permanent)
- socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_FAILED_PERMANENT);
- else
- socket_enter_listening(s);
- }
-}
-
void socket_connection_unref(Socket *s) {
assert(s);
static void socket_trigger_notify(Unit *u, Unit *other) {
Socket *s = SOCKET(u);
- Service *se;
assert(u);
assert(other);
/* Don't propagate state changes from the service if we are
already down or accepting connections */
- if ((s->state != SOCKET_RUNNING &&
- s->state != SOCKET_LISTENING) ||
- s->accept)
+ if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING) || s->accept)
return;
- if (other->load_state != UNIT_LOADED ||
- other->type != UNIT_SERVICE)
+ if (other->start_limit_hit) {
+ socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT);
return;
+ }
- se = SERVICE(other);
-
- if (se->state == SERVICE_FAILED)
- socket_notify_service_dead(s, se->result == SERVICE_FAILURE_START_LIMIT);
+ if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+ return;
- if (se->state == SERVICE_DEAD ||
- se->state == SERVICE_FINAL_SIGTERM ||
- se->state == SERVICE_FINAL_SIGKILL ||
- se->state == SERVICE_AUTO_RESTART)
- socket_notify_service_dead(s, false);
+ if (IN_SET(SERVICE(other)->state,
+ SERVICE_DEAD, SERVICE_FAILED,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
+ SERVICE_AUTO_RESTART))
+ socket_enter_listening(s);
- if (se->state == SERVICE_RUNNING)
+ if (SERVICE(other)->state == SERVICE_RUNNING)
socket_set_state(s, SOCKET_RUNNING);
}
return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
}
-static int socket_get_timeout(Unit *u, uint64_t *timeout) {
+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, timeout);
+ 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;
}
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
[SOCKET_FAILURE_SIGNAL] = "signal",
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
- [SOCKET_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent"
+ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Socket Socket;
-#include "socket-util.h"
#include "mount.h"
#include "service.h"
+#include "socket-util.h"
typedef enum SocketExecCommand {
SOCKET_EXEC_START_PRE,
SOCKET_FAILURE_EXIT_CODE,
SOCKET_FAILURE_SIGNAL,
SOCKET_FAILURE_CORE_DUMP,
- SOCKET_FAILURE_SERVICE_FAILED_PERMANENT,
+ SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
_SOCKET_RESULT_MAX,
_SOCKET_RESULT_INVALID = -1
} SocketResult;
bool remove_on_stop;
bool writable;
+ int socket_protocol;
+
/* Socket options */
bool keep_alive;
bool no_delay;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
}
-static int swap_arm_timer(Swap *s) {
+static int swap_arm_timer(Swap *s, usec_t usec) {
int r;
assert(s);
- if (s->timeout_usec <= 0) {
- s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- return 0;
- }
-
if (s->timer_event_source) {
- r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+ 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,
- now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
+ usec, 0,
swap_dispatch_timer, s);
if (r < 0)
return r;
return 0;
if (is_device_path(s->what))
- return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == MANAGER_SYSTEM);
+ 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
}
static int swap_add_default_dependencies(Swap *s) {
+ int r;
+
assert(s);
if (!UNIT(s)->default_dependencies)
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);
}
if (r < 0)
return r;
- r = swap_arm_timer(s);
+ r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
if (r < 0)
return r;
}
if (r < 0)
goto fail;
- r = swap_arm_timer(s);
+ r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
goto fail;
if (r > 0) {
- r = swap_arm_timer(s);
+ r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
}
-static int swap_get_timeout(Unit *u, uint64_t *timeout) {
+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, timeout);
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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. */
case TIMER_UNIT_ACTIVE:
leave_around = true;
- base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
+ base = trigger->inactive_exit_timestamp.monotonic;
if (base <= 0)
base = t->last_trigger.monotonic;
case TIMER_UNIT_INACTIVE:
leave_around = true;
- base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
+ base = trigger->inactive_enter_timestamp.monotonic;
if (base <= 0)
base = t->last_trigger.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 (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) {
}
static void timer_enter_running(Timer *t) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ Unit *trigger;
int r;
assert(t);
if (unit_stop_pending(UNIT(t)))
return;
- r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)), JOB_REPLACE, &error, NULL);
+ 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;
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);
- if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
Unit meta;
usec_t accuracy_usec;
+ usec_t random_usec;
LIST_HEAD(TimerValue, values);
usec_t next_elapse_realtime;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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);
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 && unit->load_state == UNIT_ERROR) {
- if (unit->load_error == -ENOENT || unit->manager->test_run)
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s.",
- unit->id,
- strerror(-unit->load_error));
- else
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s. "
- "See system logs and 'systemctl status %s' for details.",
- unit->id,
- strerror(-unit->load_error),
- unit->id);
+ if (type != JOB_STOP) {
+ r = bus_unit_check_load_state(unit, e);
+ if (r < 0)
+ return r;
}
- if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s.",
- unit->id, strerror(-unit->load_error));
-
- if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
- return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
- "Unit %s is masked.", unit->id);
-
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.",
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)
+ 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)
+ 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,
- r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, r,
- "Cannot add dependency job, ignoring: %s",
+ 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)
+ 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)
+ if (r != -EBADR) /* job type not applicable */
goto fail;
sd_bus_error_free(e);
r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e);
if (r < 0) {
- if (r != -EBADR)
+ 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) {
- r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, false, false, ignore_order, e);
+ 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",
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Transaction Transaction;
-#include "unit.h"
-#include "manager.h"
-#include "job.h"
#include "hashmap.h"
+#include "job.h"
+#include "manager.h"
+#include "unit.h"
struct Transaction {
/* Jobs to be added */
# The contents of this are an example to be copied into systemd.spec.
-%transfiletriggerin -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+%transfiletriggerin -P 900900 -p <lua> -- @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.
-%transfiletriggerun -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+pid = posix.fork()
+if pid == 0 then
+ assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+elseif pid > 0 then
+ posix.wait(pid)
+end
+
+%transfiletriggerun -p <lua> -- @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 <lua> -- @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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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;
static void unit_done(Unit *u) {
ExecContext *ec;
CGroupContext *cc;
- int r;
assert(u);
cc = unit_get_cgroup_context(u);
if (cc)
cgroup_context_done(cc);
-
- r = unit_remove_from_netclass_cgroup(u);
- if (r < 0)
- log_warning_errno(r, "Unable to remove unit from netclass group: %m");
}
void unit_free(Unit *u) {
condition_free_list(u->conditions);
condition_free_list(u->asserts);
+ free(u->reboot_arg);
+
unit_ref_unset(&u->slice);
while (u->refs)
Iterator i;
const char *prefix2;
char
+ timestamp0[FORMAT_TIMESTAMP_MAX],
timestamp1[FORMAT_TIMESTAMP_MAX],
timestamp2[FORMAT_TIMESTAMP_MAX],
timestamp3[FORMAT_TIMESTAMP_MAX],
"%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"
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)),
STRV_FOREACH(j, u->dropin_paths)
fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
- if (u->job_timeout > 0)
+ 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)
}
unit_update_cgroup_members_masks(u);
-
- /* If we are reloading, we need to wait for the deserializer
- * to restore the net_cls ids that have been set previously */
- if (u->manager->n_reloading <= 0) {
- r = unit_add_to_netclass_cgroup(u);
- if (r < 0)
- return r;
- }
}
assert((u->load_state != UNIT_MERGED) == !u->merged_into);
format = unit_get_status_message_format(u, t);
DISABLE_WARNING_FORMAT_NONLITERAL;
- snprintf(buf, sizeof(buf), format, unit_description(u));
+ xsprintf(buf, format, unit_description(u));
REENABLE_WARNING;
mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
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
+ * -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);
- /* Units that aren't loaded cannot be started */
- if (u->load_state != UNIT_LOADED)
- return -EINVAL;
-
/* 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
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,
static void unit_check_unneeded(Unit *u) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static const UnitDependency needed_dependencies[] = {
UNIT_REQUIRED_BY,
}
static void unit_check_binds_to(Unit *u) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool stop = false;
Unit *other;
Iterator i;
/* Update timestamps for state changes */
if (m->n_reloading <= 0) {
- dual_timestamp ts;
-
- dual_timestamp_get(&ts);
+ dual_timestamp_get(&u->state_change_timestamp);
if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
- u->inactive_exit_timestamp = ts;
+ 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 = ts;
+ 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 = ts;
+ 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 = ts;
+ u->active_exit_timestamp = u->state_change_timestamp;
}
/* Keep track of failed units */
case JOB_RELOAD:
case JOB_RELOAD_OR_START:
+ case JOB_TRY_RELOAD:
if (u->job->state == JOB_RUNNING) {
if (ns == UNIT_ACTIVE)
return unit_can_start(u);
case JOB_RELOAD:
+ case JOB_TRY_RELOAD:
return unit_can_reload(u);
case JOB_RELOAD_OR_START:
}
}
+ 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);
unit_serialize_item(u, f, "cgroup", u->cgroup_path);
unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
- if (u->cgroup_netclass_id)
- unit_serialize_item_format(u, f, "netclass-id", "%" PRIu32, u->cgroup_netclass_id);
-
if (serialize_jobs) {
if (u->job) {
fprintf(f, "job\n");
/* End marker */
if (isempty(l))
- return 0;
+ break;
k = strcspn(l, "=");
} 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
u->cgroup_realized = b;
- continue;
- } else if (streq(l, "netclass-id")) {
- r = safe_atou32(v, &u->cgroup_netclass_id);
- if (r < 0)
- log_unit_debug(u, "Failed to parse netclass ID %s, ignoring.", v);
- else {
- r = unit_add_to_netclass_cgroup(u);
- if (r < 0)
- log_unit_debug_errno(u, r, "Failed to add unit to netclass cgroup, ignoring: %m");
- }
-
continue;
}
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) {
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) {
Unit *device;
_cleanup_free_ char *e = NULL;
int r;
if (r < 0)
return r;
- r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == MANAGER_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
+ 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 (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) {
killed = true;
}
- if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_ALL_FAIL))
+ if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL))
return -ESRCH;
return r;
ec->no_new_privileges = true;
if (ec->private_devices)
- ec->capability_bounding_set_drop |= (uint64_t) 1ULL << (uint64_t) CAP_MKNOD;
+ ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD);
}
cc = unit_get_cgroup_context(u);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct UnitRef UnitRef;
typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
-#include "list.h"
#include "condition.h"
+#include "failure-action.h"
#include "install.h"
+#include "list.h"
#include "unit-name.h"
-#include "failure-action.h"
typedef enum KillOperation {
KILL_TERMINATE,
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;
/* 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;
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;
};
UNIT_PERSISTENT = 2,
} UnitSetPropertiesMode;
-#include "socket.h"
+#include "automount.h"
#include "busname.h"
-#include "target.h"
#include "device.h"
-#include "automount.h"
-#include "swap.h"
-#include "timer.h"
-#include "slice.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 */
/* Called whenever CLOCK_REALTIME made a jump */
void (*time_change)(Unit *u);
- int (*get_timeout)(Unit *u, uint64_t *timeout);
+ /* 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,
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);
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency d);
int unit_coldplug(Unit *u);
--- /dev/null
+../Makefile
\ No newline at end of file
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/statvfs.h>
+
+#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");
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#ifdef HAVE_ELFUTILS
+#include <dwarf.h>
+#include <elfutils/libdwfl.h>
+#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;
+}
--- /dev/null
+# 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=
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#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;
+}
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <dwarf.h>
+#include <elfutils/libdwfl.h>
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+int coredump_make_stack_trace(int fd, const char *executable, char **ret);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdlib.h>
+
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
"ID_MODEL_FROM_DATABASE\0"
"ID_MODEL\0";
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
struct stat st;
const char *i;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
finish:
- if (top)
- hashmap_free_free(top);
- if (bottom)
- hashmap_free_free(bottom);
- if (drops) {
- HASHMAP_FOREACH_KEY(h, key, drops, i){
- hashmap_free_free(hashmap_remove(drops, key));
- hashmap_remove(drops, key);
- free(key);
- }
- hashmap_free(drops);
+ 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;
}
r = process_suffix(n, onlyprefix);
if (r < 0)
return r;
- else
- n_found += r;
+
+ n_found += r;
}
+
return n_found;
}
/* Strip prefix from the suffix */
NULSTR_FOREACH(p, prefixes) {
- const char *suffix = startswith(arg, p);
+ const char *suffix;
+
+ suffix = startswith(arg, p);
if (suffix) {
suffix += strspn(suffix, "/");
if (*suffix)
if (b < 0) {
log_error("Failed to parse diff boolean.");
return -EINVAL;
- } else if (b)
- arg_diff = 1;
- else
- arg_diff = 0;
+ }
+
+ arg_diff = b;
}
break;
}
int main(int argc, char *argv[]) {
- int r = 0, k;
- int n_found = 0;
+ int r, k, n_found = 0;
log_parse_environment();
log_open();
for (i = optind; i < argc; i++) {
path_kill_slashes(argv[i]);
+
k = process_suffix_chop(argv[i]);
if (k < 0)
r = k;
}
if (r >= 0)
- printf("%s%i overridden configuration files found.\n",
- n_found ? "\n" : "", n_found);
+ printf("%s%i overridden configuration files found.\n", n_found ? "\n" : "", n_found);
finish:
pager_close();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
if (putspent(p, f) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return fflush_and_check(f);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static const char *arg_repair = "-a";
static void start_target(const char *target, const char *mode) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
int main(int argc, char *argv[]) {
_cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
- _cleanup_device_unref_ sd_device *dev = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *device, *type;
bool root_directory;
siginfo_t status;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(what);
assert(where);
assert(opts);
+ assert(post);
assert(source);
if (streq_ptr(fstype, "autofs"))
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
source);
- if (post && !noauto && !nofail && !automount)
+ if (!noauto && !nofail && !automount)
fprintf(f, "Before=%s\n", post);
if (!automount && opts) {
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", unit);
- if (!noauto && post) {
+ if (!noauto) {
lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
if (!lnk)
return log_oom();
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
source);
- if (post)
- fprintf(f,
- "Before=%s\n",
- post);
+ fprintf(f, "Before=%s\n", post);
if (opts) {
r = write_requires_after(f, opts);
"x-systemd.automount\0");
if (initrd)
post = SPECIAL_INITRD_FS_TARGET;
- else if (mount_in_initrd(me))
- post = SPECIAL_INITRD_ROOT_FS_TARGET;
else if (mount_is_network(me))
post = SPECIAL_REMOTE_FS_TARGET;
else
false,
false,
false,
- SPECIAL_INITRD_ROOT_FS_TARGET,
+ SPECIAL_INITRD_FS_TARGET,
"/proc/cmdline");
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
if (isatty(fd) <= 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
- if (!streq(fstype, "vfat")) {
+ 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(r, "Partition for /boot does not have a UUID, ignoring. %m");
+ log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring.");
return 0;
}
if (r == 1)
return 0; /* no results */
else if (r == -2) {
- log_warning("%s: probe gave ambiguous results, ignoring", node);
+ 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)
- return log_error_errno(errno ?: EIO,
- "%s: failed to determine partition table type: %m", node);
+ 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")) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int show_one_name(sd_bus *bus, const char* attr) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int set_simple_string(sd_bus *bus, const char *method, const char *value) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r = 0;
polkit_agent_open_if_enabled();
}
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-util.h"
#include "def.h"
#include "env-util.h"
-#include "event-util.h"
#include "fileio-label.h"
#include "hostname-util.h"
#include "parse-util.h"
unreliable enough, so let's not do any additional guesswork
on top of that.
- See the SMBIOS Specification 2.7.1 section 7.4.1 for
+ See the SMBIOS Specification 3.0 section 7.4.1 for
details about the values listed here:
- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
+ https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
*/
switch (t) {
case 0x11:
case 0x1C:
+ case 0x1D:
return "server";
+
+ case 0x1E:
+ return "tablet";
}
return NULL;
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
assert(c);
int main(int argc, char *argv[]) {
Context context = {};
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
}
static int hwdb_query(int argc, char *argv[], void *userdata) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
const char *key, *value;
const char *modalias;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
if (r == FTW_STOP)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <curl/curl.h>
+#include <sys/types.h>
#include "sd-event.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-compress.h"
+#include "macro.h"
typedef struct RawExport RawExport;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-compress.h"
+#include "macro.h"
typedef struct TarExport TarExport;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-event.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "export-raw.h"
#include "export-tar.h"
#include "fd-util.h"
static int export_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_export_unrefp) TarExport *export = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
static int export_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_export_unrefp) RawExport *export = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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);
+ r = capability_bounding_set_drop(retain, true);
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
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);
+ r = capability_bounding_set_drop(retain, true);
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-
+#include <bzlib.h>
#include <lzma.h>
+#include <sys/types.h>
#include <zlib.h>
-#include <bzlib.h>
#include "macro.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct RawImport RawImport;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct TarImport TarImport;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-event.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "hostname-util.h"
static int import_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_import_unrefp) TarImport *import = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
static int import_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_import_unrefp) RawImport *import = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
TRANSFER_EXPORT_RAW,
TRANSFER_PULL_TAR,
TRANSFER_PULL_RAW,
- TRANSFER_PULL_DKR,
_TRANSFER_TYPE_MAX,
_TRANSFER_TYPE_INVALID = -1,
} TransferType;
bool force_local;
bool read_only;
- char *dkr_index_url;
char *format;
pid_t pid;
[TRANSFER_EXPORT_RAW] = "export-raw",
[TRANSFER_PULL_TAR] = "pull-tar",
[TRANSFER_PULL_RAW] = "pull-raw",
- [TRANSFER_PULL_DKR] = "pull-dkr",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
free(t->remote);
free(t->local);
- free(t->dkr_index_url);
free(t->format);
free(t->object_path);
if (t->pid == 0) {
const char *cmd[] = {
NULL, /* systemd-import, systemd-export or systemd-pull */
- NULL, /* tar, raw, dkr */
+ NULL, /* tar, raw */
NULL, /* --verify= */
NULL, /* verify argument */
NULL, /* maybe --force */
NULL, /* maybe --read-only */
- NULL, /* maybe --dkr-index-url */
NULL, /* if so: the actual URL */
NULL, /* maybe --format= */
NULL, /* if so: the actual format */
if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR))
cmd[k++] = "tar";
- else if (IN_SET(t->type, TRANSFER_IMPORT_RAW, TRANSFER_EXPORT_RAW, TRANSFER_PULL_RAW))
- cmd[k++] = "raw";
else
- cmd[k++] = "dkr";
+ cmd[k++] = "raw";
if (t->verify != _IMPORT_VERIFY_INVALID) {
cmd[k++] = "--verify";
if (t->read_only)
cmd[k++] = "--read-only";
- if (t->dkr_index_url) {
- cmd[k++] = "--dkr-index-url";
- cmd[k++] = t->dkr_index_url;
- }
-
if (t->format) {
cmd[k++] = "--format";
cmd[k++] = t->format;
return 0;
}
-static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_index_url, const char *remote) {
+static Transfer *manager_find(Manager *m, TransferType type, const char *remote) {
Transfer *t;
Iterator i;
HASHMAP_FOREACH(t, m->transfers, i) {
if (t->type == type &&
- streq_ptr(t->remote, remote) &&
- streq_ptr(t->dkr_index_url, dkr_index_url))
+ streq_ptr(t->remote, remote))
return t;
}
type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
- if (manager_find(m, type, NULL, remote))
+ 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);
return sd_bus_reply_method_return(msg, "uo", id, object);
}
-static int method_pull_dkr(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
- _cleanup_(transfer_unrefp) Transfer *t = NULL;
- const char *index_url, *remote, *tag, *local, *verify, *object;
- Manager *m = userdata;
- ImportVerify v;
- 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, "sssssb", &index_url, &remote, &tag, &local, &verify, &force);
- if (r < 0)
- return r;
-
- if (isempty(index_url))
- index_url = DEFAULT_DKR_INDEX_URL;
- if (!index_url)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL must be specified.");
- if (!http_url_is_valid(index_url))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL %s is invalid", index_url);
-
- if (!dkr_name_is_valid(remote))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Remote name %s is not valid", remote);
-
- if (isempty(tag))
- tag = "latest";
- else if (!dkr_tag_is_valid(tag))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Tag %s is not valid", tag);
-
- 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);
-
- if (v != IMPORT_VERIFY_NO)
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "DKR does not support verification.");
-
- r = setup_machine_directory((uint64_t) -1, error);
- if (r < 0)
- return r;
-
- if (manager_find(m, TRANSFER_PULL_DKR, index_url, 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 = TRANSFER_PULL_DKR;
- t->verify = v;
- t->force_local = force;
-
- t->dkr_index_url = strdup(index_url);
- if (!t->dkr_index_url)
- return -ENOMEM;
-
- t->remote = strjoin(remote, ":", tag, NULL);
- 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_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Transfer *t;
Iterator i;
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("PullDkr", "sssssb", "uo", method_pull_dkr, 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),
send_interface="org.freedesktop.import1.Manager"
send_member="PullRaw"/>
- <allow send_destination="org.freedesktop.import1"
- send_interface="org.freedesktop.import1.Manager"
- send_member="PullDkr"/>
-
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Transfer"
send_member="Cancel"/>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
-#include "pull-job.h"
#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);
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <curl/curl.h>
-#include <sys/prctl.h>
-
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "aufs-util.h"
-#include "btrfs-util.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 "json.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "pull-common.h"
-#include "pull-dkr.h"
-#include "pull-job.h"
-#include "rm-rf.h"
-#include "string-util.h"
-#include "strv.h"
-#include "utf8.h"
-#include "web-util.h"
-
-typedef enum DkrProgress {
- DKR_SEARCHING,
- DKR_RESOLVING,
- DKR_METADATA,
- DKR_DOWNLOADING,
- DKR_COPYING,
-} DkrProgress;
-
-struct DkrPull {
- sd_event *event;
- CurlGlue *glue;
-
- char *index_protocol;
- char *index_address;
-
- char *index_url;
- char *image_root;
-
- PullJob *images_job;
- PullJob *tags_job;
- PullJob *ancestry_job;
- PullJob *json_job;
- PullJob *layer_job;
-
- char *name;
- char *reference;
- char *id;
-
- char *response_digest;
- char *response_token;
- char **response_registries;
-
- char **ancestry;
- unsigned n_ancestry;
- unsigned current_ancestry;
-
- DkrPullFinished on_finished;
- void *userdata;
-
- char *local;
- bool force_local;
- bool grow_machine_directory;
-
- char *temp_path;
- char *final_path;
-
- pid_t tar_pid;
-};
-
-#define PROTOCOL_PREFIX "https://"
-
-#define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:"
-#define HEADER_REGISTRY "X-Do" /* the HTTP header for the registry */ "cker-Endpoints:"
-#define HEADER_DIGEST "Do" /* the HTTP header for the manifest digest */ "cker-Content-Digest:"
-#define LAYERS_MAX 127
-
-static void dkr_pull_job_on_finished(PullJob *j);
-
-DkrPull* dkr_pull_unref(DkrPull *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->images_job);
- pull_job_unref(i->tags_job);
- pull_job_unref(i->ancestry_job);
- pull_job_unref(i->json_job);
- pull_job_unref(i->layer_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);
- }
-
- free(i->name);
- free(i->reference);
- free(i->id);
- free(i->response_token);
- strv_free(i->ancestry);
- free(i->final_path);
- free(i->index_address);
- free(i->index_protocol);
- free(i->index_url);
- free(i->image_root);
- free(i->local);
- free(i);
-
- return NULL;
-}
-
-int dkr_pull_new(
- DkrPull **ret,
- sd_event *event,
- const char *index_url,
- const char *image_root,
- DkrPullFinished on_finished,
- void *userdata) {
-
- _cleanup_(dkr_pull_unrefp) DkrPull *i = NULL;
- char *e;
- int r;
-
- assert(ret);
- assert(index_url);
-
- if (!http_url_is_valid(index_url))
- return -EINVAL;
-
- i = new0(DkrPull, 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");
-
- i->index_url = strdup(index_url);
- if (!i->index_url)
- return -ENOMEM;
-
- e = endswith(i->index_url, "/");
- if (e)
- *e = 0;
-
- 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 dkr_pull_report_progress(DkrPull *i, DkrProgress p) {
- unsigned percent;
-
- assert(i);
-
- switch (p) {
-
- case DKR_SEARCHING:
- percent = 0;
- if (i->images_job)
- percent += i->images_job->progress_percent * 5 / 100;
- break;
-
- case DKR_RESOLVING:
- percent = 5;
- if (i->tags_job)
- percent += i->tags_job->progress_percent * 5 / 100;
- break;
-
- case DKR_METADATA:
- percent = 10;
- if (i->ancestry_job)
- percent += i->ancestry_job->progress_percent * 5 / 100;
- if (i->json_job)
- percent += i->json_job->progress_percent * 5 / 100;
- break;
-
- case DKR_DOWNLOADING:
- percent = 20;
- percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry);
- if (i->layer_job)
- percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100;
-
- break;
-
- case DKR_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 parse_id(const void *payload, size_t size, char **ret) {
- _cleanup_free_ char *buf = NULL, *id = NULL, *other = NULL;
- union json_value v = {};
- void *json_state = NULL;
- const char *p;
- int t;
-
- assert(payload);
- assert(ret);
-
- if (size <= 0)
- return -EBADMSG;
-
- if (memchr(payload, 0, size))
- return -EBADMSG;
-
- buf = strndup(payload, size);
- if (!buf)
- return -ENOMEM;
-
- p = buf;
- t = json_tokenize(&p, &id, &v, &json_state, NULL);
- if (t < 0)
- return t;
- if (t != JSON_STRING)
- return -EBADMSG;
-
- t = json_tokenize(&p, &other, &v, &json_state, NULL);
- if (t < 0)
- return t;
- if (t != JSON_END)
- return -EBADMSG;
-
- if (!dkr_id_is_valid(id))
- return -EBADMSG;
-
- *ret = id;
- id = NULL;
-
- return 0;
-}
-
-static int parse_ancestry(const void *payload, size_t size, char ***ret) {
- _cleanup_free_ char *buf = NULL;
- void *json_state = NULL;
- const char *p;
- enum {
- STATE_BEGIN,
- STATE_ITEM,
- STATE_COMMA,
- STATE_END,
- } state = STATE_BEGIN;
- _cleanup_strv_free_ char **l = NULL;
- size_t n = 0, allocated = 0;
-
- if (size <= 0)
- return -EBADMSG;
-
- if (memchr(payload, 0, size))
- return -EBADMSG;
-
- buf = strndup(payload, size);
- if (!buf)
- return -ENOMEM;
-
- p = buf;
- for (;;) {
- _cleanup_free_ char *str;
- union json_value v = {};
- int t;
-
- t = json_tokenize(&p, &str, &v, &json_state, NULL);
- if (t < 0)
- return t;
-
- switch (state) {
-
- case STATE_BEGIN:
- if (t == JSON_ARRAY_OPEN)
- state = STATE_ITEM;
- else
- return -EBADMSG;
-
- break;
-
- case STATE_ITEM:
- if (t == JSON_STRING) {
- if (!dkr_id_is_valid(str))
- return -EBADMSG;
-
- if (n+1 > LAYERS_MAX)
- return -EFBIG;
-
- if (!GREEDY_REALLOC(l, allocated, n + 2))
- return -ENOMEM;
-
- l[n++] = str;
- str = NULL;
- l[n] = NULL;
-
- state = STATE_COMMA;
-
- } else if (t == JSON_ARRAY_CLOSE)
- state = STATE_END;
- else
- return -EBADMSG;
-
- break;
-
- case STATE_COMMA:
- if (t == JSON_COMMA)
- state = STATE_ITEM;
- else if (t == JSON_ARRAY_CLOSE)
- state = STATE_END;
- else
- return -EBADMSG;
- break;
-
- case STATE_END:
- if (t == JSON_END) {
-
- if (strv_isempty(l))
- return -EBADMSG;
-
- if (!strv_is_uniq(l))
- return -EBADMSG;
-
- l = strv_reverse(l);
-
- *ret = l;
- l = NULL;
- return 0;
- } else
- return -EBADMSG;
- }
-
- }
-}
-
-static const char *dkr_pull_current_layer(DkrPull *i) {
- assert(i);
-
- if (strv_isempty(i->ancestry))
- return NULL;
-
- return i->ancestry[i->current_ancestry];
-}
-
-static const char *dkr_pull_current_base_layer(DkrPull *i) {
- assert(i);
-
- if (strv_isempty(i->ancestry))
- return NULL;
-
- if (i->current_ancestry <= 0)
- return NULL;
-
- return i->ancestry[i->current_ancestry-1];
-}
-
-static int dkr_pull_add_token(DkrPull *i, PullJob *j) {
- const char *t;
-
- assert(i);
- assert(j);
-
- if (i->response_token)
- t = strjoina("Authorization: Token ", i->response_token);
- else
- t = HEADER_TOKEN " true";
-
- j->request_header = curl_slist_new("Accept: application/json", t, NULL);
- if (!j->request_header)
- return -ENOMEM;
-
- return 0;
-}
-
-static int dkr_pull_add_bearer_token(DkrPull *i, PullJob *j) {
- const char *t = NULL;
-
- assert(i);
- assert(j);
-
- if (i->response_token)
- t = strjoina("Authorization: Bearer ", i->response_token);
- else
- return -EINVAL;
-
- j->request_header = curl_slist_new("Accept: application/json", t, NULL);
- if (!j->request_header)
- return -ENOMEM;
-
- return 0;
-}
-
-static bool dkr_pull_is_done(DkrPull *i) {
- assert(i);
- assert(i->images_job);
- if (i->images_job->state != PULL_JOB_DONE)
- return false;
-
- if (!i->tags_job || i->tags_job->state != PULL_JOB_DONE)
- return false;
-
- if (!i->ancestry_job || i->ancestry_job->state != PULL_JOB_DONE)
- return false;
-
- if (i->json_job && i->json_job->state != PULL_JOB_DONE)
- return false;
-
- if (i->layer_job && i->layer_job->state != PULL_JOB_DONE)
- return false;
-
- if (dkr_pull_current_layer(i))
- return false;
-
- return true;
-}
-
-static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) {
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(i);
-
- if (!i->local)
- return 0;
-
- if (!i->final_path) {
- i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL);
- if (!i->final_path)
- return -ENOMEM;
- }
-
- if (version == DKR_PULL_V2) {
- p = dirname_malloc(i->image_root);
- if (!p)
- return -ENOMEM;
- }
-
- r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local);
- if (r < 0)
- return r;
-
- if (version == DKR_PULL_V2) {
- char **k;
-
- STRV_FOREACH(k, i->ancestry) {
- _cleanup_free_ char *d;
-
- d = strjoin(i->image_root, "/.dkr-", *k, NULL);
- if (!d)
- return -ENOMEM;
-
- r = btrfs_subvol_remove(d, BTRFS_REMOVE_QUOTA);
- if (r < 0)
- return r;
- }
-
- r = rmdir(i->image_root);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int dkr_pull_job_on_open_disk(PullJob *j) {
- const char *base;
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- assert(i->layer_job == j);
- assert(i->final_path);
- assert(!i->temp_path);
- assert(i->tar_pid <= 0);
-
- r = tempfn_random(i->final_path, NULL, &i->temp_path);
- if (r < 0)
- return log_oom();
-
- mkdir_parents_label(i->temp_path, 0700);
-
- base = dkr_pull_current_base_layer(i);
- if (base) {
- const char *base_path;
-
- base_path = strjoina(i->image_root, "/.dkr-", base);
- r = btrfs_subvol_snapshot(base_path, i->temp_path, BTRFS_SNAPSHOT_FALLBACK_COPY|BTRFS_SNAPSHOT_QUOTA);
- } else
- r = btrfs_subvol_make(i->temp_path);
- if (r < 0)
- return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path);
-
- (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 void dkr_pull_job_on_progress(PullJob *j) {
- DkrPull *i;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
-
- dkr_pull_report_progress(
- i,
- j == i->images_job ? DKR_SEARCHING :
- j == i->tags_job ? DKR_RESOLVING :
- j == i->ancestry_job || j == i->json_job ? DKR_METADATA :
- DKR_DOWNLOADING);
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j);
-
-static int dkr_pull_pull_layer_v2(DkrPull *i) {
- _cleanup_free_ char *path = NULL;
- const char *url, *layer = NULL;
- int r;
-
- assert(i);
- assert(!i->layer_job);
- assert(!i->temp_path);
- assert(!i->final_path);
-
- for (;;) {
- layer = dkr_pull_current_layer(i);
- if (!layer)
- return 0; /* no more layers */
-
- path = strjoin(i->image_root, "/.dkr-", layer, NULL);
- if (!path)
- return log_oom();
-
- if (laccess(path, F_OK) < 0) {
- if (errno == ENOENT)
- break;
-
- return log_error_errno(errno, "Failed to check for container: %m");
- }
-
- log_info("Layer %s already exists, skipping.", layer);
-
- i->current_ancestry++;
-
- path = mfree(path);
- }
-
- log_info("Pulling layer %s...", layer);
-
- i->final_path = path;
- path = NULL;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/blobs/", layer);
- r = pull_job_new(&i->layer_job, url, i->glue, i);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate layer job: %m");
-
- r = dkr_pull_add_bearer_token(i, i->layer_job);
- if (r < 0)
- return log_oom();
-
- i->layer_job->on_finished = dkr_pull_job_on_finished_v2;
- i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
- i->layer_job->on_progress = dkr_pull_job_on_progress;
- i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
- r = pull_job_begin(i->layer_job);
- if (r < 0)
- return log_error_errno(r, "Failed to start layer job: %m");
-
- return 0;
-}
-
-static int dkr_pull_pull_layer(DkrPull *i) {
- _cleanup_free_ char *path = NULL;
- const char *url, *layer = NULL;
- int r;
-
- assert(i);
- assert(!i->layer_job);
- assert(!i->temp_path);
- assert(!i->final_path);
-
- for (;;) {
- layer = dkr_pull_current_layer(i);
- if (!layer)
- return 0; /* no more layers */
-
- path = strjoin(i->image_root, "/.dkr-", layer, NULL);
- if (!path)
- return log_oom();
-
- if (laccess(path, F_OK) < 0) {
- if (errno == ENOENT)
- break;
-
- return log_error_errno(errno, "Failed to check for container: %m");
- }
-
- log_info("Layer %s already exists, skipping.", layer);
-
- i->current_ancestry++;
-
- path = mfree(path);
- }
-
- log_info("Pulling layer %s...", layer);
-
- i->final_path = path;
- path = NULL;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", layer, "/layer");
- r = pull_job_new(&i->layer_job, url, i->glue, i);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate layer job: %m");
-
- r = dkr_pull_add_token(i, i->layer_job);
- if (r < 0)
- return log_oom();
-
- i->layer_job->on_finished = dkr_pull_job_on_finished;
- i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
- i->layer_job->on_progress = dkr_pull_job_on_progress;
- i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
- r = pull_job_begin(i->layer_job);
- if (r < 0)
- return log_error_errno(r, "Failed to start layer job: %m");
-
- return 0;
-}
-
-static int dkr_pull_job_on_header(PullJob *j, const char *header, size_t sz) {
- _cleanup_free_ char *registry = NULL;
- char *token, *digest;
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- r = curl_header_strdup(header, sz, HEADER_TOKEN, &token);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- free(i->response_token);
- i->response_token = token;
- return 0;
- }
-
- r = curl_header_strdup(header, sz, HEADER_DIGEST, &digest);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- free(i->response_digest);
- i->response_digest = digest;
- return 0;
- }
-
- r = curl_header_strdup(header, sz, HEADER_REGISTRY, ®istry);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- char **l, **k;
-
- l = strv_split(registry, ",");
- if (!l)
- return log_oom();
-
- STRV_FOREACH(k, l) {
- if (!hostname_is_valid(*k, false)) {
- log_error("Registry hostname is not valid.");
- strv_free(l);
- return -EBADMSG;
- }
- }
-
- strv_free(i->response_registries);
- i->response_registries = l;
- }
-
- return 0;
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j) {
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- if (j->error != 0) {
- if (j == i->images_job)
- log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
- else if (j == i->ancestry_job)
- log_error_errno(j->error, "Failed to retrieve manifest.");
- else if (j == i->json_job)
- log_error_errno(j->error, "Failed to retrieve json data.");
- else
- log_error_errno(j->error, "Failed to retrieve layer data.");
-
- r = j->error;
- goto finish;
- }
-
- if (i->images_job == j) {
- const char *url;
-
- assert(!i->tags_job);
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- if (strv_isempty(i->response_registries)) {
- r = -EBADMSG;
- log_error("Didn't get registry information.");
- goto finish;
- }
-
- log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
- dkr_pull_report_progress(i, DKR_RESOLVING);
-
- url = strjoina(i->index_protocol, "auth.", i->index_address, "/v2/token/?scope=repository:",
- i->name, ":pull&service=registry.", i->index_address);
- r = pull_job_new(&i->tags_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate tags job: %m");
- goto finish;
- }
-
- i->tags_job->on_finished = dkr_pull_job_on_finished_v2;
- i->tags_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->tags_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start tags job: %m");
- goto finish;
- }
-
- } else if (i->tags_job == j) {
- const char *url;
- _cleanup_free_ char *buf;
- _cleanup_json_variant_unref_ JsonVariant *doc = NULL;
- JsonVariant *e = NULL;
-
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- buf = strndup((const char *)j->payload, j->payload_size);
- if (!buf) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- r = json_parse(buf, &doc);
- if (r < 0) {
- log_error("Unable to parse bearer token\n%s", j->payload);
- goto finish;
- }
-
- e = json_variant_value(doc, "token");
- if (!e || e->type != JSON_VARIANT_STRING) {
- r = -EBADMSG;
- log_error("Invalid JSON format for Bearer token");
- goto finish;
- }
-
- r = free_and_strdup(&i->response_token, json_variant_string(e));
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/manifests/", i->reference);
- r = pull_job_new(&i->ancestry_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate ancestry job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_bearer_token(i, i->ancestry_job);
- if (r < 0)
- goto finish;
-
- i->ancestry_job->on_finished = dkr_pull_job_on_finished_v2;
- i->ancestry_job->on_progress = dkr_pull_job_on_progress;
- i->ancestry_job->on_header = dkr_pull_job_on_header;
-
-
- r = pull_job_begin(i->ancestry_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start ancestry job: %m");
- goto finish;
- }
-
- } else if (i->ancestry_job == j) {
-
- _cleanup_json_variant_unref_ JsonVariant *doc = NULL, *compat = NULL;
- JsonVariant *e = NULL;
- _cleanup_strv_free_ char **ancestry = NULL;
- size_t allocated = 0, size = 0;
- char *path = NULL, **k = NULL;
-
- r = json_parse((const char *)j->payload, &doc);
- if (r < 0) {
- log_error("Invalid JSON Manifest");
- goto finish;
- }
-
- e = json_variant_value(doc, "fsLayers");
- if (!e || e->type != JSON_VARIANT_ARRAY || e->size == 0) {
- r = -EBADMSG;
- goto finish;
- }
-
- log_info("JSON manifest with schema v%"PRIi64" for %s parsed!",
- json_variant_integer(json_variant_value(doc, "schemaVersion")),
- json_variant_string(json_variant_value(doc, "name")));
-
- for (unsigned z = 0; z < e->size; z++) {
- JsonVariant *f = json_variant_element(e, z), *g = NULL;
- const char *layer;
- if (f->type != JSON_VARIANT_OBJECT) {
- r = -EBADMSG;
- goto finish;
- }
-
- g = json_variant_value(f, "blobSum");
-
- layer = json_variant_string(g);
- if (!dkr_digest_is_valid(layer)) {
- r = -EBADMSG;
- goto finish;
- }
-
- if (!GREEDY_REALLOC(ancestry, allocated, size + 2)) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- ancestry[size] = strdup(layer);
- if (!ancestry[size]) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- ancestry[size+1] = NULL;
- size += 1;
- }
-
- e = json_variant_value(doc, "history");
- if (!e || e->type != JSON_VARIANT_ARRAY) {
- r = -EBADMSG;
- goto finish;
- }
-
- e = json_variant_element(e, 0);
- e = json_variant_value(e, "v1Compatibility");
- r = json_parse(json_variant_string(e), &compat);
- if (r < 0) {
- log_error("Invalid v1Compatibility JSON");
- goto finish;
- }
-
- e = json_variant_value(compat, "id");
-
- strv_free(i->ancestry);
- i->ancestry = strv_reverse(strv_uniq(ancestry));
- i->n_ancestry = strv_length(i->ancestry);
- i->current_ancestry = 0;
- i->id = strdup(i->ancestry[i->n_ancestry - 1]);
- if (!i->id) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
- path = strjoin(i->image_root, "/.dkr-", json_variant_string(e), NULL);
- if (!path) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
- free(i->image_root);
- i->image_root = path;
- ancestry = NULL;
-
- log_info("Required layers:\n");
- STRV_FOREACH(k, i->ancestry)
- log_info("\t%s", *k);
- log_info("\nProvenance:\n\tImageID: %s\n\tDigest: %s", json_variant_string(e), i->response_digest);
-
- dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
- r = dkr_pull_pull_layer_v2(i);
- if (r < 0)
- goto finish;
-
- } else if (i->layer_job == j) {
- assert(i->temp_path);
- assert(i->final_path);
-
- j->disk_fd = safe_close(j->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;
- }
-
- r = aufs_resolve(i->temp_path);
- if (r < 0) {
- log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
- goto finish;
- }
-
- r = btrfs_subvol_set_read_only(i->temp_path, true);
- if (r < 0) {
- log_error_errno(r, "Failed to mark snapshot read-only: %m");
- goto finish;
- }
-
- if (rename(i->temp_path, i->final_path) < 0) {
- log_error_errno(errno, "Failed to rename snaphsot: %m");
- goto finish;
- }
-
- log_info("Completed writing to layer %s.", i->final_path);
-
- i->layer_job = pull_job_unref(i->layer_job);
- free(i->temp_path);
- i->temp_path = NULL;
- free(i->final_path);
- i->final_path = NULL;
-
- i->current_ancestry ++;
- r = dkr_pull_pull_layer_v2(i);
- if (r < 0)
- goto finish;
-
- } else if (i->json_job != j)
- assert_not_reached("Got finished event for unknown curl object");
-
- if (!dkr_pull_is_done(i))
- return;
-
- dkr_pull_report_progress(i, DKR_COPYING);
-
- r = dkr_pull_make_local_copy(i, DKR_PULL_V2);
- 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 void dkr_pull_job_on_finished(PullJob *j) {
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- if (j->error != 0) {
- if (j == i->images_job)
- log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
- else if (j == i->tags_job)
- log_error_errno(j->error, "Failed to retrieve tags list.");
- else if (j == i->ancestry_job)
- log_error_errno(j->error, "Failed to retrieve ancestry list.");
- else if (j == i->json_job)
- log_error_errno(j->error, "Failed to retrieve json data.");
- else
- log_error_errno(j->error, "Failed to retrieve layer data.");
-
- r = j->error;
- goto finish;
- }
-
- if (i->images_job == j) {
- const char *url;
-
- assert(!i->tags_job);
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- if (strv_isempty(i->response_registries)) {
- r = -EBADMSG;
- log_error("Didn't get registry information.");
- goto finish;
- }
-
- log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
- dkr_pull_report_progress(i, DKR_RESOLVING);
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->reference);
- r = pull_job_new(&i->tags_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate tags job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->tags_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->tags_job->on_finished = dkr_pull_job_on_finished;
- i->tags_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->tags_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start tags job: %m");
- goto finish;
- }
-
- } else if (i->tags_job == j) {
- const char *url;
- char *id = NULL;
-
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- r = parse_id(j->payload, j->payload_size, &id);
- if (r < 0) {
- log_error_errno(r, "Failed to parse JSON id.");
- goto finish;
- }
-
- free(i->id);
- i->id = id;
-
- log_info("Tag lookup succeeded, resolved to layer %s.", i->id);
- dkr_pull_report_progress(i, DKR_METADATA);
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry");
- r = pull_job_new(&i->ancestry_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate ancestry job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->ancestry_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->ancestry_job->on_finished = dkr_pull_job_on_finished;
- i->ancestry_job->on_progress = dkr_pull_job_on_progress;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json");
- r = pull_job_new(&i->json_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate json job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->json_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->json_job->on_finished = dkr_pull_job_on_finished;
- i->json_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->ancestry_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start ancestry job: %m");
- goto finish;
- }
-
- r = pull_job_begin(i->json_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start json job: %m");
- goto finish;
- }
-
- } else if (i->ancestry_job == j) {
- char **ancestry = NULL, **k;
- unsigned n;
-
- assert(!i->layer_job);
-
- r = parse_ancestry(j->payload, j->payload_size, &ancestry);
- if (r < 0) {
- log_error_errno(r, "Failed to parse JSON id.");
- goto finish;
- }
-
- n = strv_length(ancestry);
- if (n <= 0 || !streq(ancestry[n-1], i->id)) {
- log_error("Ancestry doesn't end in main layer.");
- strv_free(ancestry);
- r = -EBADMSG;
- goto finish;
- }
-
- log_info("Ancestor lookup succeeded, requires layers:\n");
- STRV_FOREACH(k, ancestry)
- log_info("\t%s", *k);
-
- strv_free(i->ancestry);
- i->ancestry = ancestry;
- i->n_ancestry = n;
- i->current_ancestry = 0;
-
- dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
- r = dkr_pull_pull_layer(i);
- if (r < 0)
- goto finish;
-
- } else if (i->layer_job == j) {
- assert(i->temp_path);
- assert(i->final_path);
-
- j->disk_fd = safe_close(j->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;
- }
-
- r = aufs_resolve(i->temp_path);
- if (r < 0) {
- log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
- goto finish;
- }
-
- r = btrfs_subvol_set_read_only(i->temp_path, true);
- if (r < 0) {
- log_error_errno(r, "Failed to mark snapshot read-only: %m");
- goto finish;
- }
-
- if (rename(i->temp_path, i->final_path) < 0) {
- log_error_errno(errno, "Failed to rename snaphsot: %m");
- goto finish;
- }
-
- log_info("Completed writing to layer %s.", i->final_path);
-
- i->layer_job = pull_job_unref(i->layer_job);
- i->temp_path = mfree(i->temp_path);
- i->final_path = mfree(i->final_path);
-
- i->current_ancestry ++;
- r = dkr_pull_pull_layer(i);
- if (r < 0)
- goto finish;
-
- } else if (i->json_job != j)
- assert_not_reached("Got finished event for unknown curl object");
-
- if (!dkr_pull_is_done(i))
- return;
-
- dkr_pull_report_progress(i, DKR_COPYING);
-
- r = dkr_pull_make_local_copy(i, DKR_PULL_V1);
- 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 get_protocol_address(char **protocol, char **address, const char *url) {
- const char *sep, *dot;
- _cleanup_free_ char *a = NULL, *p = NULL;
-
- sep = strstr(url, "://");
- if (!sep)
- return -EINVAL;
-
- dot = strrchr(url, '.');
- if (!dot)
- return -EINVAL;
- dot--;
-
- p = strndup(url, (sep - url) + 3);
- if (!p)
- return log_oom();
-
- while (dot > (sep + 3) && *dot != '.')
- dot--;
-
- a = strdup(dot + 1);
- if (!a)
- return log_oom();
-
- *address = a;
- *protocol = p;
- a = p = NULL;
-
- return 0;
-}
-
-int dkr_pull_start(DkrPull *i, const char *name, const char *reference, const char *local, bool force_local, DkrPullVersion version) {
- const char *url;
- int r;
-
- assert(i);
-
- if (!dkr_name_is_valid(name))
- return -EINVAL;
-
- if (reference && !dkr_ref_is_valid(reference))
- return -EINVAL;
-
- if (local && !machine_name_is_valid(local))
- return -EINVAL;
-
- if (i->images_job)
- return -EBUSY;
-
- if (!reference)
- reference = "latest";
-
- free(i->index_protocol);
- free(i->index_address);
- r = get_protocol_address(&i->index_protocol, &i->index_address, i->index_url);
- if (r < 0)
- return r;
-
- r = free_and_strdup(&i->local, local);
- if (r < 0)
- return r;
- i->force_local = force_local;
-
- r = free_and_strdup(&i->name, name);
- if (r < 0)
- return r;
- r = free_and_strdup(&i->reference, reference);
- if (r < 0)
- return r;
-
- url = strjoina(i->index_url, "/v1/repositories/", name, "/images");
-
- r = pull_job_new(&i->images_job, url, i->glue, i);
- if (r < 0)
- return r;
-
- r = dkr_pull_add_token(i, i->images_job);
- if (r < 0)
- return r;
-
- if (version == DKR_PULL_V1)
- i->images_job->on_finished = dkr_pull_job_on_finished;
- else
- i->images_job->on_finished = dkr_pull_job_on_finished_v2;
-
- i->images_job->on_header = dkr_pull_job_on_header;
- i->images_job->on_progress = dkr_pull_job_on_progress;
-
- return pull_job_begin(i->images_job);
-}
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#pragma once
-
-#include "sd-event.h"
-#include "util.h"
-
-typedef enum { DKR_PULL_V1, DKR_PULL_V2 } DkrPullVersion;
-typedef struct DkrPull DkrPull;
-
-typedef void (*DkrPullFinished)(DkrPull *pull, int error, void *userdata);
-
-int dkr_pull_new(DkrPull **pull, sd_event *event, const char *index_url, const char *image_root, DkrPullFinished on_finished, void *userdata);
-DkrPull* dkr_pull_unref(DkrPull *pull);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DkrPull*, dkr_pull_unref);
-
-int dkr_pull_start(DkrPull *pull, const char *name, const char *tag, const char *local, bool force_local, DkrPullVersion version);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <gcrypt.h>
-#include "macro.h"
#include "curl-util.h"
#include "import-compress.h"
+#include "macro.h"
typedef struct PullJob PullJob;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct RawPull RawPull;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct TarPull TarPull;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-event.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "hostname-util.h"
#include "import-util.h"
#include "machine-image.h"
#include "parse-util.h"
-#include "pull-dkr.h"
#include "pull-raw.h"
#include "pull-tar.h"
#include "signal-util.h"
static bool arg_force = false;
static const char *arg_image_root = "/var/lib/machines";
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
static bool arg_settings = true;
static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
static int pull_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_pull_unrefp) TarPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *url, *local;
_cleanup_free_ char *l = NULL, *ll = NULL;
int r;
static int pull_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_pull_unrefp) RawPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *url, *local;
_cleanup_free_ char *l = NULL, *ll = NULL;
int r;
return -r;
}
-static void on_dkr_finished(DkrPull *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_dkr(int argc, char *argv[], void *userdata) {
- _cleanup_(dkr_pull_unrefp) DkrPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
- const char *name, *reference, *local, *digest;
- int r;
-
- if (!arg_dkr_index_url) {
- log_error("Please specify an index URL with --dkr-index-url=");
- return -EINVAL;
- }
-
- if (arg_verify != IMPORT_VERIFY_NO) {
- log_error("Pulls from dkr do not support image verification, please pass --verify=no.");
- return -EINVAL;
- }
-
- digest = strchr(argv[1], '@');
- if (digest) {
- reference = digest + 1;
- name = strndupa(argv[1], digest - argv[1]);
- } else {
- reference = strchr(argv[1], ':');
- if (reference) {
- name = strndupa(argv[1], reference - argv[1]);
- reference++;
- } else {
- name = argv[1];
- reference = "latest";
- }
- }
-
- if (!dkr_name_is_valid(name)) {
- log_error("Remote name '%s' is not valid.", name);
- return -EINVAL;
- }
-
- if (!dkr_ref_is_valid(reference)) {
- log_error("Tag name '%s' is not valid.", reference);
- return -EINVAL;
- }
-
- if (argc >= 3)
- local = argv[2];
- else {
- local = strchr(name, '/');
- if (local)
- local++;
- else
- local = name;
- }
-
- if (isempty(local) || streq(local, "-"))
- local = NULL;
-
- if (local) {
- 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' with reference '%s', saving as '%s'.", name, reference, local);
- } else
- log_info("Pulling '%s' with reference '%s'.", name, reference);
-
- 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 = dkr_pull_new(&pull, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate puller: %m");
-
- r = dkr_pull_start(pull, name, reference, local, arg_force, DKR_PULL_V2);
- 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"
" --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"
- " --dkr-index-url=URL Specify index URL to use for downloads\n\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"
- " dkr REMOTE [NAME] Download a DKR image\n",
+ " raw URL [NAME] Download a RAW image\n",
program_invocation_short_name);
return 0;
enum {
ARG_VERSION = 0x100,
ARG_FORCE,
- ARG_DKR_INDEX_URL,
ARG_IMAGE_ROOT,
ARG_VERIFY,
ARG_SETTINGS,
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "force", no_argument, NULL, ARG_FORCE },
- { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
{ "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "settings", required_argument, NULL, ARG_SETTINGS },
arg_force = true;
break;
- case ARG_DKR_INDEX_URL:
- if (!http_url_is_valid(optarg)) {
- log_error("Index URL is not valid: %s", optarg);
- return -EINVAL;
- }
-
- arg_dkr_index_url = optarg;
- break;
-
case ARG_IMAGE_ROOT:
arg_image_root = optarg;
break;
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "tar", 2, 3, 0, pull_tar },
{ "raw", 2, 3, 0, pull_raw },
- { "dkr", 2, 3, 0, pull_dkr },
{}
};
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static void change_runlevel(Server *s, int runlevel) {
const char *target;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *mode;
bool isolate = false;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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;
} else if (r == 0) {
if (m->follow) {
- r = sd_journal_wait(m->journal, (uint64_t) -1);
+ 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;
}
}
n = m->size - pos;
+ if (n < 1)
+ return 0;
if (n > max)
n = max;
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_offset(st.st_size, fd, 0);
+ response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
if (!response)
return respond_oom(connection);
}
static int get_virtualization(char **v) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
char *b = NULL;
int r;
assert(method);
if (!streq(method, "GET"))
- return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+ return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE,
"Unsupported method.\n");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#pragma once
#include "sd-event.h"
+
#include "journal-remote-write.h"
typedef enum {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return r;
}
-static int spawn_getter(const char *getter, const char *url) {
+static int spawn_getter(const char *getter) {
int r;
_cleanup_strv_free_ char **words = NULL;
if (r < 0)
return log_error_errno(r, "Failed to split getter option: %m");
- r = strv_extend(&words, url);
- if (r < 0)
- return log_error_errno(r, "Failed to create command line: %m");
-
r = spawn_child(words[0], words);
if (r < 0)
log_error_errno(r, "Failed to spawn getter %s: %m", getter);
static int setup_raw_socket(RemoteServer *s, const char *address) {
int fd;
- fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
+ fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC);
if (fd < 0)
return fd;
*connection_cls);
if (!streq(method, "POST"))
- return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+ return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE,
"Unsupported method.\n");
if (!streq(url, "/upload"))
if (r < 0)
return code;
} else {
- r = getnameinfo_pretty(fd, &hostname);
+ r = getpeername_pretty(fd, false, &hostname);
if (r < 0)
return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
"Cannot check remote hostname");
{ 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, DATA_SIZE_MAX},
+ { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
const char *trust) {
int fd;
- fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
+ fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC);
if (fd < 0)
return fd;
} else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
char *hostname;
- r = getnameinfo_pretty(fd, &hostname);
+ r = getpeername_pretty(fd, false, &hostname);
if (r < 0)
return log_error_errno(r, "Failed to retrieve remote name: %m");
fd);
}
- if (arg_url) {
- const char *url, *hostname;
+ if (arg_getter) {
+ log_info("Spawning getter %s...", arg_getter);
+ fd = spawn_getter(arg_getter);
+ if (fd < 0)
+ return fd;
- url = strjoina(arg_url, "/entries");
+ r = add_source(s, fd, (char*) arg_output, false);
+ if (r < 0)
+ return r;
+ }
- if (arg_getter) {
- log_info("Spawning getter %s...", url);
- fd = spawn_getter(arg_getter, url);
- } else {
- log_info("Spawning curl %s...", url);
- fd = spawn_curl(url);
+ 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;
startswith(arg_url, "http://") ?:
arg_url;
- r = add_source(s, fd, (char*) hostname, false);
+ 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;
}
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]
+# Seal=false
# SplitMode=host
# ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem
# ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-event.h"
-#include "hashmap.h"
-#include "microhttpd-util.h"
+#include "hashmap.h"
#include "journal-remote-parse.h"
#include "journal-remote-write.h"
+#include "microhttpd-util.h"
typedef struct MHDDaemonWrapper MHDDaemonWrapper;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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");
assert(u);
- if (u->uploading) {
- log_warning("dispatch_journal_input called when uploading, ignoring.");
+ if (u->uploading)
return 0;
- }
log_debug("Detected journal input, checking for new data.");
return check_journal_input(u);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <inttypes.h>
-#include "sd-journal.h"
#include "sd-event.h"
+#include "sd-journal.h"
typedef enum {
ENTRY_CURSOR = 0, /* Nothing actually written yet. */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#pragma once
-#include <stdarg.h>
#include <microhttpd.h>
+#include <stdarg.h>
#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. */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "syslog-util.h"
#include "util.h"
-static char *arg_identifier = NULL;
+static const char *arg_identifier = NULL;
static int arg_priority = LOG_INFO;
static bool arg_level_prefix = true;
return version();
case 't':
- free(arg_identifier);
if (isempty(optarg))
arg_identifier = NULL;
- else {
- arg_identifier = strdup(optarg);
- if (!arg_identifier)
- return log_oom();
- }
+ else
+ arg_identifier = optarg;
break;
case 'p':
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
.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,
- struct strbuf *sb,
sd_id128_t id,
const char *language,
- const char *payload) {
+ char *payload) {
- ssize_t offset;
_cleanup_free_ CatalogItem *i = NULL;
+ _cleanup_free_ char *combined = NULL, *prev = NULL;
int r;
assert(h);
- assert(sb);
assert(payload);
- offset = strbuf_add_string(sb, payload, strlen(payload));
- if (offset < 0)
- return log_oom();
-
i = new0(CatalogItem, 1);
if (!i)
return log_oom();
assert(strlen(language) > 1 && strlen(language) < 32);
strcpy(i->language, language);
}
- i->offset = htole64((uint64_t) offset);
- r = hashmap_put(h, i, i);
- if (r == -EEXIST) {
- log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.",
- SD_ID128_FORMAT_VAL(id), language ? language : "C");
- return 0;
- } else if (r < 0)
- return r;
+ 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;
+ }
- i = NULL;
return 0;
}
return 0;
}
-int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
+int catalog_import_file(Hashmap *h, const char *path) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *payload = NULL;
unsigned n = 0;
int r;
assert(h);
- assert(sb);
assert(path);
f = fopen(path, "re");
if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
if (got_id) {
- r = finish_item(h, sb, id, lang ?: deflang, payload);
+ r = finish_item(h, id, lang ?: deflang, payload);
if (r < 0)
return r;
+ payload = NULL;
lang = mfree(lang);
}
}
if (got_id) {
- r = finish_item(h, sb, id, lang ?: deflang, payload);
+ r = finish_item(h, id, lang ?: deflang, payload);
if (r < 0)
return r;
+ payload = NULL;
}
return 0;
_cleanup_strv_free_ char **files = NULL;
char **f;
struct strbuf *sb = NULL;
- _cleanup_hashmap_free_free_ Hashmap *h = 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;
STRV_FOREACH(f, files) {
log_debug("Reading file '%s'", *f);
- r = catalog_import_file(h, sb, *f);
+ r = catalog_import_file(h, *f);
if (r < 0) {
log_error_errno(r, "Failed to import file '%s': %m", *f);
goto finish;
} else
log_debug("Found %u items in catalog.", hashmap_size(h));
- strbuf_complete(sb);
-
items = new(CatalogItem, hashmap_size(h));
if (!items) {
r = log_oom();
}
n = 0;
- HASHMAP_FOREACH(i, h, j) {
+ 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);
static char *find_header(const char *s, const char *header) {
for (;;) {
- const char *v, *e;
+ const char *v;
v = startswith(s, header);
if (v) {
return strndup(v, strcspn(v, NEWLINE));
}
- /* End of text */
- e = strchr(s, '\n');
- if (!e)
+ if (!next_header(&s))
return NULL;
-
- /* End of header */
- if (e == s)
- return NULL;
-
- s = e + 1;
}
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
#include "sd-id128.h"
+
#include "hashmap.h"
#include "strbuf.h"
-int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
DEFINE_STRING_TABLE_LOOKUP(object_compressed, int);
-int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_size) {
+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,
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
return -ENOBUFS;
ret = lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL,
- src, src_size, dst, &out_pos, src_size - 1);
+ src, src_size, dst, &out_pos, dst_alloc_size);
if (ret != LZMA_OK)
return -ENOBUFS;
#endif
}
-int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, 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) {
#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
if (src_size < 9)
return -ENOBUFS;
- r = LZ4_compress_limitedOutput(src, dst + 8, src_size, src_size - 8 - 1);
+ r = LZ4_compress_limitedOutput(src, dst + 8, src_size, (int) dst_alloc_size - 8);
if (r <= 0)
return -ENOBUFS;
return -EBADMSG;
size = le64toh( *(le64_t*)src );
- if (size < 0 || (le64_t) size != *(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);
* prefix */
int r;
+ size_t size;
assert(src);
assert(src_size > 0);
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 (r < 0)
- return -EBADMSG;
- if ((unsigned) r >= prefix_len + 1)
+ if (size >= prefix_len + 1)
return memcmp(*buffer, prefix, prefix_len) == 0 &&
((const uint8_t*) *buffer)[prefix_len] == extra;
else
_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 = 0, offset = 0, frame_size;
+ size_t size, n, total_in = 0, total_out, offset = 0, frame_size;
struct stat st;
int r;
static const LZ4F_compressOptions_t options = {
if (!buf)
return -ENOMEM;
- n = offset = LZ4F_compressBegin(ctx, buf, size, &preferences);
+ n = offset = total_out = LZ4F_compressBegin(ctx, buf, size, &preferences);
if (LZ4F_isError(n))
return -EINVAL;
#endif
}
+int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
#ifdef HAVE_LZ4
-static int decompress_stream_lz4_v1(int fdf, int fdt, uint64_t max_bytes) {
-
- _cleanup_free_ char *buf = NULL, *out = NULL;
- size_t buf_size = 0;
- LZ4_streamDecode_t lz4_data = {};
- le32_t header;
- size_t total_in = sizeof(header), total_out = 0;
-
- assert(fdf >= 0);
- assert(fdt >= 0);
-
- out = malloc(4*LZ4_BUFSIZE);
- if (!out)
- return -ENOMEM;
-
- for (;;) {
- ssize_t m;
- int r;
-
- r = loop_read_exact(fdf, &header, sizeof(header), false);
- if (r < 0)
- return r;
-
- m = le32toh(header);
- if (m == 0)
- break;
-
- /* We refuse to use a bigger decompression buffer than
- * the one used for compression by 4 times. This means
- * that compression buffer size can be enlarged 4
- * times. This can be changed, but old binaries might
- * not accept buffers compressed by newer binaries then.
- */
- if (m > LZ4_COMPRESSBOUND(LZ4_BUFSIZE * 4)) {
- log_debug("Compressed stream block too big: %zd bytes", m);
- return -ENOBUFS;
- }
-
- total_in += sizeof(header) + m;
-
- if (!GREEDY_REALLOC(buf, buf_size, m))
- return -ENOMEM;
-
- r = loop_read_exact(fdf, buf, m, false);
- if (r < 0)
- return r;
-
- r = LZ4_decompress_safe_continue(&lz4_data, buf, out, m, 4*LZ4_BUFSIZE);
- if (r <= 0) {
- log_debug("LZ4 decompression failed (legacy format).");
- return -EBADMSG;
- }
-
- total_out += r;
-
- if (max_bytes != (uint64_t) -1 && (uint64_t) total_out > max_bytes) {
- log_debug("Decompressed stream longer than %" PRIu64 " bytes", max_bytes);
- return -EFBIG;
- }
-
- r = loop_write(fdt, out, r, false);
- if (r < 0)
- return r;
- }
-
- log_debug("LZ4 decompression finished (legacy format, %zu -> %zu bytes, %.1f%%)",
- total_in, total_out,
- (double) total_out / total_in * 100);
-
- return 0;
-}
-
-static int decompress_stream_lz4_v2(int in, int out, uint64_t max_bytes) {
size_t c;
_cleanup_(LZ4F_freeDecompressionContextp) LZ4F_decompressionContext_t ctx = NULL;
_cleanup_free_ char *buf = NULL;
cleanup:
munmap(src, st.st_size);
return r;
-}
-#endif
-
-int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
-#ifdef HAVE_LZ4
- int r;
-
- r = decompress_stream_lz4_v2(fdf, fdt, max_bytes);
- if (r == -EBADMSG)
- r = decompress_stream_lz4_v1(fdf, fdt, max_bytes);
- return r;
#else
log_debug("Cannot decompress file. Compiled without LZ4 support.");
return -EPROTONOSUPPORT;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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_size);
-int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
+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_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_size);
+ 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_size);
+ r = compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size);
if (r == 0)
return OBJECT_COMPRESSED_XZ;
#endif
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/statvfs.h>
-
-#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");
-}
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use);
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-#include <sys/xattr.h>
-#include <unistd.h>
-
-#ifdef HAVE_ELFUTILS
-# include <dwarf.h>
-# include <elfutils/libdwfl.h>
-#endif
-
-#include "sd-journal.h"
-#include "sd-login.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 "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 {
- INFO_PID,
- INFO_UID,
- INFO_GID,
- INFO_SIGNAL,
- INFO_TIMESTAMP,
- INFO_COMM,
- INFO_EXE,
- _INFO_LEN
-};
-
-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 *info[_INFO_LEN]) {
-
- static const char * const xattrs[_INFO_LEN] = {
- [INFO_PID] = "user.coredump.pid",
- [INFO_UID] = "user.coredump.uid",
- [INFO_GID] = "user.coredump.gid",
- [INFO_SIGNAL] = "user.coredump.signal",
- [INFO_TIMESTAMP] = "user.coredump.timestamp",
- [INFO_COMM] = "user.coredump.comm",
- [INFO_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 < _INFO_LEN; i++) {
- int k;
-
- if (isempty(info[i]) || !xattrs[i])
- continue;
-
- k = fsetxattr(fd, xattrs[i], info[i], strlen(info[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 *info[_INFO_LEN],
- uid_t uid) {
-
- assert(fd >= 0);
- assert(filename);
- assert(target);
- assert(info);
-
- /* Ignore errors on these */
- fchmod(fd, 0640);
- fix_acl(fd, uid);
- fix_xattr(fd, info);
-
- 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 *info[_INFO_LEN], char **ret) {
- _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
- sd_id128_t boot = {};
- int r;
-
- assert(info);
-
- c = filename_escape(info[INFO_COMM]);
- if (!c)
- return -ENOMEM;
-
- u = filename_escape(info[INFO_UID]);
- if (!u)
- return -ENOMEM;
-
- r = sd_id128_get_boot(&boot);
- if (r < 0)
- return r;
-
- p = filename_escape(info[INFO_PID]);
- if (!p)
- return -ENOMEM;
-
- t = filename_escape(info[INFO_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 *info[_INFO_LEN],
- uid_t uid,
- char **ret_filename,
- int *ret_fd,
- uint64_t *ret_size) {
-
- _cleanup_free_ char *fn = NULL, *tmp = NULL;
- _cleanup_close_ int fd = -1;
- struct stat st;
- int r;
-
- assert(info);
- assert(ret_filename);
- assert(ret_fd);
- assert(ret_size);
-
- r = make_filename(info, &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(STDIN_FILENO, fd, arg_process_size_max, false);
- if (r == -EFBIG) {
- log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", info[INFO_PID], info[INFO_COMM]);
- goto fail;
- } else if (IN_SET(r, -EDQUOT, -ENOSPC)) {
- log_error("Not enough disk space for coredump of %s (%s), refusing.", info[INFO_PID], info[INFO_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, info, 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_fd = fd; /* uncompressed */
- *ret_size = (uint64_t) st.st_size; /* uncompressed */
-
- fn_compressed = NULL;
- fd = -1;
-
- return 0;
-
- fail_compressed:
- unlink_noerrno(tmp_compressed);
- }
-
-uncompressed:
-#endif
- r = fix_permissions(fd, tmp, fn, info, uid);
- if (r < 0)
- goto fail;
-
- *ret_filename = fn;
- *ret_fd = fd;
- *ret_size = (uint64_t) st.st_size;
-
- fn = NULL;
- fd = -1;
-
- return 0;
-
-fail:
- unlink_noerrno(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;
-}
-
-int main(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_slice = NULL;
-
- /* The larger ones we allocate on the heap */
- _cleanup_free_ char
- *core_timestamp = NULL, *core_message = NULL, *coredump_data = NULL, *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, *filename = NULL;
- const char *info[_INFO_LEN];
-
- _cleanup_close_ int coredump_fd = -1;
-
- struct iovec iovec[26];
- uint64_t coredump_size;
- int r, j = 0;
- uid_t uid, owner_uid;
- gid_t gid;
- pid_t pid;
- char *t;
- const char *p;
-
- /* Make sure we never enter a loop */
- prctl(PR_SET_DUMPABLE, 0);
-
- /* 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();
-
- if (argc < INFO_COMM + 1) {
- log_error("Not enough arguments passed from kernel (%d, expected %d).",
- argc - 1, INFO_COMM + 1 - 1);
- r = -EINVAL;
- goto finish;
- }
-
- /* Ignore all parse errors */
- parse_config();
-
- log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
- log_debug("Selected compression %s.", yes_no(arg_compress));
-
- r = parse_uid(argv[INFO_UID + 1], &uid);
- if (r < 0) {
- log_error("Failed to parse UID.");
- goto finish;
- }
-
- r = parse_pid(argv[INFO_PID + 1], &pid);
- if (r < 0) {
- log_error("Failed to parse PID.");
- goto finish;
- }
-
- r = parse_gid(argv[INFO_GID + 1], &gid);
- if (r < 0) {
- log_error("Failed to parse GID.");
- goto finish;
- }
-
- if (get_process_comm(pid, &comm) < 0) {
- log_warning("Failed to get COMM, falling back to the command line.");
- comm = strv_join(argv + INFO_COMM + 1, " ");
- }
-
- if (get_process_exe(pid, &exe) < 0)
- log_warning("Failed to get EXE.");
-
- info[INFO_PID] = argv[INFO_PID + 1];
- info[INFO_UID] = argv[INFO_UID + 1];
- info[INFO_GID] = argv[INFO_GID + 1];
- info[INFO_SIGNAL] = argv[INFO_SIGNAL + 1];
- info[INFO_TIMESTAMP] = argv[INFO_TIMESTAMP + 1];
- info[INFO_COMM] = comm;
- info[INFO_EXE] = exe;
-
- if (cg_pid_get_unit(pid, &t) >= 0) {
-
- if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
- free(t);
-
- /* 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(info, uid, &filename, &coredump_fd, &coredump_size);
- if (r < 0)
- goto finish;
-
- r = maybe_remove_external_coredump(filename, coredump_size);
- if (r < 0)
- goto finish;
-
- log_info("Detected coredump of the journal daemon itself, diverted to %s.", filename);
- goto finish;
- }
-
- core_unit = strjoina("COREDUMP_UNIT=", t);
- free(t);
-
- } else if (cg_pid_get_user_unit(pid, &t) >= 0) {
- core_unit = strjoina("COREDUMP_USER_UNIT=", t);
- free(t);
- }
-
- if (core_unit)
- IOVEC_SET_STRING(iovec[j++], 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();
-
- core_pid = strjoina("COREDUMP_PID=", info[INFO_PID]);
- IOVEC_SET_STRING(iovec[j++], core_pid);
-
- core_uid = strjoina("COREDUMP_UID=", info[INFO_UID]);
- IOVEC_SET_STRING(iovec[j++], core_uid);
-
- core_gid = strjoina("COREDUMP_GID=", info[INFO_GID]);
- IOVEC_SET_STRING(iovec[j++], core_gid);
-
- core_signal = strjoina("COREDUMP_SIGNAL=", info[INFO_SIGNAL]);
- IOVEC_SET_STRING(iovec[j++], core_signal);
-
- if (sd_pid_get_session(pid, &t) >= 0) {
- core_session = strjoina("COREDUMP_SESSION=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], 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[j++], core_owner_uid);
- }
-
- if (sd_pid_get_slice(pid, &t) >= 0) {
- core_slice = strjoina("COREDUMP_SLICE=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], core_slice);
- }
-
- if (comm) {
- core_comm = strjoina("COREDUMP_COMM=", comm);
- IOVEC_SET_STRING(iovec[j++], core_comm);
- }
-
- if (exe) {
- core_exe = strjoina("COREDUMP_EXE=", exe);
- IOVEC_SET_STRING(iovec[j++], core_exe);
- }
-
- if (get_process_cmdline(pid, 0, false, &t) >= 0) {
- core_cmdline = strjoina("COREDUMP_CMDLINE=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], core_cmdline);
- }
-
- if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) {
- core_cgroup = strjoina("COREDUMP_CGROUP=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], 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[j++], 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[j++], 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[j++], 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[j++], 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[j++], core_proc_cgroup);
- }
-
- if (get_process_cwd(pid, &t) >= 0) {
- core_cwd = strjoina("COREDUMP_CWD=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], core_cwd);
- }
-
- if (get_process_root(pid, &t) >= 0) {
- core_root = strjoina("COREDUMP_ROOT=", t);
- free(t);
-
- IOVEC_SET_STRING(iovec[j++], core_root);
- }
-
- if (get_process_environ(pid, &t) >= 0) {
- core_environ = strappend("COREDUMP_ENVIRON=", t);
- free(t);
-
- if (core_environ)
- IOVEC_SET_STRING(iovec[j++], core_environ);
- }
-
- core_timestamp = strjoin("COREDUMP_TIMESTAMP=", info[INFO_TIMESTAMP], "000000", NULL);
- if (core_timestamp)
- IOVEC_SET_STRING(iovec[j++], core_timestamp);
-
- IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
- IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
-
- /* Vacuum before we write anything again */
- coredump_vacuum(-1, arg_keep_free, arg_max_use);
-
- /* Always stream the coredump to disk, if that's possible */
- r = save_external_coredump(info, uid, &filename, &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)
- goto finish;
- if (r == 0) {
- const char *coredump_filename;
-
- coredump_filename = strjoina("COREDUMP_FILENAME=", filename);
- IOVEC_SET_STRING(iovec[j++], coredump_filename);
- }
-
- /* Vacuum again, but exclude the coredump we just created */
- coredump_vacuum(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 = drop_privileges(uid, gid, 0);
- if (r < 0) {
- log_error_errno(r, "Failed to drop privileges: %m");
- goto finish;
- }
-
-#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, exe, &stacktrace);
- if (r >= 0)
- core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_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 ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.", NULL);
- if (core_message)
- IOVEC_SET_STRING(iovec[j++], 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[j].iov_base = coredump_data;
- iovec[j].iov_len = sz;
- j++;
- }
- }
-
- r = sd_journal_sendv(iovec, j);
- if (r < 0)
- log_error_errno(r, "Failed to log coredump: %m");
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
+++ /dev/null
-# 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=
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-#include <getopt.h>
-#include <locale.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#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_journal_close_ 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;
-}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
* Copyright (C) 2012 B. Poettering
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef __fsprgh__
#define __fsprgh__
*
*/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include "macro.h"
#include "util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "lookup3.h"
#include "parse-util.h"
#include "random-util.h"
+#include "sd-event.h"
#include "string-util.h"
#include "xattr-util.h"
if (mmap_cache_got_sigbus(f->mmap, f->fd))
return -EIO;
- switch(f->header->state) {
+ switch (f->header->state) {
case STATE_ONLINE:
return 0;
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)
safe_close(f->fd);
free(f->path);
- if (f->mmap)
- mmap_cache_unref(f->mmap);
+ mmap_cache_unref(f->mmap);
ordered_hashmap_free_free(f->chain_cache);
int r;
assert(f);
+ assert(f->header);
r = sd_id128_get_machine(&f->header->machine_id);
if (r < 0)
uint32_t flags;
assert(f);
+ assert(f->header);
if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
return -EBADMSG;
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()
uint64_t r;
assert(f);
+ assert(f->header);
r = le64toh(f->header->tail_entry_seqnum) + 1;
void *t;
assert(f);
+ assert(f->header);
assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX);
assert(size >= sizeof(ObjectHeader));
assert(offset);
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
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 */
int r;
assert(f);
+ assert(f->header);
if (f->data_hash_table)
return 0;
int r;
assert(f);
+ assert(f->header);
if (f->field_hash_table)
return 0;
int r;
assert(f);
+ assert(f->header);
+ assert(f->field_hash_table);
assert(o);
assert(offset > 0);
int r;
assert(f);
+ assert(f->header);
+ assert(f->data_hash_table);
assert(o);
assert(offset > 0);
int r;
assert(f);
+ assert(f->header);
assert(field && size > 0);
/* If the field hash table is empty, we can't find anything */
int r;
assert(f);
+ assert(f->header);
assert(data || size == 0);
/* If there's no data hash table, then there's no entry. */
if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
size_t rsize = 0;
- compression = compress_blob(data, size, o->data.payload, &rsize);
+ compression = compress_blob(data, size, o->data.payload, size - 1, &rsize);
if (compression >= 0) {
o->object.size = htole64(offsetof(Object, data.payload) + rsize);
Object *o;
assert(f);
+ assert(f->header);
assert(first);
assert(idx);
assert(p > 0);
int r;
assert(f);
+ assert(f->header);
assert(o);
assert(offset > 0);
int r;
assert(f);
+ assert(f->header);
assert(items || n_items == 0);
assert(ts);
__sync_synchronize();
if (ftruncate(f->fd, f->last_stat.st_size) < 0)
- log_error_errno(errno, "Failed to truncate file to its own size: %m");
+ 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) {
struct dual_timestamp _ts;
assert(f);
+ assert(f->header);
assert(iovec || n_iovec == 0);
if (!ts) {
ts = &_ts;
}
- if (f->tail_entry_monotonic_valid &&
- ts->monotonic < le64toh(f->header->tail_entry_monotonic))
- return -EINVAL;
-
#ifdef HAVE_GCRYPT
r = journal_file_maybe_append_tag(f, ts->realtime);
if (r < 0)
if (mmap_cache_got_sigbus(f->mmap, f->fd))
r = -EIO;
- journal_file_post_change(f);
+ if (f->post_change_timer)
+ schedule_post_change(f);
+ else
+ journal_file_post_change(f);
return r;
}
direction_t direction,
Object **ret,
uint64_t *offset) {
+ assert(f);
+ assert(f->header);
return generic_array_bisect(f,
le64toh(f->header->entry_array_offset),
direction_t direction,
Object **ret,
uint64_t *offset) {
+ assert(f);
+ assert(f->header);
return generic_array_bisect(f,
le64toh(f->header->entry_array_offset),
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);
int r;
assert(f);
+ assert(f->header);
n = le64toh(f->header->n_entries);
if (n <= 0)
uint64_t p;
assert(f);
+ assert(f->header);
journal_file_print_header(f);
char bytes[FORMAT_BYTES_MAX];
assert(f);
+ assert(f->header);
printf("File Path: %s\n"
"File ID: %s\n"
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;
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) {
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 */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-id128.h"
-#include "sparse-endian.h"
+#include "hashmap.h"
#include "journal-def.h"
#include "macro.h"
#include "mmap-cache.h"
-#include "hashmap.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" */
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)
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
#include <stdbool.h>
+#include <sys/types.h>
#include "sd-id128.h"
#include "sd-journal.h"
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;
- bool no_new_files;
- bool unique_file_lost; /* 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 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;
char *journal_make_match_string(sd_journal *j);
void journal_print_header(sd_journal *j);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_journal*, sd_journal_close);
-#define _cleanup_journal_close_ _cleanup_(sd_journal_closep)
-
#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \
for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert_return(iov, -EINVAL);
assert_return(n > 0, -EINVAL);
- w = alloca(sizeof(struct iovec) * n * 5 + 3);
- l = alloca(sizeof(uint64_t) * n);
+ w = newa(struct iovec, n * 5 + 3);
+ l = newa(uint64_t, n);
for (i = 0; i < n; i++) {
char *c, *nl;
return r;
}
- return send_one_fd(fd, buffer_fd, 0);
+ 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[]) {
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
ACTION_SYNC,
ACTION_ROTATE,
ACTION_VACUUM,
+ ACTION_LIST_FIELDS,
+ ACTION_LIST_FIELD_NAMES,
} arg_action = ACTION_SHOW;
typedef struct BootId {
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)
"\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"
{ "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 },
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:F:xrM:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0)
switch (c) {
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;
have_term = false;
} else if (path_is_absolute(*i)) {
- _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
+ _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL;
const char *path;
- _cleanup_free_ char *interpreter = NULL;
struct stat st;
p = canonicalize_file_name(*i);
- path = p ? p : *i;
+ path = p ?: *i;
if (lstat(path, &st) < 0)
return log_error_errno(errno, "Couldn't stat file: %m");
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)) {
+ if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
t2 = strappend("_EXE=", interpreter);
if (!t2)
return log_oom();
}
- } else
+ } else {
t = strappend("_EXE=", path);
- } else if (S_ISCHR(st.st_mode))
- (void) asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
- else if (S_ISBLK(st.st_mode))
- (void) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
- else {
+ 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;
}
- if (!t)
- return log_oom();
-
- r = sd_journal_add_match(j, t, 0);
- if (t2)
- r = sd_journal_add_match(j, t2, 0);
have_term = true;
-
} else {
r = sd_journal_add_match(j, *i, 0);
have_term = true;
const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
if (sd_id128_is_null(arg_boot_id))
- log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
+ log_error("Data from the specified boot (%+i) is not available: %s",
+ arg_boot_offset, reason);
else
- log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
- SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
+ 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;
}
}
static int flush_to_var(void) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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;
}
static int send_signal_and_wait(int sig, const char *watch_path) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int watch_fd = -1;
usec_t start;
int r;
/* Let's ask for a sync, but only once. */
if (!bus) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
r = bus_connect_system_systemd(&bus);
if (r < 0)
int main(int argc, char *argv[]) {
int r;
- _cleanup_journal_close_ sd_journal *j = NULL;
+ _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;
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;
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);
log_debug("Journal filter: %s", filter);
}
- if (arg_field) {
+ 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");
flags =
arg_all * OUTPUT_SHOW_ALL |
arg_full * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
+ colors_enabled() * OUTPUT_COLOR |
arg_catalog * OUTPUT_CATALOG |
arg_utc * OUTPUT_UTC;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
IOVEC_SET_STRING(iov[n_iov++], id_field);
- assert_cc(32 == LOG_AUTH);
- IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=32");
+ 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "socket-util.h"
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/* Did we lose any? */
if (serial > *s->kernel_seqnum)
- server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages",
- 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return log_error_errno(errno, "SO_PASSCRED failed: %m");
#ifdef HAVE_SELINUX
- if (mac_selinux_use()) {
+ 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");
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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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 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,
sum += (uint64_t) st.st_blocks * 512UL;
}
- /* If request, then let's bump the min_use limit to the
+ /* 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
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,
- "%s (%s) is currently using %s.\n"
- "Maximum allowed usage is set to %s.\n"
- "Leaving at least %s free (of currently available %s of space).\n"
- "Enforced usage limit is thus %s, of which %s are still available.",
- name, path,
- 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));
+ 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)
return determine_space_for(s, metrics, path, name, verbose, patch_min_use, available, limit);
}
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
- int r;
+static void server_add_acls(JournalFile *f, uid_t uid) {
#ifdef HAVE_ACL
- _cleanup_(acl_freep) acl_t acl = NULL;
- acl_entry_t entry;
- acl_permset_t permset;
+ int r;
#endif
-
assert(f);
- r = fchmod(f->fd, 0640);
- if (r < 0)
- log_warning_errno(errno, "Failed to fix access mode on %s, ignoring: %m", f->path);
-
#ifdef HAVE_ACL
if (uid <= SYSTEM_UID_MAX)
return;
- acl = acl_get_fd(f->fd);
- if (!acl) {
- log_warning_errno(errno, "Failed to read ACL on %s, ignoring: %m", f->path);
- 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
+}
- r = acl_find_uid(acl, uid, &entry);
- if (r <= 0) {
+static int open_journal(
+ Server *s,
+ bool reliably,
+ const char *fname,
+ int flags,
+ bool seal,
+ JournalMetrics *metrics,
+ JournalFile **ret) {
+ int r;
+ JournalFile *f;
- if (acl_create_entry(&acl, &entry) < 0 ||
- acl_set_tag_type(entry, ACL_USER) < 0 ||
- acl_set_qualifier(entry, &uid) < 0) {
- log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
- return;
- }
- }
+ assert(s);
+ assert(fname);
+ assert(ret);
- /* 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) {
- log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
- return;
- }
+ 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 = calc_acl_mask_if_needed(&acl);
+ r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
if (r < 0) {
- log_warning_errno(r, "Failed to patch ACL on %s, ignoring: %m", f->path);
- return;
+ journal_file_close(f);
+ return r;
}
- if (acl_set_fd(f->fd, acl) < 0)
- log_warning_errno(errno, "Failed to set ACL on %s, ignoring: %m", f->path);
-
-#endif
+ *ret = f;
+ return r;
}
static JournalFile* find_journal(Server *s, uid_t uid) {
journal_file_close(f);
}
- r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &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_fix_perms(s, f, uid);
+ server_add_acls(f, uid);
r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f);
if (r < 0) {
else
log_error_errno(r, "Failed to create new %s journal: %m", name);
else
- server_fix_perms(s, *f, uid);
+ server_add_acls(*f, uid);
return r;
}
}
#ifdef HAVE_SELINUX
- if (mac_selinux_use()) {
+ if (mac_selinux_have()) {
if (label) {
x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
char mid[11 + 32 + 1];
- char buffer[16 + LINE_MAX + 1];
- struct iovec iovec[N_IOVEC_META_FIELDS + 6];
- int n = 0;
+ 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++], "PRIORITY=6");
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
-
- memcpy(buffer, "MESSAGE=", 8);
- va_start(ap, format);
- vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
- va_end(ap);
- IOVEC_SET_STRING(iovec[n++], buffer);
+ 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();
- dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
+ 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(
/* Write a suppression message if we suppressed something */
if (rl > 1)
server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
- "Suppressed %u messages from %s", rl - 1, path);
+ 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);
(void) mkdir(fn, 0755);
fn = strjoina(fn, "/system.journal");
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+ r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal);
if (r >= 0) {
- server_fix_perms(s, s->system_journal, 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)
* if it already exists, so that we can flush
* it into the system journal */
- r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_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");
(void) mkdir("/run/log/journal", 0755);
(void) mkdir_parents(fn, 0750);
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+ 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_fix_perms(s, s->runtime_journal, 0);
+ server_add_acls(s->runtime_journal, 0);
(void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL);
}
}
sd_journal_close(j);
- server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n);
+ 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;
}
p = line;
for(;;) {
- _cleanup_free_ char *word;
+ _cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#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,4);
+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);
const char *split_mode_to_string(SplitMode s) _const_;
SplitMode split_mode_from_string(const char *s) _pure_;
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid);
int server_init(Server *s);
void server_done(Server *s);
void server_sync(Server *s);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(s);
assert(p);
- if (isempty(p))
- return 0;
-
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);
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) {
return 0;
case STDOUT_STREAM_RUNNING:
- return stdout_stream_log(s, p);
+ return stdout_stream_log(s, orig);
}
assert_not_reached("Unknown stream state");
if (r < 0)
return log_error_errno(r, "Failed to determine peer credentials: %m");
- if (mac_selinux_use()) {
+ 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");
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+10);
+ 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");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
size_t label_len) {
char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
- syslog_facility[sizeof("SYSLOG_FACILITY") + 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;
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
- sprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
+ xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
IOVEC_SET_STRING(iovec[n++], syslog_priority);
if (priority & LOG_FACMASK) {
- sprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
+ xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
IOVEC_SET_STRING(iovec[n++], syslog_facility);
}
return log_error_errno(errno, "SO_PASSCRED failed: %m");
#ifdef HAVE_SELINUX
- if (mac_selinux_use()) {
+ 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");
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;
}
if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n)
return;
- server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed);
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
server_flush_dev_kmsg(&server);
log_debug("systemd-journald running as pid "PID_FMT, getpid());
- server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
+ server_driver_message(&server, SD_MESSAGE_JOURNAL_START,
+ LOG_MESSAGE("Journal started"),
+ NULL);
for (;;) {
usec_t t = USEC_INFINITY, n;
}
log_debug("systemd-journald stopped as pid "PID_FMT, getpid());
- server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
+ server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP,
+ LOG_MESSAGE("Journal stopped"),
+ NULL);
finish:
server_done(&server);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
#include <inttypes.h>
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
struct Window {
MMapCache *cache;
- bool invalidated;
- bool keep_always;
- bool in_unused;
+ bool invalidated:1;
+ bool keep_always:1;
+ bool in_unused:1;
int prot;
void *ptr;
unsigned n_hit, n_missed;
-
Hashmap *fds;
Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
offset + size <= w->offset + w->size;
}
-static Window *window_add(MMapCache *m) {
+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) {
}
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;
}
}
MMapCache* mmap_cache_unref(MMapCache *m) {
- assert(m);
+
+ if (!m)
+ return NULL;
+
assert(m->n_ref > 0);
m->n_ref --;
if (c->window->fd->sigbus)
return -EIO;
- c->window->keep_always |= keep_always;
+ c->window->keep_always = c->window->keep_always || keep_always;
*ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
return 1;
return -ENOMEM;
context_attach_window(c, w);
- w->keep_always += keep_always;
+ 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,
wsize = PAGE_ALIGN(st->st_size - woffset);
}
- for (;;) {
- d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
- if (d != MAP_FAILED)
- break;
- if (errno != ENOMEM)
- return -errno;
-
- r = make_room(m);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOMEM;
- }
+ 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)
if (!f)
goto outofmem;
- w = window_add(m);
+ w = window_add(m, f, prot, keep_always, woffset, wsize, d);
if (!w)
goto outofmem;
- w->keep_always = keep_always;
- w->ptr = d;
- w->offset = woffset;
- w->prot = prot;
- w->size = wsize;
- w->fd = f;
-
- LIST_PREPEND(by_fd, f->windows, w);
-
context_detach_window(c);
c->window = w;
LIST_PREPEND(by_window, w->contexts, c);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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);
}
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 ++;
free(j->path);
free(j->prefix);
free(j->unique_field);
+ free(j->fields_buffer);
free(j);
}
compression = o->object.flags & OBJECT_COMPRESSION_MASK;
if (compression) {
#if defined(HAVE_XZ) || defined(HAVE_LZ4)
- if (decompress_startswith(compression,
+ r = decompress_startswith(compression,
o->data.payload, l,
&f->compress_buffer, &f->compress_buffer_size,
- field, field_length, '=')) {
+ 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;
* traversed files. */
found = false;
ORDERED_HASHMAP_FOREACH(of, j->files, i) {
- Object *oo;
- uint64_t op;
-
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)
+ /* 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), &oo, &op);
+ 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)
+ if (r > 0) {
found = true;
+ break;
+ }
}
if (found)
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);
*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;
+}
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <dwarf.h>
-#include <elfutils/libdwfl.h>
-
-#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;
-}
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#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 <http://www.gnu.org/licenses/>.
-***/
-
-int coredump_make_stack_trace(int fd, const char *executable, char **ret);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
NULL
};
-static void test_import(Hashmap *h, struct strbuf *sb,
- const char* contents, ssize_t size, int code) {
+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, sb, name);
+ r = catalog_import_file(h, name);
assert_se(r == code);
unlink(name);
+
+ return h;
}
-static void test_catalog_importing(void) {
- Hashmap *h;
- struct strbuf *sb;
+static void test_catalog_import_invalid(void) {
+ _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
- assert_se(h = hashmap_new(&catalog_hash_ops));
- assert_se(sb = strbuf_new());
-
-#define BUF "xxx"
- test_import(h, sb, BUF, sizeof(BUF), -EINVAL);
-#undef BUF
+ h = test_import("xxx", -1, -EINVAL);
assert_se(hashmap_isempty(h));
- log_debug("----------------------------------------");
+}
-#define BUF \
+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"
- test_import(h, sb, BUF, sizeof(BUF), -EINVAL);
-#undef BUF
+"payload\n";
+ h = test_import(input, -1, -EINVAL);
+}
- log_debug("----------------------------------------");
+static void test_catalog_import_one(void) {
+ _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
+ char *payload;
+ Iterator j;
-#define BUF \
+ const char *input =
"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
"Subject: message\n" \
"\n" \
-"payload\n"
- test_import(h, sb, BUF, sizeof(BUF), 0);
-#undef BUF
+"payload\n";
+ const char *expect =
+"Subject: message\n" \
+"\n" \
+"payload\n";
+ h = test_import(input, -1, 0);
assert_se(hashmap_size(h) == 1);
- log_debug("----------------------------------------");
+ 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_free_free(h);
- strbuf_cleanup(sb);
+ 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;
test_catalog_file_lang();
- test_catalog_importing();
+ 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();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd
#include "string-util.h"
#include "util.h"
-typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
+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);
memzero(buf, MIN(size + 1000, MAX_SIZE));
- r = compress(text, size, buf, &j);
- /* assume compression must be successful except for small inputs */
+ 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 */
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#ifdef HAVE_LZ4
+#include <lz4.h>
+#endif
+
#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
#endif
typedef int (compress_blob_t)(const void *src, uint64_t src_size,
- void *dst, size_t *dst_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);
size_t data_len,
bool may_fail) {
char compressed[512];
- size_t csize = 512;
- size_t usize = 0;
+ 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, &csize);
+ r = compress(data, data_len, compressed, sizeof(compressed), &csize);
if (r == -ENOBUFS) {
log_info_errno(r, "compression failed: %m");
assert_se(may_fail);
size_t data_len,
bool may_fail) {
- char compressed[512];
- size_t csize = 512;
- size_t usize = 0;
- _cleanup_free_ char *decompressed = NULL;
+ 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 %s text*/",
+ log_info("/* testing decompress_startswith with %s on %.20s text*/",
object_compressed_to_string(compression), data);
- r = compress(data, data_len, compressed, &csize);
+#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);
- return;
+
+ compressed = compressed2 = malloc(BUFSIZE_2);
+ assert_se(compressed2);
+ r = compress(data, data_len, compressed, BUFSIZE_2, &csize);
+ assert(r == 0);
}
assert_se(r == 0);
- assert_se(decompress_sw(compressed,
- csize,
- (void **) &decompressed,
- &usize,
- data, strlen(data), '\0') > 0);
- assert_se(decompress_sw(compressed,
- csize,
- (void **) &decompressed,
- &usize,
- data, strlen(data), 'w') == 0);
- assert_se(decompress_sw(compressed,
- csize,
- (void **) &decompressed,
- &usize,
- "barbarbar", 9, ' ') == 0);
- assert_se(decompress_sw(compressed,
- csize,
- (void **) &decompressed,
- &usize,
- data, strlen(data), '\0') > 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,
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"
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);
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
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
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-
-#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;
-}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int main(int argc, char *argv[]) {
unsigned n = 0;
- _cleanup_journal_close_ sd_journal*j = NULL;
+ _cleanup_(sd_journal_closep) sd_journal*j = NULL;
log_set_max_level(LOG_DEBUG);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "util.h"
int main(int argc, char *argv[]) {
- _cleanup_journal_close_ sd_journal*j;
+ _cleanup_(sd_journal_closep) sd_journal*j = NULL;
_cleanup_free_ char *t;
log_set_max_level(LOG_DEBUG);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include "sd-journal.h"
-#include "log.h"
+#include "macro.h"
int main(int argc, char *argv[]) {
char huge[4096*1024];
- log_set_max_level(LOG_DEBUG);
-
- sd_journal_print(LOG_INFO, "piepapo");
-
- sd_journal_send("MESSAGE=foobar",
- "VALUE=%i", 7,
- NULL);
+ /* 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;
- sd_journal_perror("Foobar");
+ assert_se(sd_journal_perror("Foobar") == 0);
- sd_journal_perror("");
+ assert_se(sd_journal_perror("") == 0);
memset(huge, 'x', sizeof(huge));
memcpy(huge, "HUGE=", 5);
char_array_0(huge);
- sd_journal_send("MESSAGE=Huge field attached",
- huge,
- NULL);
+ assert_se(sd_journal_send("MESSAGE=Huge field attached",
+ huge,
+ NULL) == 0);
- 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);
+ 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!");
- sd_journal_print(LOG_NOTICE, "Hello World");
-
- 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);
+ 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
JournalFile *one, *two, *three;
char t[] = "/tmp/journal-stream-XXXXXX";
unsigned i;
- _cleanup_journal_close_ sd_journal *j = NULL;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
char *z;
const void *data;
size_t l;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <netinet/if_ether.h>
-#include "sparse-endian.h"
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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);
+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,
int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_client*, sd_dhcp_client_unref);
-#define _cleanup_dhcp_client_unref_ _cleanup_(sd_dhcp_client_unrefp)
-
/* 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_dhcp_client_unref_ _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(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__)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdint.h>
#include <linux/if_packet.h>
-#include "util.h"
-#include "list.h"
+#include "sd-dhcp-client.h"
#include "dhcp-protocol.h"
-
-#include "sd-dhcp-client.h"
+#include "list.h"
+#include "util.h"
struct sd_dhcp_route {
struct in_addr dst_addr;
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
-#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <stdio.h>
#include <string.h>
+#include "alloc-util.h"
+#include "utf8.h"
+
#include "dhcp-internal.h"
static int option_append(uint8_t options[], size_t size, size_t *offset,
assert(options);
assert(offset);
- if (code != DHCP_OPTION_END)
+ if (code != SD_DHCP_OPTION_END)
/* always make sure there is space for an END option */
size --;
switch (code) {
- case DHCP_OPTION_PAD:
- case DHCP_OPTION_END:
+ case SD_DHCP_OPTION_PAD:
+ case SD_DHCP_OPTION_END:
if (size < *offset + 1)
return -ENOBUFS;
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, DHCP_OPTION_END, 0, NULL);
+ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
} 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, DHCP_OPTION_END, 0, NULL);
+ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
}
static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
- uint8_t *message_type, dhcp_option_cb_t cb,
+ 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) {
- switch (options[offset]) {
- case DHCP_OPTION_PAD:
- offset++;
+ code = options[offset ++];
- break;
+ switch (code) {
+ case SD_DHCP_OPTION_PAD:
+ continue;
- case DHCP_OPTION_END:
+ case SD_DHCP_OPTION_END:
return 0;
+ }
+
+ if (buflen < offset + 1)
+ return -ENOBUFS;
+
+ len = options[offset ++];
- case DHCP_OPTION_MESSAGE_TYPE:
- if (buflen < offset + 3)
- return -ENOBUFS;
+ if (buflen < offset + len)
+ return -EINVAL;
- len = options[++offset];
+ option = &options[offset];
+
+ switch (code) {
+ case SD_DHCP_OPTION_MESSAGE_TYPE:
if (len != 1)
return -EINVAL;
if (message_type)
- *message_type = options[++offset];
- else
- offset++;
-
- offset++;
+ *message_type = *option;
break;
- case DHCP_OPTION_OVERLOAD:
- if (buflen < offset + 3)
- return -ENOBUFS;
-
- len = options[++offset];
- if (len != 1)
+ case SD_DHCP_OPTION_ERROR_MESSAGE:
+ if (len == 0)
return -EINVAL;
- if (overload)
- *overload = options[++offset];
- else
- offset++;
+ if (error_message) {
+ _cleanup_free_ char *string = NULL;
- offset++;
+ /* Accept a trailing NUL byte */
+ if (memchr(option, 0, len - 1))
+ return -EINVAL;
- break;
+ string = strndup((const char *) option, len);
+ if (!string)
+ return -ENOMEM;
- default:
- if (buflen < offset + 3)
- return -ENOBUFS;
+ if (!ascii_is_valid(string))
+ return -EINVAL;
- code = options[offset];
- len = options[++offset];
+ free(*error_message);
+ *error_message = string;
+ string = NULL;
+ }
- if (buflen < ++offset + len)
+ break;
+ case SD_DHCP_OPTION_OVERLOAD:
+ if (len != 1)
return -EINVAL;
- if (cb)
- cb(code, len, &options[offset], userdata);
+ if (overload)
+ *overload = *option;
- offset += len;
+ break;
+
+ default:
+ if (cb)
+ cb(code, len, option, userdata);
break;
}
+
+ offset += len;
}
if (offset < buflen)
return 0;
}
-int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *userdata) {
+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;
len -= sizeof(DHCPMessage);
- r = parse_options(message->options, len, &overload, &message_type,
- cb, userdata);
+ 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, cb, userdata);
+ 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, cb, userdata);
+ r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata);
if (r < 0)
return r;
}
- if (message_type)
- return message_type;
+ 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 -ENOMSG;
+ return message_type;
}
message->magic = htobe32(DHCP_MAGIC_COOKIE);
r = dhcp_option_append(message, optlen, &offset, 0,
- DHCP_OPTION_MESSAGE_TYPE, 1, &type);
+ SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
if (r < 0)
return r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/udp.h>
#include <netinet/ip.h>
+#include <netinet/udp.h>
#include <stdint.h>
#include "macro.h"
DHCP_OVERLOAD_SNAME = 2,
};
+#define DHCP_MAX_FQDN_LENGTH 255
+
enum {
- DHCP_OPTION_PAD = 0,
- DHCP_OPTION_SUBNET_MASK = 1,
- DHCP_OPTION_TIME_OFFSET = 2,
- DHCP_OPTION_ROUTER = 3,
- DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
- DHCP_OPTION_HOST_NAME = 12,
- DHCP_OPTION_BOOT_FILE_SIZE = 13,
- DHCP_OPTION_DOMAIN_NAME = 15,
- DHCP_OPTION_ROOT_PATH = 17,
- DHCP_OPTION_ENABLE_IP_FORWARDING = 19,
- DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20,
- DHCP_OPTION_POLICY_FILTER = 21,
- DHCP_OPTION_INTERFACE_MDR = 22,
- DHCP_OPTION_INTERFACE_TTL = 23,
- DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
- DHCP_OPTION_INTERFACE_MTU = 26,
- DHCP_OPTION_BROADCAST = 28,
- DHCP_OPTION_STATIC_ROUTE = 33,
- DHCP_OPTION_NTP_SERVER = 42,
- DHCP_OPTION_VENDOR_SPECIFIC = 43,
- DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
- DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
- DHCP_OPTION_OVERLOAD = 52,
- DHCP_OPTION_MESSAGE_TYPE = 53,
- DHCP_OPTION_SERVER_IDENTIFIER = 54,
- DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
- DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57,
- DHCP_OPTION_RENEWAL_T1_TIME = 58,
- DHCP_OPTION_REBINDING_T2_TIME = 59,
- DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
- DHCP_OPTION_CLIENT_IDENTIFIER = 61,
- DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
- DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
- DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
- DHCP_OPTION_PRIVATE_BASE = 224,
- DHCP_OPTION_PRIVATE_LAST = 254,
- DHCP_OPTION_END = 255,
+ DHCP_FQDN_FLAG_S = (1 << 0),
+ DHCP_FQDN_FLAG_O = (1 << 1),
+ DHCP_FQDN_FLAG_E = (1 << 2),
+ DHCP_FQDN_FLAG_N = (1 << 3),
};
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#pragma once
-#include "sd-event.h"
#include "sd-dhcp-server.h"
+#include "sd-event.h"
+#include "dhcp-internal.h"
#include "hashmap.h"
-#include "util.h"
#include "log.h"
-
-#include "dhcp-internal.h"
+#include "util.h"
typedef struct DHCPClientId {
size_t length;
uint32_t lifetime;
} DHCPRequest;
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_server*, sd_dhcp_server_unref);
-#define _cleanup_dhcp_server_unref_ _cleanup_(sd_dhcp_server_unrefp)
-
#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,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdint.h>
#include "sd-dhcp6-lease.h"
+
#include "dhcp6-internal.h"
struct sd_dhcp6_lease {
size_t optlen) ;
int dhcp6_lease_new(sd_dhcp6_lease **ret);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
-#define _cleanup_dhcp6_lease_free_ _cleanup_(sd_dhcp6_lease_unrefp)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <netinet/in.h>
#include <string.h>
+#include "sd-dhcp6-client.h"
+
#include "alloc-util.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
assert_return(buf && *buf && buflen && ia, -EINVAL);
switch (ia->type) {
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
len = DHCP6_OPTION_IA_NA_LEN;
break;
- case DHCP6_OPTION_IA_TA:
+ case SD_DHCP6_OPTION_IA_TA:
len = DHCP6_OPTION_IA_TA_LEN;
break;
*buflen -= len;
LIST_FOREACH(addresses, addr, ia->addresses) {
- r = option_append_hdr(buf, buflen, DHCP6_OPTION_IAADDR,
+ r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR,
sizeof(addr->iaaddr));
if (r < 0)
return r;
assert_return(!ia->addresses, -EINVAL);
switch (iatype) {
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) {
break;
- case DHCP6_OPTION_IA_TA:
+ case SD_DHCP6_OPTION_IA_TA:
if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) {
r = -ENOBUFS;
while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) {
switch (opt) {
- case DHCP6_OPTION_IAADDR:
+ case SD_DHCP6_OPTION_IAADDR:
addr = new0(DHCP6Address, 1);
if (!addr) {
break;
- case DHCP6_OPTION_STATUS_CODE:
+ case SD_DHCP6_OPTION_STATUS_CODE:
if (optlen < sizeof(status))
break;
/* End of name */
break;
else if (c <= 63) {
- _cleanup_free_ char *t = NULL;
const char *label;
/* Literal label */
if (pos > optlen)
return -EMSGSIZE;
- r = dns_label_escape(label, c, &t);
- if (r < 0)
- goto fail;
-
- if (!GREEDY_REALLOC0(ret, allocated, n + !first + strlen(t) + 1)) {
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
r = -ENOMEM;
goto fail;
}
- if (!first)
- ret[n++] = '.';
- else
+ if (first)
first = false;
+ else
+ ret[n++] = '.';
+
+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ goto fail;
- memcpy(ret + n, t, r);
n += r;
continue;
} else {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
_DHCP6_MESSAGE_MAX = 14,
};
-enum {
- DHCP6_OPTION_CLIENTID = 1,
- DHCP6_OPTION_SERVERID = 2,
- DHCP6_OPTION_IA_NA = 3,
- DHCP6_OPTION_IA_TA = 4,
- DHCP6_OPTION_IAADDR = 5,
- DHCP6_OPTION_ORO = 6,
- DHCP6_OPTION_PREFERENCE = 7,
- DHCP6_OPTION_ELAPSED_TIME = 8,
- DHCP6_OPTION_RELAY_MSG = 9,
- /* option code 10 is unassigned */
- DHCP6_OPTION_AUTH = 11,
- DHCP6_OPTION_UNICAST = 12,
- DHCP6_OPTION_STATUS_CODE = 13,
- DHCP6_OPTION_RAPID_COMMIT = 14,
- DHCP6_OPTION_USER_CLASS = 15,
- DHCP6_OPTION_VENDOR_CLASS = 16,
- DHCP6_OPTION_VENDOR_OPTS = 17,
- DHCP6_OPTION_INTERFACE_ID = 18,
- DHCP6_OPTION_RECONF_MSG = 19,
- DHCP6_OPTION_RECONF_ACCEPT = 20,
-
- DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
- DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
-
- DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
-
- /* option code 35 is unassigned */
-
- DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */
-
- /* option codes 89-142 are unassigned */
- /* option codes 144-65535 are unassigned */
-};
-
enum {
DHCP6_NTP_SUBOPTION_SRV_ADDR = 1,
DHCP6_NTP_SUBOPTION_MC_ADDR = 2,
.ipv6mr_interface = index,
};
_cleanup_close_ int s = -1;
- int r, zero = 0, hops = 255;
+ int r, zero = 0, one = 1, hops = 255;
- s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
- IPPROTO_ICMPV6);
+ 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));
+ r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
if (r < 0)
return -errno;
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));
+ 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));
+ 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));
+ 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));
+ 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;
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[1] = {
- { &rs, },
+ struct iovec iov = {
+ .iov_base = &rs,
+ .iov_len = sizeof(rs),
};
struct msghdr msg = {
.msg_name = &dst,
.msg_namelen = sizeof(dst),
- .msg_iov = iov,
+ .msg_iov = &iov,
.msg_iovlen = 1,
};
int r;
- if (ether_addr) {
- memcpy(&rs.rs_opt_mac, ether_addr, ETH_ALEN);
- rs.rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
- rs.rs_opt.nd_opt_len = 1;
- iov[0].iov_len = sizeof(rs);
- } else
- iov[0].iov_len = sizeof(rs.rs);
+ assert(s >= 0);
+ assert(ether_addr);
+
+ rs.rs_opt_mac = *ether_addr;
r = sendmsg(s, &msg, 0);
if (r < 0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_lldp_packet_unref_ tlv_packet *packet = NULL;
+ _cleanup_(sd_lldp_packet_unrefp) tlv_packet *packet = NULL;
tlv_packet *p;
uint16_t length;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <net/ethernet.h>
-#include "util.h"
-#include "lldp.h"
-#include "list.h"
-
#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;
int tlv_packet_new(tlv_packet **ret);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_lldp_packet*, sd_lldp_packet_unref);
-#define _cleanup_lldp_packet_unref_ _cleanup_(sd_lldp_packet_unrefp)
-
int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type);
int lldp_tlv_packet_close_container(tlv_packet *m);
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#pragma once
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_lldp *, sd_lldp_free);
-#define _cleanup_lldp_free_ _cleanup_(sd_lldp_freep)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return size;
}
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
+void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
unsigned i;
assert(f);
fprintf(f, "%s=", key);
for (i = 0; i < size; i++) {
- fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
- routes[i].dst_prefixlen);
- fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
- (i < (size - 1)) ? " ": "");
+ 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
-#include "udev.h"
+#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,
/* 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, struct sd_dhcp_route *routes, size_t size);
+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);
#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;
sd_dhcp_client_cb_t cb;
void *userdata;
sd_dhcp_lease *lease;
+ usec_t start_delay;
};
static const uint8_t default_req_opts[] = {
- DHCP_OPTION_SUBNET_MASK,
- DHCP_OPTION_ROUTER,
- DHCP_OPTION_HOST_NAME,
- DHCP_OPTION_DOMAIN_NAME,
- DHCP_OPTION_DOMAIN_NAME_SERVER,
+ 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,
DHCP_STATE_STOPPED), -EBUSY);
switch(option) {
- case DHCP_OPTION_PAD:
- case DHCP_OPTION_OVERLOAD:
- case DHCP_OPTION_MESSAGE_TYPE:
- case DHCP_OPTION_PARAMETER_REQUEST_LIST:
- case DHCP_OPTION_END:
+ 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:
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;
Identifier option is not set */
if (client->client_id_len) {
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_CLIENT_IDENTIFIER,
+ SD_DHCP_OPTION_CLIENT_IDENTIFIER,
client->client_id_len,
&client->client_id);
if (r < 0)
messages.
*/
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_PARAMETER_REQUEST_LIST,
+ SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
client->req_opts_size, client->req_opts);
if (r < 0)
return r;
*/
max_size = htobe16(size);
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
- DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
+ SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
2, &max_size);
if (r < 0)
return r;
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,
*/
if (client->last_addr != INADDR_ANY) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
+ SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr);
if (r < 0)
return r;
}
- /* it is unclear from RFC 2131 if client should send hostname in
- DHCPDISCOVER but dhclient does and so we do as well
- */
if (client->hostname) {
- r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_HOST_NAME,
- strlen(client->hostname), 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,
- DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
+ SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
strlen(client->vendor_class_identifier),
client->vendor_class_identifier);
if (r < 0)
}
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_END, 0, NULL);
+ SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
*/
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_SERVER_IDENTIFIER,
+ SD_DHCP_OPTION_SERVER_IDENTIFIER,
4, &client->lease->server_address);
if (r < 0)
return r;
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
+ SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->lease->address);
if (r < 0)
return r;
assigned address. ’ciaddr’ MUST be zero.
*/
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
+ SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr);
if (r < 0)
return r;
}
if (client->hostname) {
- r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_HOST_NAME,
- strlen(client->hostname), 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,
- DHCP_OPTION_END, 0, NULL);
+ SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
}
static int client_initialize_time_events(sd_dhcp_client *client) {
+ uint64_t usec = 0;
int r;
assert(client);
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(),
- 0, 0,
+ usec, 0,
client_timeout_resend, client);
if (r < 0)
goto error;
return 0;
}
-static int client_start(sd_dhcp_client *client) {
+static int client_start_delayed(sd_dhcp_client *client) {
int r;
assert_return(client, -EINVAL);
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;
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
size_t len) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+ _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
int r;
r = dhcp_lease_new(&lease);
return r;
}
- r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
+ 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;
size_t len) {
int r;
- r = dhcp_option_parse(force, len, NULL, NULL);
+ r = dhcp_option_parse(force, len, NULL, NULL, NULL);
if (r != DHCP_FORCERENEW)
return -ENOMSG;
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
size_t len) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+ _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
+ _cleanup_free_ char *error_message = NULL;
int r;
r = dhcp_lease_new(&lease);
return r;
}
- r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
+ r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
if (r == DHCP_NAK) {
- log_dhcp_client(client, "NAK");
+ log_dhcp_client(client, "NAK: %s", strna(error_message));
return -EADDRNOTAVAIL;
}
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);
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 =
if (r < 0)
goto error;
- r = client_start(client);
+ r = client_start_delayed(client);
if (r < 0)
goto error;
- log_dhcp_client(client, "REBOOTED");
+ 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)
r = ioctl(fd, FIONREAD, &buflen);
if (r < 0)
- return r;
-
- if (buflen < 0)
+ return -errno;
+ else if (buflen < 0)
/* this can't be right */
return -EIO;
len = read(fd, message, buflen);
if (len < 0) {
- log_dhcp_client(client, "could not receive message from UDP "
- "socket: %m");
- return 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");
+ 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");
+ log_dhcp_client(client, "Not a DHCP message: ignoring");
return 0;
}
if (message->op != BOOTREPLY) {
- log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
+ 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");
+ log_dhcp_client(client, "Packet type does not match client type");
return 0;
}
}
if (message->hlen != expected_hlen) {
- log_dhcp_client(client, "unexpected packet hlen %d", message->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");
+ log_dhcp_client(client, "Received chaddr does not match expected: ignoring");
return 0;
}
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",
+ log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring",
be32toh(message->xid), client->xid);
return 0;
}
r = ioctl(fd, FIONREAD, &buflen);
if (r < 0)
- return r;
-
- if (buflen < 0)
+ return -errno;
+ else if (buflen < 0)
/* this can't be right */
return -EIO;
len = recvmsg(fd, &msg, 0);
if (len < 0) {
- log_dhcp_client(client, "could not receive message from raw "
- "socket: %m");
- return 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;
}
int sd_dhcp_client_new(sd_dhcp_client **ret) {
- _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
+ _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
assert_return(ret, -EINVAL);
#include "in-addr-util.h"
#include "network-internal.h"
#include "parse-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "unaligned.h"
return 0;
}
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
+/*
+ * 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;
- *routes = lease->static_route;
+ 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;
}
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);
if (len < 4)
return -EINVAL;
- lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+ assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
option += 4;
len -= 4;
switch(code) {
- case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
+ 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 DHCP_OPTION_SERVER_IDENTIFIER:
+ 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 DHCP_OPTION_SUBNET_MASK:
+ 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");
lease->have_subnet_mask = true;
break;
- case DHCP_OPTION_BROADCAST:
+ 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");
lease->have_broadcast = true;
break;
- case DHCP_OPTION_ROUTER:
+ case SD_DHCP_OPTION_ROUTER:
if (len >= 4) {
r = lease_parse_be32(option, 4, &lease->router);
if (r < 0)
}
break;
- case DHCP_OPTION_DOMAIN_NAME_SERVER:
+ 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 DHCP_OPTION_NTP_SERVER:
+ 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 DHCP_OPTION_STATIC_ROUTE:
+ 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 DHCP_OPTION_INTERFACE_MTU:
+ 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 DHCP_OPTION_DOMAIN_NAME: {
- _cleanup_free_ char *domainname = NULL, *normalized = NULL;
-
- r = lease_parse_string(option, len, &domainname);
+ 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;
}
- r = dns_name_normalize(domainname, &normalized);
- if (r < 0) {
- log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
- return 0;
- }
-
- if (is_localhost(normalized)) {
- log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
- break;
- }
-
- free(lease->domainname);
- lease->domainname = normalized;
- normalized = NULL;
-
break;
- }
-
- case DHCP_OPTION_HOST_NAME: {
- _cleanup_free_ char *hostname = NULL, *normalized = NULL;
- r = lease_parse_string(option, len, &hostname);
+ 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;
}
- r = dns_name_normalize(hostname, &normalized);
- if (r < 0) {
- log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
- return 0;
- }
-
- if (is_localhost(normalized)) {
- log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
- return 0;
- }
-
- free(lease->hostname);
- lease->hostname = normalized;
- normalized = NULL;
-
break;
- }
- case DHCP_OPTION_ROOT_PATH:
+ 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 DHCP_OPTION_RENEWAL_T1_TIME:
+ 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 DHCP_OPTION_REBINDING_T2_TIME:
+ 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 DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+ case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
r = lease_parse_classless_routes(
option, len,
&lease->static_route,
log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
break;
- case DHCP_OPTION_NEW_TZDB_TIMEZONE: {
+ case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: {
_cleanup_free_ char *tz = NULL;
r = lease_parse_string(option, len, &tz);
break;
}
- case DHCP_OPTION_VENDOR_SPECIFIC:
+ case SD_DHCP_OPTION_VENDOR_SPECIFIC:
if (len <= 0)
lease->vendor_specific = mfree(lease->vendor_specific);
lease->vendor_specific_len = len;
break;
- case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST:
+ 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 %i while parsing.", code);
+ log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code);
break;
}
size_t client_id_len, data_len;
const char *string;
uint16_t mtu;
- struct sd_dhcp_route *routes;
+ _cleanup_free_ sd_dhcp_route **routes = NULL;
uint32_t t1, t2, lifetime;
int r;
LIST_FOREACH(options, option, lease->private_options) {
char key[strlen("OPTION_000")+1];
- snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag);
+ xsprintf(key, "OPTION_%" PRIu8, option->tag);
r = serialize_dhcp_option(f, key, option->data, option->length);
if (r < 0)
goto fail;
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
- _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+ _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
_cleanup_free_ char
*address = NULL,
*router = NULL,
*lifetime = NULL,
*t1 = NULL,
*t2 = NULL,
- *options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {};
+ *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {};
int r, i;
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
}
- for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) {
+ for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
_cleanup_free_ void *data = NULL;
size_t len;
continue;
}
- r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len);
+ r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
if (r < 0)
return r;
}
*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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
- _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+ _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
assert_return(ret, -EINVAL);
assert_return(ifindex > 0, -EINVAL);
assert(packet);
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
- DHCP_OPTION_SERVER_IDENTIFIER,
+ SD_DHCP_OPTION_SERVER_IDENTIFIER,
4, &server->address);
if (r < 0)
return r;
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
- DHCP_OPTION_END, 0, NULL);
+ SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
lease_time = htobe32(req->lifetime);
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
+ 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,
- DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+ SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
if (r < 0)
return r;
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- DHCP_OPTION_ROUTER, 4, &server->address);
+ SD_DHCP_OPTION_ROUTER, 4, &server->address);
if (r < 0)
return r;
lease_time = htobe32(req->lifetime);
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
+ 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,
- DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+ SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
if (r < 0)
return r;
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- DHCP_OPTION_ROUTER, 4, &server->address);
+ 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,
- DHCP_OPTION_DOMAIN_NAME_SERVER,
+ 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,
- DHCP_OPTION_NTP_SERVER,
+ 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,
- DHCP_OPTION_NEW_TZDB_TIMEZONE,
+ SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
strlen(server->timezone), server->timezone);
if (r < 0)
return r;
return r;
r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
- &optoffset, 0, DHCP_OPTION_END, 0, NULL);
+ &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
assert(req);
switch(code) {
- case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
+ case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
if (len == 4)
req->lifetime = be32toh(*(be32_t*)option);
break;
- case DHCP_OPTION_REQUESTED_IP_ADDRESS:
+ case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS:
if (len == 4)
req->requested_ip = *(be32_t*)option;
break;
- case DHCP_OPTION_SERVER_IDENTIFIER:
+ case SD_DHCP_OPTION_SERVER_IDENTIFIER:
if (len == 4)
req->server_id = *(be32_t*)option;
break;
- case DHCP_OPTION_CLIENT_IDENTIFIER:
+ case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
if (len >= 2) {
uint8_t *data;
}
break;
- case DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
+ case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
if (len == 2)
req->max_optlen = be16toh(*(be16_t*)option) -
- sizeof(DHCPPacket);
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;
if (!req)
return -ENOMEM;
- type = dhcp_option_parse(message, length, parse_request, req);
+ type = dhcp_option_parse(message, length, parse_request, req, &error_message);
if (type < 0)
return 0;
break;
}
case DHCP_DECLINE:
- log_dhcp_server(server, "DECLINE (0x%x)",
- be32toh(req->message->xid));
+ 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 */
if (ioctl(fd, FIONREAD, &buflen) < 0)
return -errno;
- if (buflen < 0)
+ else if (buflen < 0)
return -EIO;
- message = malloc0(buflen);
+ message = malloc(buflen);
if (!message)
return -ENOMEM;
iov.iov_len = buflen;
len = recvmsg(fd, &msg, 0);
- if (len < buflen)
- return 0;
- else if ((size_t)len < sizeof(DHCPMessage))
+ 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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
};
static const uint16_t default_req_opts[] = {
- DHCP6_OPTION_DNS_SERVERS,
- DHCP6_OPTION_DOMAIN_LIST,
- DHCP6_OPTION_NTP_SERVER,
- DHCP6_OPTION_SNTP_SERVERS,
+ 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] = {
DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
-#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
-
#define DHCP6_CLIENT_DONT_DESTROY(client) \
- _cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(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);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
switch(option) {
- case DHCP6_OPTION_DNS_SERVERS:
- case DHCP6_OPTION_DOMAIN_LIST:
- case DHCP6_OPTION_SNTP_SERVERS:
- case DHCP6_OPTION_NTP_SERVER:
+ 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:
message->type = DHCP6_SOLICIT;
r = dhcp6_option_append(&opt, &optlen,
- DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+ SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
else
message->type = DHCP6_RENEW;
- r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
+ r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
client->lease->serverid_len,
client->lease->serverid);
if (r < 0)
return -EINVAL;
}
- r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
+ 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, DHCP6_OPTION_CLIENTID,
+ r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
client->duid_len, &client->duid);
if (r < 0)
return r;
else
elapsed_time = 0xffff;
- r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
+ r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME,
sizeof(elapsed_time), &elapsed_time);
if (r < 0)
return r;
while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
&optval)) >= 0) {
switch (optcode) {
- case DHCP6_OPTION_CLIENTID:
+ case SD_DHCP6_OPTION_CLIENTID:
if (clientid) {
log_dhcp6_client(client, "%s contains multiple clientids",
dhcp6_message_type_to_string(message->type));
break;
- case DHCP6_OPTION_SERVERID:
+ 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",
break;
- case DHCP6_OPTION_PREFERENCE:
+ case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
return -EINVAL;
break;
- case DHCP6_OPTION_STATUS_CODE:
+ case SD_DHCP6_OPTION_STATUS_CODE:
if (optlen < 2)
return -EINVAL;
break;
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
log_dhcp6_client(client, "Information request ignoring IA NA option");
break;
- case DHCP6_OPTION_RAPID_COMMIT:
+ case SD_DHCP6_OPTION_RAPID_COMMIT:
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
return r;
break;
- case DHCP6_OPTION_DNS_SERVERS:
+ case SD_DHCP6_OPTION_DNS_SERVERS:
r = dhcp6_lease_set_dns(lease, optval, optlen);
if (r < 0)
return r;
break;
- case DHCP6_OPTION_DOMAIN_LIST:
+ case SD_DHCP6_OPTION_DOMAIN_LIST:
r = dhcp6_lease_set_domains(lease, optval, optlen);
if (r < 0)
return r;
break;
- case DHCP6_OPTION_NTP_SERVER:
+ case SD_DHCP6_OPTION_NTP_SERVER:
r = dhcp6_lease_set_ntp(lease, optval, optlen);
if (r < 0)
return r;
break;
- case DHCP6_OPTION_SNTP_SERVERS:
+ case SD_DHCP6_OPTION_SNTP_SERVERS:
r = dhcp6_lease_set_sntp(lease, optval, optlen);
if (r < 0)
return r;
static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
int r;
- _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+ _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
bool rapid_commit;
if (reply->type != DHCP6_REPLY)
static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
int r;
- _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+ _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
uint8_t pref_advertise = 0, pref_lease = 0;
if (advertise->type != DHCP6_ADVERTISE)
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;
+ _cleanup_free_ DHCP6Message *message = NULL;
int r, buflen, len;
assert(s);
assert(client->event);
r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0 || buflen <= 0)
- buflen = DHCP6_MIN_OPTIONS_SIZE;
+ if (r < 0)
+ return -errno;
+ else if (buflen < 0)
+ /* This really should not happen */
+ return -EIO;
- message = malloc0(buflen);
+ message = malloc(buflen);
if (!message)
return -ENOMEM;
len = read(fd, message, buflen);
- if ((size_t)len < sizeof(DHCP6Message)) {
- log_dhcp6_client(client, "could not receive message from UDP socket: %m");
+ 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:
}
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
- _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
+ _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
size_t t;
assert_return(ret, -EINVAL);
client->n_ref = 1;
- client->ia_na.type = DHCP6_OPTION_IA_NA;
+ client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
client->index = -1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert_return(lease, -EINVAL);
assert_return(optval, -EINVAL);
- free(lease->ntp);
+ lease->ntp = mfree(lease->ntp);
lease->ntp_count = 0;
lease->ntp_allocated = 0;
#include "alloc-util.h"
#include "arp-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "in-addr-util.h"
#include "list.h"
return NULL;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd*, sd_ipv4acd_unref);
-#define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
-
int sd_ipv4acd_new(sd_ipv4acd **ret) {
- _cleanup_ipv4acd_unref_ sd_ipv4acd *ll = NULL;
+ _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL;
assert_return(ret, -EINVAL);
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_event_source_unref_ sd_event_source *timer = NULL;
+ _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
usec_t next_timeout;
usec_t time_now;
int r;
#include "sd-ipv4ll.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "in-addr-util.h"
#include "list.h"
#include "random-util.h"
#define IPV4LL_NETMASK 0xFFFF0000L
#define IPV4LL_DONT_DESTROY(ll) \
- _cleanup_ipv4ll_unref_ _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
+ _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
struct sd_ipv4ll {
unsigned n_ref;
return NULL;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
-#define _cleanup_ipv4ll_unref_ _cleanup_(sd_ipv4ll_unrefp)
-
static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
int sd_ipv4ll_new(sd_ipv4ll **ret) {
- _cleanup_ipv4ll_unref_ sd_ipv4ll *ll = NULL;
+ _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
int r;
assert_return(ret, -EINVAL);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "lldp-internal.h"
#include "lldp-port.h"
#include "lldp-tlv.h"
-#include "lldp-util.h"
#include "prioq.h"
#include "siphash24.h"
#include "string-util.h"
/* 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;
- bool chassis_id = false;
- bool malformed = false;
- bool port_id = false;
- bool ttl = false;
- bool end = false;
lldp_port *port;
uint8_t *p, *q;
sd_lldp *lldp;
lldp = (sd_lldp *) port->userdata;
if (lldp->port->status == LLDP_PORT_STATUS_DISABLED) {
- log_lldp("Port is disabled : %s . Dropping ...",
- lldp->port->ifname);
+ log_lldp("Port: %s is disabled. Dropping.", lldp->port->ifname);
goto out;
}
if (type == LLDP_TYPE_END) {
if (len != 0) {
- log_lldp("TLV type end is not length 0. Length:%d received . Dropping ...",
- len);
+ log_lldp("TLV type end must be length 0 (not %d). Dropping.", len);
malformed = true;
goto out;
break;
} else if (type >=_LLDP_TYPE_MAX) {
- log_lldp("TLV type not recognized %d . Dropping ...",
- type);
+ log_lldp("TLV type: %d not recognized. Dropping.", type);
malformed = true;
goto out;
if (i <= 3) {
if (i != type) {
- log_lldp("TLV missing or out of order. Dropping ...");
+ log_lldp("TLV missing or out of order. Dropping.");
malformed = true;
goto out;
case LLDP_TYPE_CHASSIS_ID:
if (len < 2) {
- log_lldp("Received malformed Chassis ID TLV len = %d. Dropping",
- len);
+ 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 ...");
+ 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);
+ 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;
case LLDP_TYPE_PORT_ID:
if (len < 2) {
- log_lldp("Received malformed Port ID TLV len = %d. Dropping",
- len);
+ 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 ...");
+ 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);
+ 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;
case LLDP_TYPE_TTL:
if(len != 2) {
- log_lldp(
- "Received invalid lenth: %d TTL TLV. Dropping ...",
- len);
+ log_lldp("Received invalid TTL TLV lenth: %d. Dropping.", len);
malformed = true;
goto out;
}
if (ttl) {
- log_lldp("Duplicate TTL TLV found. Dropping ...");
+ 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's, length 0 received . Dropping ...",
- type);
+ log_lldp("TLV type: %d length 0 received. Dropping.", type);
malformed = true;
goto out;
}
if(!chassis_id || !port_id || !ttl || !end) {
- log_lldp( "One or more mandotory TLV missing . Dropping ...");
+ 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 ...");
+ log_lldp("Failed to parse the TLV. Dropping.");
malformed = true;
goto out;
return 0;
}
-void sd_lldp_free(sd_lldp *lldp) {
+sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
if (!lldp)
- return;
+ return NULL;
/* Drop all packets */
lldp_mib_objects_flush(lldp);
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_lldp_free_ sd_lldp *lldp = NULL;
+ _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
int r;
assert_return(ret, -EINVAL);
#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
}
static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
- _cleanup_free_ NDiscPrefix *prefix = NULL;
+ NDiscPrefix *prefix;
assert(ret);
prefix->nd = nd;
*ret = prefix;
- prefix = NULL;
-
return 0;
}
return NULL;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ndisc*, sd_ndisc_unref);
-#define _cleanup_sd_ndisc_free_ _cleanup_(sd_ndisc_unrefp)
-
int sd_ndisc_new(sd_ndisc **ret) {
- _cleanup_sd_ndisc_free_ sd_ndisc *nd = NULL;
+ _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL;
assert(ret);
LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
if (prefix->valid_until < time_now) {
prefix = ndisc_prefix_unref(prefix);
-
continue;
}
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 (r < 0 && r != -EADDRNOTAVAIL)
- return r;
-
- /* if router advertisment prefix valid timeout is zero, the timeout
- callback will be called immediately to clean up the prefix */
+ /* if router advertisment prefix valid timeout is zero, the timeout
+ callback will be called immediately to clean up the prefix */
- if (r == -EADDRNOTAVAIL) {
r = ndisc_prefix_new(nd, &prefix);
if (r < 0)
return r;
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));
+ 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);
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,
+ 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));
+ 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);
return 0;
}
-static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
- ssize_t len) {
+static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra, ssize_t len) {
void *opt;
struct nd_opt_hdr *opt_hdr;
nd->mtu = MAX(mtu, IP6_MIN_MTU);
log_ndisc(nd, "Router Advertisement link MTU %d using %d",
- mtu, nd->mtu);
+ mtu, nd->mtu);
}
break;
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;
- int r, buflen = 0, pref, stateful;
- union sockaddr_union router = {};
- socklen_t router_len = sizeof(router);
+ 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 || buflen <= 0)
- buflen = ICMP6_RECV_SIZE;
+ if (r < 0)
+ return -errno;
+ else if (buflen < 0)
+ /* This really should not happen */
+ return -EIO;
+
+ iov.iov_len = buflen;
- ra = malloc(buflen);
+ ra = malloc(iov.iov_len);
if (!ra)
return -ENOMEM;
- len = recvfrom(fd, ra, buflen, 0, &router.sa, &router_len);
+ 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 (router_len != sizeof(router.in6) && router_len != 0) {
- log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)router_len);
+ } 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 (nd->router_callback)
- nd->router_callback(nd, stateful, router_len != 0 ? &router.in6.sin6_addr : NULL, lifetime, pref, nd->userdata);
+ 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;
- struct ether_addr unset = { };
- struct ether_addr *addr = NULL;
int r;
assert(s);
nd->callback(nd, SD_NDISC_EVENT_TIMEOUT, nd->userdata);
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
} else {
- if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
- addr = &nd->mac_addr;
-
- r = icmp6_send_router_solicitation(nd->fd, addr);
+ r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
if (r < 0)
log_ndisc(nd, "Error sending Router Solicitation");
else {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-ipv4acd.h"
#include "sd-netlink.h"
-#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
#include "util.h"
}
static int test_acd(const char *ifname, const char *address) {
- _cleanup_event_unref_ sd_event *e = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *reply = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
#include "dhcp-protocol.h"
-#include "event-util.h"
#include "fd-util.h"
#include "util.h"
assert_se(sd_dhcp_client_set_index(client, 1) == 0);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_SUBNET_MASK) == -EEXIST);
+ SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_ROUTER) == -EEXIST);
+ SD_DHCP_OPTION_ROUTER) == -EEXIST);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_HOST_NAME) == -EEXIST);
+ SD_DHCP_OPTION_HOST_NAME) == -EEXIST);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
+ SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
+ SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_PAD) == -EINVAL);
+ SD_DHCP_OPTION_PAD) == -EINVAL);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_END) == -EINVAL);
+ SD_DHCP_OPTION_END) == -EINVAL);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
+ SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_OVERLOAD) == -EINVAL);
+ SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
assert_se(sd_dhcp_client_set_request_option(client,
- DHCP_OPTION_PARAMETER_REQUEST_LIST)
+ SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
== -EINVAL);
assert_se(sd_dhcp_client_set_request_option(client, 33) == 0);
static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
switch(code) {
- case DHCP_OPTION_CLIENT_IDENTIFIER:
+ case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
{
uint32_t iaid;
struct duid duid;
static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
int res;
- res = dhcp_option_parse(dhcp, size, check_options, NULL);
+ res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
assert_se(res == DHCP_DISCOVER);
if (verbose)
uint8_t *msg_bytes = (uint8_t *)request;
int res;
- res = dhcp_option_parse(request, size, check_options, NULL);
+ 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] == DHCP_OPTION_END);
+ assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
if (verbose)
printf(" recv DHCP Request 0x%08x\n", be32toh(xid));
uint8_t *msg_bytes = (uint8_t *)discover;
int res;
- res = dhcp_option_parse(discover, size, check_options, NULL);
+ res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
assert_se(res == DHCP_DISCOVER);
- assert_se(msg_bytes[size - 1] == DHCP_OPTION_END);
+ assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
xid = discover->xid;
}
int main(int argc, char *argv[]) {
- _cleanup_event_unref_ sd_event *e;
+ _cleanup_(sd_event_unrefp) sd_event *e;
log_set_max_level(LOG_DEBUG);
log_parse_environment();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
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,
- DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
+ 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,
0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
40, true, },
- { {}, 0, {}, 0, { DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
+ { {}, 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, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
- { DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
+ { 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, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
+ { { 1, 4, 1, 2, 3, 4, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
{ 222, 3, 1, 2, 3 }, 5,
- { DHCP_OPTION_OVERLOAD, 1,
+ { SD_DHCP_OPTION_OVERLOAD, 1,
DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, },
};
static void test_invalid_buffer_length(void) {
DHCPMessage message;
- assert_se(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
- assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL)
- == -EINVAL);
+ 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) {
assert_se(magic[2] == 83);
assert_se(magic[3] == 99);
- assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0);
+ assert_se(dhcp_option_parse(message, len, NULL, NULL, NULL) >= 0);
}
static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
while (*descpos < *desclen) {
switch(descoption[*descpos]) {
- case DHCP_OPTION_PAD:
+ case SD_DHCP_OPTION_PAD:
*descpos += 1;
break;
- case DHCP_OPTION_MESSAGE_TYPE:
- case DHCP_OPTION_OVERLOAD:
+ case SD_DHCP_OPTION_MESSAGE_TYPE:
+ case SD_DHCP_OPTION_OVERLOAD:
*descpos += 3;
break;
if (!desc)
return -EINVAL;
- assert_se(code != DHCP_OPTION_PAD);
- assert_se(code != DHCP_OPTION_END);
- assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
- assert_se(code != DHCP_OPTION_OVERLOAD);
+ 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) {
buflen = sizeof(DHCPMessage) + optlen;
if (!desc) {
- assert_se((res = dhcp_option_parse(message, buflen,
- test_options_cb,
- NULL)) == -ENOMSG);
+ 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)) >= 0);
- assert_se(desc->pos == -1 && desc->filepos == -1 &&
- desc->snamepos == -1);
+ 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)) < 0);
+ assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) < 0);
if (verbose)
printf("DHCP type %s\n", dhcp_type(res));
result->options[2] = 'C';
result->options[3] = 'D';
- assert_se(dhcp_option_append(result, 0, &offset, 0, DHCP_OPTION_PAD,
+ 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, DHCP_OPTION_PAD,
+ 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, DHCP_OPTION_PAD,
+ 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] != DHCP_OPTION_END) {
+ 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] == DHCP_OPTION_PAD)
+ if (options[pos] == SD_DHCP_OPTION_PAD)
pos++;
else
pos += 2 + options[pos + 1];
if (verbose)
printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9],
- DHCP_OPTION_END);
+ SD_DHCP_OPTION_END);
- assert_se(result->options[9] == 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],
- DHCP_OPTION_PAD);
+ SD_DHCP_OPTION_PAD);
- assert_se(result->options[10] == DHCP_OPTION_PAD);
+ assert_se(result->options[10] == SD_DHCP_OPTION_PAD);
for (i = 0; i < pos - 8; i++) {
if (verbose)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-event.h"
#include "dhcp-server-internal.h"
-#include "event-util.h"
static void test_pool(struct in_addr *address, unsigned size, int ret) {
- _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+ _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
assert_se(sd_dhcp_server_new(&server, 1) >= 0);
}
static int test_basic(sd_event *event) {
- _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+ _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
struct in_addr address_lo = {
.s_addr = htonl(INADDR_LOOPBACK),
};
}
static void test_message_handler(void) {
- _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+ _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
struct {
DHCPMessage message;
struct {
.message.hlen = ETHER_ADDR_LEN,
.message.xid = htobe32(0x12345678),
.message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
- .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
+ .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE,
.option_type.length = 1,
.option_type.type = DHCP_DISCOVER,
- .end = DHCP_OPTION_END,
+ .end = SD_DHCP_OPTION_END,
};
struct in_addr address_lo = {
.s_addr = htonl(INADDR_LOOPBACK),
test.end = 0;
/* TODO, shouldn't this fail? */
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
- test.end = DHCP_OPTION_END;
+ 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 = DHCP_OPTION_MESSAGE_TYPE;
+ 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.option_type.type = DHCP_REQUEST;
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
- test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
+ 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 = DHCP_OPTION_SERVER_IDENTIFIER;
+ 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);
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 = DHCP_OPTION_CLIENT_IDENTIFIER;
+ 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';
}
int main(int argc, char *argv[]) {
- _cleanup_event_unref_ sd_event *e;
+ _cleanup_(sd_event_unrefp) sd_event *e;
int r;
log_set_max_level(LOG_DEBUG);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
-#include "event-util.h"
#include "fd-util.h"
#include "macro.h"
#include "socket-util.h"
sizeof (mac_addr),
ARPHRD_ETHER) >= 0);
- assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_CLIENTID) == -EINVAL);
- assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
- assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_NTP_SERVER) == -EEXIST);
- assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
- assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
+ 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);
static int test_option(sd_event *e) {
uint8_t packet[] = {
'F', 'O', 'O',
- 0x00, DHCP6_OPTION_ORO, 0x00, 0x07,
+ 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
'A', 'B', 'C', 'D', 'E', 'F', 'G',
- 0x00, DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
+ 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
'1', '2', '3', '4', '5', '6', '7', '8', '9',
'B', 'A', 'R',
};
&optval) >= 0);
pos += 4 + optlen;
assert_se(buf == &packet[pos]);
- assert_se(optcode == DHCP6_OPTION_ORO);
+ assert_se(optcode == SD_DHCP6_OPTION_ORO);
assert_se(optlen == 7);
assert_se(buflen + pos == sizeof(packet));
&optval) >= 0);
pos += 4 + optlen;
assert_se(buf == &packet[pos]);
- assert_se(optcode == DHCP6_OPTION_VENDOR_CLASS);
+ assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
assert_se(optlen == 9);
assert_se(buflen + pos == sizeof(packet));
};
static int test_advertise_option(sd_event *e) {
- _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+ _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;
&optval)) >= 0) {
switch(optcode) {
- case DHCP6_OPTION_CLIENTID:
+ case SD_DHCP6_OPTION_CLIENTID:
assert_se(optlen == 14);
opt_clientid = true;
break;
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
assert_se(optlen == 94);
assert_se(!memcmp(optval, &msg_advertise[26], optlen));
break;
- case DHCP6_OPTION_SERVERID:
+ case SD_DHCP6_OPTION_SERVERID:
assert_se(optlen == 14);
assert_se(!memcmp(optval, &msg_advertise[179], optlen));
optlen) >= 0);
break;
- case DHCP6_OPTION_PREFERENCE:
+ case SD_DHCP6_OPTION_PREFERENCE:
assert_se(optlen == 1);
assert_se(!*optval);
*optval) >= 0);
break;
- case DHCP6_OPTION_ELAPSED_TIME:
+ case SD_DHCP6_OPTION_ELAPSED_TIME:
assert_se(optlen == 2);
break;
- case DHCP6_OPTION_DNS_SERVERS:
+ case SD_DHCP6_OPTION_DNS_SERVERS:
assert_se(optlen == 16);
assert_se(dhcp6_lease_set_dns(lease, optval,
optlen) >= 0);
break;
- case DHCP6_OPTION_DOMAIN_LIST:
+ case SD_DHCP6_OPTION_DOMAIN_LIST:
assert_se(optlen == 11);
assert_se(dhcp6_lease_set_domains(lease, optval,
optlen) >= 0);
break;
- case DHCP6_OPTION_SNTP_SERVERS:
+ case SD_DHCP6_OPTION_SNTP_SERVERS:
assert_se(optlen == 16);
assert_se(dhcp6_lease_set_sntp(lease, optval,
optlen) >= 0);
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, DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
+ assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
if (verbose)
printf(" got DHCPv6 event %d\n", event);
static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
size_t len) {
- _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+ _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
uint8_t *optval;
uint16_t optcode;
size_t optlen;
while ((r = dhcp6_option_parse(&option, &len,
&optcode, &optlen, &optval)) >= 0) {
switch(optcode) {
- case DHCP6_OPTION_CLIENTID:
+ case SD_DHCP6_OPTION_CLIENTID:
assert_se(!found_clientid);
found_clientid = true;
break;
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
assert_se(!found_iana);
found_iana = true;
break;
- case DHCP6_OPTION_SERVERID:
+ case SD_DHCP6_OPTION_SERVERID:
assert_se(!found_serverid);
found_serverid = true;
break;
- case DHCP6_OPTION_ELAPSED_TIME:
+ case SD_DHCP6_OPTION_ELAPSED_TIME:
assert_se(!found_elapsed_time);
found_elapsed_time = true;
while ((r = dhcp6_option_parse(&option, &len,
&optcode, &optlen, &optval)) >= 0) {
switch(optcode) {
- case DHCP6_OPTION_CLIENTID:
+ case SD_DHCP6_OPTION_CLIENTID:
assert_se(!found_clientid);
found_clientid = true;
break;
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
assert_se(!found_iana);
found_iana = true;
break;
- case DHCP6_OPTION_ELAPSED_TIME:
+ case SD_DHCP6_OPTION_ELAPSED_TIME:
assert_se(!found_elapsed_time);
found_elapsed_time = true;
static int test_client_verify_information_request(DHCP6Message *information_request,
uint8_t *option, size_t len) {
- _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+ _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
uint8_t *optval;
uint16_t optcode;
size_t optlen;
while ((r = dhcp6_option_parse(&option, &len,
&optcode, &optlen, &optval)) >= 0) {
switch(optcode) {
- case DHCP6_OPTION_CLIENTID:
+ case SD_DHCP6_OPTION_CLIENTID:
assert_se(!found_clientid);
found_clientid = true;
break;
- case DHCP6_OPTION_IA_NA:
+ case SD_DHCP6_OPTION_IA_NA:
assert_not_reached("IA TA option must not be present");
break;
- case DHCP6_OPTION_SERVERID:
+ case SD_DHCP6_OPTION_SERVERID:
assert_not_reached("Server ID option must not be present");
break;
- case DHCP6_OPTION_ELAPSED_TIME:
+ case SD_DHCP6_OPTION_ELAPSED_TIME:
assert_se(!found_elapsed_time);
found_elapsed_time = true;
}
int main(int argc, char *argv[]) {
- _cleanup_event_unref_ sd_event *e;
+ _cleanup_(sd_event_unrefp) sd_event *e;
assert_se(sd_event_new(&e) >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-netlink.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
#include "parse-util.h"
}
static int test_ll(const char *ifname, const char *seed) {
- _cleanup_event_unref_ sd_event *e = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *reply = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
#include "sd-ipv4ll.h"
#include "arp-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "socket-util.h"
#include "util.h"
}
int main(int argc, char *argv[]) {
- _cleanup_event_unref_ sd_event *e = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
log_set_max_level(LOG_DEBUG);
log_parse_environment();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-lldp.h"
#include "alloc-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "lldp-network.h"
#include "lldp-tlv.h"
};
static int lldp_build_tlv_packet(tlv_packet **ret) {
- _cleanup_lldp_packet_unref_ tlv_packet *m = NULL;
+ _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),
}
static void test_parser(void) {
- _cleanup_lldp_packet_unref_ tlv_packet *tlv = NULL;
+ _cleanup_(sd_lldp_packet_unrefp) tlv_packet *tlv = NULL;
/* form a packet */
lldp_build_tlv_packet(&tlv);
if (r)
return r;
- sd_lldp_free(lldp);
+ sd_lldp_unref(lldp);
safe_close(test_fd[1]);
return 0;
}
int main(int argc, char *argv[]) {
- _cleanup_event_unref_ sd_event *e = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
test_parser();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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, EBADR),
+ 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_NO_SUCH_PROCESS, ESRCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, EIO),
+ 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),
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret, param = 0;
int r;
}
static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret;
int r;
}
static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **x = NULL, **y = NULL;
int r;
bool allow_activator,
sd_bus_creds **creds) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _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 mask,
sd_bus_creds **creds) {
- _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _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;
}
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const void *p = NULL;
size_t sz = 0;
}
static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
struct kdbus_cmd_info cmd = {
.size = sizeof(struct kdbus_cmd_info),
};
}
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
pid_t pid = 0;
bool do_label;
int r;
}
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
const char *mid;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
const char *member,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(bus, -EINVAL);
void *userdata,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(bus, -EINVAL);
sd_bus_message **reply,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
bus_assert_return(bus, -EINVAL, error);
sd_bus_message *call,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(call, -EINVAL);
sd_bus_message *call,
const sd_bus_error *e) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(call, -EINVAL);
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
va_list ap;
assert_return(call, -EINVAL);
int error,
const sd_bus_error *p) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
assert_return(call, -EINVAL);
assert_return(call->sealed, -EPERM);
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
va_list ap;
assert_return(call, -EINVAL);
sd_bus_error *error,
char type, void *ptr) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
bus_assert_return(bus, -EINVAL, error);
sd_bus_error *error,
char **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *s;
char *n;
int r;
sd_bus_error *error,
char ***ret) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
bus_assert_return(bus, -EINVAL, error);
sd_bus_error *error,
const char *type, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
va_list ap;
int r;
}
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t our_uid;
bool know_caps = false;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
- assert_return(c, NULL);
+
+ if (!c)
+ return NULL;
if (c->allocated) {
assert(c->n_ref > 0);
}
int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
int r;
assert(c);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
#include "sd-bus.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
p = startswith(name, "System.Error.");
if (p) {
r = errno_from_name(p);
- if (r <= 0)
+ if (r < 0)
return EIO;
return r;
}
- if (additional_error_maps) {
- for (map = additional_error_maps; *map; map++) {
+ 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)
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 netx 8byte
+ * 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) {
if (!name)
return 0;
- if (!e)
- goto finish;
- assert_return(!bus_error_is_dirty(e), -EINVAL);
+ if (e) {
+ assert_return(!bus_error_is_dirty(e), -EINVAL);
- e->name = strdup(name);
- if (!e->name) {
- *e = BUS_ERROR_OOM;
- return -ENOMEM;
- }
+ 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);
+ /* 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;
+ e->_need_free = 1;
+ }
-finish:
return -bus_error_name_to_errno(name);
}
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 (;; n++) {
- if (additional_error_maps[n] == NULL)
- break;
-
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
#include "sd-bus.h"
+
#include "macro.h"
bool bus_error_is_dirty(sd_bus_error *e);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
* bus from the callback doesn't destroy the object we are working
* on */
#define BUS_DONT_DESTROY(bus) \
- _cleanup_bus_unref_ _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdio.h>
#include "sd-bus.h"
+
#include "set.h"
struct introspect {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
struct bus_body_part *part;
struct kdbus_item *d;
const char *destination;
- bool well_known;
- uint64_t unique;
+ bool well_known = false;
+ uint64_t dst_id;
size_t sz, dl;
unsigned i;
int r;
destination = m->destination ?: m->destination_ptr;
if (destination) {
- r = bus_kernel_parse_unique_name(destination, &unique);
+ r = bus_kernel_parse_unique_name(destination, &dst_id);
if (r < 0)
return r;
-
- well_known = r == 0;
+ 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
- well_known = false;
+ dst_id = KDBUS_DST_ID_BROADCAST;
sz = offsetof(struct kdbus_msg, items);
((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);
- if (well_known)
- /* 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 weel-known-name, and fail if they
- * differ. Currently, this is only needed for bus-proxyd. */
- m->kdbus->dst_id = m->verify_destination_id;
- else
- m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
-
+ 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 (k->src_id == KDBUS_SRC_ID_KERNEL)
bus_message_set_sender_driver(bus, m);
else {
- snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
+ xsprintf(m->sender_buffer, ":1.%llu",
+ (unsigned long long)k->src_id);
m->sender = m->creds.unique_name = m->sender_buffer;
}
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 {
- snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
+ xsprintf(m->destination_buffer, ":1.%llu",
+ (unsigned long long)k->dst_id);
m->destination = m->destination_buffer;
}
r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
if (r < 0) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *reply;
if (errno == EAGAIN || errno == EINTR)
const char *new_owner,
const struct kdbus_timestamp *ts) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
const struct kdbus_item *d,
const struct kdbus_timestamp *ts) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/* Run the callback. And then invoke siblings. */
if (node->leaf.callback->callback) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
va_list ap;
assert_return(name, -EINVAL);
int error,
const sd_bus_error *p) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _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);
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
va_list ap;
va_start(ap, format);
}
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
- assert_return(m, NULL);
+
+ if (!m)
+ return NULL;
assert(m->n_ref > 0);
m->n_ref++;
}
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
usec_t timeout;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(found_object);
LIST_FOREACH(callbacks, c, first) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
sd_bus_slot *slot;
if (bus->nodes_modified)
bool require_fallback,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *signature;
void *u;
int r;
bool is_get,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
const char *iface,
bool *found_object) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
struct node_vtable *c;
bool found_interface;
int r;
streq(iface, "org.freedesktop.DBus.Introspectable");
LIST_FOREACH(vtables, c, first) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
void *u;
if (require_fallback && !c->is_fallback)
}
LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (require_fallback && !c->is_fallback)
continue;
bool require_fallback,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_set_free_free_ Set *s = NULL;
const char *previous_interface = NULL;
struct introspect intro;
bool require_fallback,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_set_free_free_ Set *s = NULL;
Iterator i;
char *path;
bool *found_interface,
char **names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ 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 *m = NULL;
bool has_invalidating = false, has_changing = false;
struct vtable_member key = {};
struct node_vtable *c;
return 0;
LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
void *u = NULL;
if (require_fallback && !c->is_fallback)
_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
struct node *object_manager;
int r;
return 0;
LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
void *u = NULL;
if (require_fallback && !c->is_fallback)
_public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
struct node *object_manager;
int r;
const char *interface,
bool require_fallback) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool found_interface = false;
struct node_vtable *c;
struct node *n;
_public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
struct node *object_manager;
char **i;
int r;
}
_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
struct node *object_manager;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
- assert_return(slot, NULL);
+
+ if (!slot)
+ return NULL;
assert(slot->n_ref > 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
/* Get the SELinux context of the peer */
- if (mac_selinux_use()) {
+ 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");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
_public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
- assert_return(track, NULL);
+
+ if (!track)
+ return NULL;
assert(track->n_ref > 0);
}
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
_cleanup_free_ char *n = NULL;
const char *match;
int r;
}
_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
_cleanup_free_ char *n = NULL;
assert_return(name, -EINVAL);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
STRV_FOREACH(i, merged) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_id128_t mid;
if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
.on_path = on_path,
};
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
.on_property = on_property,
};
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
log_info("Monitoring bus message stream.");
for (;;) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
r = sd_bus_process(bus, &m);
if (r < 0)
}
static int status(sd_bus *bus, char *argv[]) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
int r;
}
static int call(sd_bus *bus, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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);
}
static int get_property(sd_bus *bus, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
unsigned n;
char **i;
int r;
}
STRV_FOREACH(i, argv + 4) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *contents = NULL;
char type;
}
static int set_property(sd_bus *bus, char *argv[]) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
log_parse_environment();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int bus_send_hello(sd_bus *bus) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
- assert_return(bus, NULL);
+
+ if (!bus)
+ return NULL;
assert_se(REFCNT_INC(bus->n_ref) >= 2);
}
static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
int r;
assert_return(m, -EINVAL);
void *userdata,
uint64_t usec) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
- _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL;
+ _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);
sd_bus_error *error,
sd_bus_message **reply) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
usec_t timeout;
uint64_t cookie;
unsigned i;
}
static int process_timeout(sd_bus *bus) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
+ _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;
}
static int process_reply(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _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;
}
static int process_filter(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
struct filter_callback *l;
int r;
}
static int process_builtin(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
assert(bus);
}
static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
}
static int process_closing(sd_bus *bus, sd_bus_message **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
struct reply_callback *c;
int r;
c = ordered_hashmap_first(bus->reply_callbacks);
if (c) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
sd_bus_slot *slot;
/* First, fail all outstanding method calls */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int r;
for (;;) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
r = sd_bus_process(b, &m);
assert_se(r >= 0);
}
static void transaction(sd_bus *b, size_t sz, const char *server_name) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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);
}
static void client_bisect(const char *address, const char *server_name) {
- _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
size_t lsize, rsize, csize;
sd_bus *b;
int r;
}
static void client_chart(Type type, const char *address, const char *server_name, int fd) {
- _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
size_t csize;
sd_bus *b;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
bool client1_gone = false, client2_gone = false;
while (!client1_gone || !client2_gone) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
pid_t pid = 0;
const char *label = NULL;
}
static void* client1(void*p) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
- _cleanup_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;
+ _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 };
finish:
if (bus) {
- _cleanup_bus_message_unref_ sd_bus_message *q;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
r = sd_bus_message_new_method_call(
bus,
}
static void* client2(void*p) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
finish:
if (bus) {
- _cleanup_bus_message_unref_ sd_bus_message *q;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
r = sd_bus_message_new_method_call(
bus,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "refcnt.h"
static void test_bus_new(void) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _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_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
r = sd_bus_open_system(&bus);
static void test_bus_new_method_call(void) {
sd_bus *bus = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
assert_se(sd_bus_open_system(&bus) >= 0);
printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
- sd_bus_unref(bus);
- printf("after bus_unref: refcount %u\n", m->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_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
assert_se(sd_bus_open_system(&bus) >= 0);
printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
- sd_bus_unref(bus);
- printf("after bus_unref: refcount %u\n", m->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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "cgroup-util.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
int r;
- if (cg_unified() == -ENOEXEC) {
+ if (cg_unified() == -ENOMEDIUM) {
puts("Skipping test: /sys/fs/cgroup/ not available");
return EXIT_TEST_SKIP;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "errno-list.h"
static void test_error(void) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
+ _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,
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_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[];
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-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[]) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static void test_marshal(void) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
_cleanup_close_ int bus_ref = -1;
_cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
sd_bus *a, *b;
int r, found = 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_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];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int main(int argc, char *argv[]) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL;
+ _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;
_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_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
double dbl;
uint64_t u64;
log_error("%s", error.message);
else
dbus_message_unref(w);
+
+ dbus_error_free(&error);
}
#endif
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
.type = BUS_MATCH_ROOT,
};
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int client(struct context *c) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_unref_ sd_bus *bus = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static void test_proxy_matched(void) {
- _cleanup_bus_flush_close_unref_ sd_bus *a = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL;
_cleanup_free_ char *matchstr = NULL;
TestProxyMatch match = {};
const char *me;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert_se(sd_bus_start(bus) >= 0);
while (!quit) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
r = sd_bus_process(bus, &m);
if (r < 0) {
}
static int client(struct context *c) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
};
_public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
- _cleanup_device_enumerator_unref_ sd_device_enumerator *enumerator = NULL;
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL;
assert(ret);
return -errno;
FOREACH_DIRENT_ALL(dent, dir, return -errno) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _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;
/* TODO: filter away subsystems? */
FOREACH_DIRENT_ALL(dent, dir, return -errno) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *subsystem, *sysname;
int k;
}
static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *subsystem, *sysname;
int r;
}
int device_new_from_strv(sd_device **ret, char **strv) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
char **key;
const char *major = NULL, *minor = NULL;
DeviceAction action = _DEVICE_ACTION_INVALID;
}
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *major = NULL, *minor = NULL;
DeviceAction action = _DEVICE_ACTION_INVALID;
uint64_t seqnum;
}
int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
- _cleanup_device_unref_ sd_device *ret = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
int r;
assert(old_device);
}
int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
- _cleanup_device_unref_ sd_device *ret = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
int r;
assert(old_device);
}
int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
- _cleanup_device_unref_ sd_device *ret = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
int r;
assert(new_device);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "util.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_device*, sd_device_unref);
-#define _cleanup_device_unref_ _cleanup_(sd_device_unrefp)
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_device_enumerator*, sd_device_enumerator_unref);
-#define _cleanup_device_enumerator_unref_ _cleanup_(sd_device_enumerator_unrefp)
-
#define FOREACH_DEVICE_PROPERTY(device, key, value) \
for (key = sd_device_get_property_first(device, &(value)); \
key; \
#include "util.h"
int device_new_aux(sd_device **ret) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
assert(ret);
}
_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
int r;
assert_return(ret, -EINVAL);
int device_read_uevent_file(sd_device *device) {
_cleanup_free_ char *uevent = NULL;
- const char *syspath, *key, *value, *major = NULL, *minor = NULL;
+ const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
char *path;
size_t uevent_len;
unsigned i;
}
case 'n':
{
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
_cleanup_close_ int sk = -1;
struct ifreq ifr = {};
int ifindex;
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-event.h"
-
-#include "util.h"
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event*, sd_event_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, sd_event_source_unref);
-
-#define _cleanup_event_unref_ _cleanup_(sd_event_unrefp)
-#define _cleanup_event_source_unref_ _cleanup_(sd_event_source_unrefp)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
_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 {
bool exit_requested:1;
bool need_process_child:1;
bool watchdog:1;
+ bool profile_delays:1;
int exit_code;
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);
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;
return 1;
/* Order by time */
- if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
+ if (time_event_source_latest(x) < time_event_source_latest(y))
return -1;
- if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
+ if (time_event_source_latest(x) > time_event_source_latest(y))
return 1;
return 0;
e->original_pid = getpid();
e->perturb = USEC_INFINITY;
- e->pending = prioq_new(pending_prioq_compare);
- if (!e->pending) {
- r = -ENOMEM;
+ 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) {
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;
}
_public_ sd_event* sd_event_ref(sd_event *e) {
- assert_return(e, NULL);
+
+ if (!e)
+ return NULL;
assert(e->n_ref >= 1);
e->n_ref++;
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 from epoll: %m", strna(s->description));
+ 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;
}
d->priority = priority;
r = hashmap_put(e->signal_data, &d->priority, d);
- if (r < 0)
+ if (r < 0) {
+ free(d);
return r;
+ }
added = true;
}
int r;
assert_return(e, -EINVAL);
- assert_return(usec != (uint64_t) -1, -EINVAL);
assert_return(accuracy != (uint64_t) -1, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
d = event_get_clock_data(e, type);
assert(d);
- if (!d->earliest) {
- d->earliest = prioq_new(earliest_time_prioq_compare);
- if (!d->earliest)
- return -ENOMEM;
- }
+ r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare);
+ if (r < 0)
+ return r;
- if (!d->latest) {
- d->latest = prioq_new(latest_time_prioq_compare);
- if (!d->latest)
- return -ENOMEM;
- }
+ 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);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- if (!e->exit) {
- e->exit = prioq_new(exit_prioq_compare);
- if (!e->exit)
- return -ENOMEM;
- }
+ r = prioq_ensure_allocated(&e->exit, exit_prioq_compare);
+ if (r < 0)
+ return r;
s = source_new(e, !ret, SOURCE_EXIT);
if (!s)
}
_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
- assert_return(s, NULL);
+
+ if (!s)
+ return NULL;
assert(s->n_ref >= 1);
s->n_ref++;
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 (a <= 0)
return 0;
+ if (a >= USEC_INFINITY)
+ return USEC_INFINITY;
if (b <= a + 1)
return a;
d->needs_rearm = false;
a = prioq_peek(d->earliest);
- if (!a || a->enabled == SD_EVENT_OFF) {
+ if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) {
if (d->fd < 0)
return 0;
b = prioq_peek(d->latest);
assert_se(b && b->enabled != SD_EVENT_OFF);
- t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
+ t = sleep_between(e, a->time.next, time_event_source_latest(b));
if (d->next == t)
return 0;
s->dispatching = false;
- if (r < 0) {
- if (s->description)
- log_debug_errno(r, "Event source '%s' returned error, disabling: %m", s->description);
- else
- log_debug_errno(r, "Event source %p returned error, disabling: %m", s);
- }
+ 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);
r = s->prepare(s, s->userdata);
s->dispatching = false;
- if (r < 0) {
- if (s->description)
- log_debug_errno(r, "Prepare callback of event source '%s' returned error, disabling: %m", s->description);
- else
- log_debug_errno(r, "Prepare callback of event source %p returned error, disabling: %m", s);
- }
+ 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);
e->iteration++;
+ e->state = SD_EVENT_PREPARING;
r = event_prepare(e);
+ e->state = SD_EVENT_INITIAL;
if (r < 0)
return r;
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->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);
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
*usec = e->timestamp.monotonic;
break;
- case CLOCK_BOOTTIME:
- case CLOCK_BOOTTIME_ALARM:
+ default:
*usec = e->timestamp_boottime;
break;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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(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);
sd_event_source_unref(y);
do_quit = true;
- assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
+ 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);
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;
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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "util.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_hwdb*, sd_hwdb_unref);
-#define _cleanup_hwdb_unref_ _cleanup_(sd_hwdb_unrefp)
-
bool hwdb_validate(sd_hwdb *hwdb);
UDEVLIBEXECDIR "/hwdb.bin\0";
_public_ int sd_hwdb_new(sd_hwdb **ret) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
const char *hwdb_bin_path;
const char sig[] = HWDB_SIG;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
int fd;
- assert_return(m, NULL);
+ if (!m)
+ return NULL;
fd = MONITOR_TO_FD(m);
close_nointr(fd);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _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 local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-netlink.h"
+
#include "in-addr-util.h"
struct local_address {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
/* Make sure callbacks don't destroy the rtnl connection */
-#define RTNL_DONT_DESTROY(rtnl) \
- _cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
+#define NETLINK_DONT_DESTROY(rtnl) \
+ _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
const NLType *nl_type;
size_t size;
int 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int r;
assert(nl);
- assert(nl->fd > 0);
+ assert(nl->fd >= 0);
r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
if (r < 0) {
* On failure, a negative error code is returned.
*/
int socket_read_message(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *first = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
struct iovec iov = {};
uint32_t group = 0;
bool multi_part = false, done = false;
}
for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_bridge_management_types[] = {
- [IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
- [IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 },
-/*
- [IFLA_BRIDGE_VLAN_INFO] = { .type = NETLINK_TYPE_BINARY,
- .len = sizeof(struct bridge_vlan_info), },
-*/
-};
-
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 },
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "netlink-util.h"
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
- _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
const struct ether_addr *mac, unsigned mtu) {
- _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
int rtnl_log_parse_error(int r);
int rtnl_log_create_error(int r);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_netlink*, sd_netlink_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_netlink_message*, sd_netlink_message_unref);
-
-#define _cleanup_netlink_unref_ _cleanup_(sd_netlink_unrefp)
-#define _cleanup_netlink_message_unref_ _cleanup_(sd_netlink_message_unrefp)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "util.h"
static int sd_netlink_new(sd_netlink **ret) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
assert_return(ret, -EINVAL);
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);
}
int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
socklen_t addrlen;
int r;
if (r < 0)
return -errno;
+ if (rtnl->sockaddr.nl.nl_family != AF_NETLINK)
+ return -EINVAL;
+
rtnl->fd = fd;
*ret = rtnl;
}
int sd_netlink_open_fd(sd_netlink **ret, int fd) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int r;
assert_return(ret, -EINVAL);
rtnl->fd = fd;
r = socket_bind(rtnl);
- if (r < 0)
+ 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;
}
static int process_timeout(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
struct reply_callback *c;
usec_t n;
int r;
}
static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(rtnl);
}
int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) {
- RTNL_DONT_DESTROY(rtnl);
+ NETLINK_DONT_DESTROY(rtnl);
int r;
assert_return(rtnl, -EINVAL);
received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
if (received_serial == serial) {
- _cleanup_netlink_message_unref_ sd_netlink_message *incoming = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
uint16_t type;
incoming = rtnl->rqueue[i];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-netlink.h"
#include "ether-addr-util.h"
-#include "event-util.h"
#include "macro.h"
#include "missing.h"
#include "netlink-util.h"
#include "util.h"
static void test_message_link_bridge(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+ _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);
}
static void test_link_configure(sd_netlink *rtnl, int ifindex) {
- _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+ _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;
}
static void test_route(void) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req;
struct in_addr addr, addr_data;
uint32_t index = 2, u32_data;
int r;
}
static void test_event_loop(int ifindex) {
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _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");
}
static void test_async(int ifindex) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *r = NULL;
+ _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;
}
static void test_pipe(int ifindex) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- _cleanup_netlink_message_unref_ sd_netlink_message *m1 = NULL, *m2 = NULL;
+ _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);
}
static void test_container(void) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint16_t u16_data;
uint32_t u32_data;
const char *string_data;
}
static void test_match(void) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
assert_se(sd_netlink_open(&rtnl) >= 0);
}
static void test_get_addresses(sd_netlink *rtnl) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _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);
}
static void test_message(void) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-network.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_network_monitor*, sd_network_monitor_unref);
-#define _cleanup_network_monitor_unref_ _cleanup_(sd_network_monitor_unrefp)
-
bool network_is_online(void);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return network_get_strv("NTP", ret);
}
-_public_ int sd_network_get_domains(char ***ret) {
+_public_ int sd_network_get_search_domains(char ***ret) {
return network_get_strv("DOMAINS", ret);
}
-_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
+_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(state, -EINVAL);
+ assert_return(ret, -EINVAL);
- if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
+ if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0)
return -ENOMEM;
- r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
+ r = parse_env_file(p, NEWLINE, field, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
if (isempty(s))
return -ENODATA;
- *state = s;
+ *ret = s;
s = NULL;
return 0;
}
-_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
- _cleanup_free_ char *s = NULL, *p = NULL;
+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(filename, -EINVAL);
+ assert_return(ret, -EINVAL);
if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
return -ENOMEM;
- r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL);
+ r = parse_env_file(p, NEWLINE, key, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
return r;
- if (isempty(s))
- return -ENODATA;
-
- *filename = s;
- s = NULL;
+ if (isempty(s)) {
+ *ret = NULL;
+ return 0;
+ }
- return 0;
-}
+ a = strv_split(s, " ");
+ if (!a)
+ return -ENOMEM;
-_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
- _cleanup_free_ char *s = NULL, *p = NULL;
- int r;
+ strv_uniq(a);
+ r = strv_length(a);
- assert_return(ifindex > 0, -EINVAL);
- assert_return(state, -EINVAL);
+ *ret = a;
+ a = NULL;
- if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
- return -ENOMEM;
+ return r;
+}
- r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
- if (r == -ENOENT)
- return -ENODATA;
- if (r < 0)
- return r;
- if (isempty(s))
- return -ENODATA;
+_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
+ return network_link_get_string(ifindex, "ADMIN_STATE", state);
+}
- *state = s;
- s = NULL;
+_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
+ return network_link_get_string(ifindex, "NETWORK_FILE", filename);
+}
- return 0;
+_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) {
- _cleanup_free_ char *s = NULL, *p = NULL;
- int r;
-
- assert_return(ifindex > 0, -EINVAL);
- assert_return(llmnr, -EINVAL);
-
- if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
- return -ENOMEM;
+ return network_link_get_string(ifindex, "LLMNR", llmnr);
+}
- r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
- if (r == -ENOENT)
- return -ENODATA;
- if (r < 0)
- return r;
- if (isempty(s))
- return -ENODATA;
+_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
+ return network_link_get_string(ifindex, "MDNS", mdns);
+}
- *llmnr = s;
- s = NULL;
+_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
+ return network_link_get_string(ifindex, "DNSSEC", dnssec);
+}
- return 0;
+_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) {
}
int sd_network_link_get_timezone(int ifindex, 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/%d", ifindex) < 0)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE, "TIMEZONE", &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_get_link_strv(const char *key, int ifindex, 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;
+ return network_link_get_string(ifindex, "TIMEZONE", ret);
}
_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
- return network_get_link_strv("DNS", ifindex, ret);
+ return network_link_get_strv(ifindex, "DNS", ret);
}
_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
- return network_get_link_strv("NTP", ifindex, ret);
+ return network_link_get_strv(ifindex, "NTP", ret);
}
-_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
- return network_get_link_strv("DOMAINS", ifindex, 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_carrier_bound_to(int ifindex, char ***ret) {
- return network_get_link_strv("CARRIER_BOUND_TO", ifindex, 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_by(int ifindex, char ***ret) {
- return network_get_link_strv("CARRIER_BOUND_BY", ifindex, 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_wildcard_domain(int ifindex) {
- int r;
- _cleanup_free_ char *p = NULL, *s = NULL;
-
- assert_return(ifindex > 0, -EINVAL);
-
- if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
- if (r == -ENOENT)
- return -ENODATA;
- if (r < 0)
- return r;
- if (isempty(s))
- return -ENODATA;
-
- return parse_boolean(s);
+_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) {
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-resolve.h"
-
-#include "util.h"
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve*, sd_resolve_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve_query*, sd_resolve_query_unref);
-
-#define _cleanup_resolve_unref_ _cleanup_(sd_resolve_unrefp)
-#define _cleanup_resolve_query_unref_ _cleanup_(sd_resolve_query_unrefp)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "io-util.h"
#include "list.h"
#include "missing.h"
-#include "resolve-util.h"
#include "socket-util.h"
#include "util.h"
static void resolve_query_disconnect(sd_resolve_query *q);
#define RESOLVE_DONT_DESTROY(resolve) \
- _cleanup_resolve_unref_ _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
+ _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
static int send_died(int out_fd) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "macro.h"
-#include "resolve-util.h"
#include "socket-util.h"
#include "string-util.h"
}
int main(int argc, char *argv[]) {
- _cleanup_resolve_query_unref_ sd_resolve_query *q1 = NULL, *q2 = NULL;
- _cleanup_resolve_unref_ sd_resolve *resolve = NULL;
+ _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 = {
if (r < 0)
log_error_errno(r, "sd_resolve_getnameinfo(): %m");
- /* Wait until the two queries are completed */
- while (sd_resolve_query_is_done(q1) == 0 ||
- sd_resolve_query_is_done(q2) == 0) {
-
+ /* 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");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *udev_device_old) {
- sd_device *device_old = NULL;
-
assert(udev_device);
- if (udev_device_old)
- device_old = udev_device_old->device;
-
- device_ensure_usec_initialized(udev_device->device, device_old);
+ 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) {
* Returns: 0 on success, otherwise a negative error value.
*/
_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
- _cleanup_device_unref_ sd_device *device = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
int r;
assert_return(udev_enumerate, -EINVAL);
* Returns: a hwdb context.
**/
_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb_internal = NULL;
struct udev_hwdb *hwdb;
int r;
#define _LIBUDEV_PRIVATE_H_
#include <signal.h>
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include "libudev.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int set_locale(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
}
static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *map, *toggle_map;
int r;
}
static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *layout, *model, *variant, *options;
int r;
}
int main(int argc, char*argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-util.h"
#include "def.h"
#include "env-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
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_bus_message_unref_ sd_bus_message *m = 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;
}
static int vconsole_reload(sd_bus *bus) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
if (!fgets(line, sizeof(line), f)) {
if (ferror(f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
assert(c);
int main(int argc, char *argv[]) {
_cleanup_(context_free) Context context = {};
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
} arg_action = ACTION_INHIBIT;
static int inhibit(sd_bus *bus, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
int fd;
}
static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *what, *who, *why, *mode;
unsigned int uid, pid;
unsigned n = 0;
}
int main(int argc, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
arg_all * OUTPUT_SHOW_ALL |
arg_full * OUTPUT_FULL_WIDTH |
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR;
+ colors_enabled() * OUTPUT_COLOR;
}
static int list_sessions(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int list_users(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int list_seats(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_free_ char *path = NULL;
const char *cgroup;
int r;
}
static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
}
for (i = 1; i < argc; i++) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+ _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(
}
for (i = 1; i < argc; i++) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+ _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;
}
for (i = 1; i < argc; i++) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+ _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(
}
static int activate(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
char *short_argv[3];
int r, i;
}
static int kill_session(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int enable_linger(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
char* short_argv[3];
bool b;
}
static int terminate_user(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int kill_user(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int attach(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int flush_devices(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
}
static int lock_sessions(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
}
static int terminate_seat(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
#include "libudev.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
[HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
};
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
InhibitWhat inhibit_operation;
Inhibitor *offending = NULL;
bool supported;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
_HANDLE_ACTION_INVALID = -1
} HandleAction;
-#include "logind.h"
#include "logind-inhibit.h"
+#include "logind.h"
int manager_handle_action(
Manager *m,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
p = getpwuid(uid);
if (!p)
- return errno ? -errno : -ENOENT;
+ return errno > 0 ? -errno : -ENOENT;
return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
}
}
int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
Session *session;
int r;
assert(ret);
if (uid == UID_INVALID) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
return r;
seat = session->seat;
-
if (!seat)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
} else {
}
static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Session *session;
Iterator i;
}
static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
User *user;
Iterator i;
}
static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Seat *seat;
Iterator i;
}
static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Inhibitor *inhibitor;
Iterator i;
}
if (leader == 0) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
if (uid == UID_INVALID) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
errno = 0;
pw = getpwuid(uid);
if (!pw)
- return errno ? -errno : -ENOENT;
+ return errno > 0 ? -errno : -ENOENT;
r = bus_verify_polkit_async(
message,
return -ENOMEM;
mkdir_p_label("/etc/udev/rules.d", 0755);
- mac_selinux_init("/etc");
r = write_string_file_atomic_label(file, rule);
if (r < 0)
return r;
const char *unit_name,
sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
char *c = NULL;
const char *p;
int r;
int manager_dispatch_delayed(Manager *manager, bool timeout) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Inhibitor *offending = NULL;
int r;
const char *action_ignore_inhibit,
sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
bool multiple_sessions, blocked;
uid_t uid;
int r;
log_info("Creating /run/nologin, blocking further logins...");
- r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+ 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
uint64_t usec,
void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Manager *m = userdata;
const char *target;
int r;
static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
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.poweroff";
- action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
+ 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 = 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;
+ const char *tty = NULL;
(void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
(void) sd_bus_creds_get_tty(creds, &tty);
reset_scheduled_shutdown(m);
if (cancelled) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *tty = NULL;
uid_t uid = 0;
int r;
const char *sleep_verb,
sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
bool multiple_sessions, challenge, blocked;
const char *result = NULL;
uid_t uid;
}
static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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;
if (streq(result, "done"))
r = session_send_create_reply(s, NULL);
else {
- _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+ _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);
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,
sd_bus_error *error,
char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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,
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;
+ return strdup_job(reply, job);
}
int manager_start_scope(
sd_bus_error *error,
char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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,
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;
+ return strdup_job(reply, job);
}
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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,
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;
+ return strdup_job(reply, job);
}
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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,
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;
-
+ *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;
+ return strdup_job(reply, job);
}
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
}
int manager_unit_is_active(Manager *manager, const char *unit) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_free_ char *path = NULL;
const char *state;
int r;
}
int manager_job_is_active(Manager *manager, const char *path) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(m);
if (streq(path, "/org/freedesktop/login1/seat/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *name;
Session *session;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
assert(vtnr >= 1);
- snprintf(p, sizeof(p), "/dev/tty%u", vtnr);
+ xsprintf(p, "/dev/tty%u", vtnr);
fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return -errno;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
Session *s = userdata;
uid_t uid;
int r, b;
}
static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
Session *s = userdata;
int r, force;
uid_t uid;
assert(m);
if (streq(path, "/org/freedesktop/login1/session/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
}
int session_send_create_reply(Session *s, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
_cleanup_close_ int fifo_fd = -1;
_cleanup_free_ char *p = NULL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
};
static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *path = NULL;
const char *t = NULL;
uint32_t major, minor;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(s->user);
if (!s->scope) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *scope, *job = NULL;
const char *description;
}
static int session_stop_scope(Session *s, bool force) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job = NULL;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef enum KillWho KillWho;
#include "list.h"
-#include "logind-user.h"
#include "login-util.h"
+#include "logind-user.h"
typedef enum SessionState {
SESSION_OPENING, /* Session scope is being created */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(m);
if (streq(path, "/org/freedesktop/login1/user/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
message = sd_bus_get_current_message(bus);
message = sd_bus_get_current_message(bus);
if (message) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int user_start_slice(User *u) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *description;
char *job;
int r;
u->manager->user_tasks_max,
&error,
&job);
- if (r < 0) {
- /* we don't fail due to this, let's try to continue */
- if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
- log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", u->slice, bus_error_message(&error, r), error.name);
- } else {
+ 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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
int r;
}
static int user_stop_slice(User *u) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
int r;
}
static int user_stop_service(User *u) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
int r;
errno = 0;
ul = strtoul(rvalue, &f, 10);
- if (errno != 0 || f != e) {
+ if (errno > 0 || f != e) {
log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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(4096);
+ m->user_tasks_max = UINT64_C(12288);
m->devices = hashmap_new(&string_hash_ops);
m->seats = hashmap_new(&string_hash_ops);
}
static int manager_connect_bus(Manager *m) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
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
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=yes
-#UserTasksMax=4096
+#UserTasksMax=12288
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int flags,
int argc, const char **argv) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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,
*seat = NULL,
*type = NULL, *class = NULL,
*class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int session_fd = -1, existing, r;
bool debug = false, remote;
struct passwd *pw;
int flags,
int argc, const char **argv) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "util.h"
static int inhibit(sd_bus *bus, const char *what) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static void print_inhibitors(sd_bus *bus) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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 main(int argc, char*argv[]) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int fd1, fd2;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
if (arg_commit)
r = machine_id_commit(arg_root);
else
- r = machine_id_setup(arg_root);
+ r = machine_id_setup(arg_root, SD_ID128_NULL);
finish:
free(arg_root);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Machine *m = userdata;
int r;
}
int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **l = NULL;
Machine *m = userdata;
char **k, **v;
}
int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *pty_name = NULL;
_cleanup_close_ int master = -1;
Machine *m = userdata;
break;
case MACHINE_CONTAINER: {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
char *address;
r = sd_bus_new(&bus);
}
int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *pty_name = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = 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;
}
int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *tm = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *tm = NULL;
_cleanup_free_ char *pty_name = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = 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;
First, we start by creating a private playground in /tmp,
that we can mount MS_SLAVE. (Which is necessary, since
- MS_MOUNT cannot be applied to mounts with MS_SHARED parent
+ MS_MOVE cannot be applied to mounts with MS_SHARED parent
mounts.) */
if (!mkdtemp(mount_slave))
}
static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
MachineOperation *o = userdata;
int r;
assert(m);
if (streq(path, "/org/freedesktop/machine1/machine/self")) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
pid_t pid;
}
int machine_send_create_reply(Machine *m, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
_cleanup_free_ char *p = NULL;
assert(m);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int machine_stop_scope(Machine *m) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job = NULL;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "cgroup-util.h"
#include "copy.h"
#include "env-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "hostname-util.h"
#include "import-util.h"
static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_force = false;
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static const char* arg_dkr_index_url = NULL;
static const char* arg_format = NULL;
static const char *arg_uid = NULL;
static char **arg_setenv = NULL;
arg_all * OUTPUT_SHOW_ALL |
arg_full * OUTPUT_FULL_WIDTH |
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
+ colors_enabled() * OUTPUT_COLOR |
!arg_quiet * OUTPUT_WARN_CUTOFF;
}
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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_free_ MachineInfo *machines = NULL;
const char *name, *class, *service, *object;
size_t n_machines = 0, n_allocated = 0, j;
static int list_images(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
assert(bus);
}
static int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *k, *v, *pretty = NULL;
int r;
static int show_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
static int show_image(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int kill_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int terminate_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int copy_files(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int bind_mount(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
}
static int login_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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_bus_slot_unref_ sd_bus_slot *slot = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
}
static int shell_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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_bus_slot_unref_ sd_bus_slot *slot = NULL;
- _cleanup_event_unref_ sd_event *event = 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;
}
static int remove_image(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int rename_image(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
}
static int clone_image(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
}
static int read_only_image(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int b = true, r;
}
static int start_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
return log_oom();
for (i = 1; i < argc; i++) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *unit = NULL;
const char *object;
return log_oom();
}
- r = bus_wait_for_jobs(w, arg_quiet);
+ r = bus_wait_for_jobs(w, arg_quiet, NULL);
if (r < 0)
return r;
}
static int enable_machine(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_event_unref_ sd_event* event = NULL;
+ _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;
}
static int import_tar(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
}
static int import_raw(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
}
static int export_tar(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
}
static int export_raw(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
}
static int pull_tar(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
}
static int pull_raw(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _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;
return transfer_image_common(bus, m);
}
-static int pull_dkr(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- const char *local, *remote, *tag;
- sd_bus *bus = userdata;
- int r;
-
- if (arg_verify != IMPORT_VERIFY_NO) {
- log_error("Imports from DKR do not support image verification, please pass --verify=no.");
- return -EINVAL;
- }
-
- remote = argv[1];
- tag = strchr(remote, ':');
- if (tag) {
- remote = strndupa(remote, tag - remote);
- tag++;
- }
-
- if (!dkr_name_is_valid(remote)) {
- log_error("DKR name '%s' is invalid.", remote);
- return -EINVAL;
- }
- if (tag && !dkr_tag_is_valid(tag)) {
- log_error("DKR tag '%s' is invalid.", remote);
- return -EINVAL;
- }
-
- if (argc >= 3)
- local = argv[2];
- else {
- local = strchr(remote, '/');
- if (local)
- local++;
- else
- local = remote;
- }
-
- if (isempty(local) || streq(local, "-"))
- local = NULL;
-
- if (local) {
- 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",
- "PullDkr");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(
- m,
- "sssssb",
- arg_dkr_index_url,
- remote,
- tag,
- 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;
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_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int cancel_transfer(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
}
static int set_limit(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
uint64_t limit;
int r;
" 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"
- " --dkr-index-url=URL Specify the index URL to use for DKR image\n"
- " downloads\n\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"
"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"
- " pull-dkr REMOTE [NAME] Download a DKR container 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"
ARG_NO_ASK_PASSWORD,
ARG_VERIFY,
ARG_FORCE,
- ARG_DKR_INDEX_URL,
ARG_FORMAT,
ARG_UID,
ARG_SETENV,
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "force", no_argument, NULL, ARG_FORCE },
- { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
{ "format", required_argument, NULL, ARG_FORMAT },
{ "uid", required_argument, NULL, ARG_UID },
{ "setenv", required_argument, NULL, ARG_SETENV },
arg_force = true;
break;
- case ARG_DKR_INDEX_URL:
- if (!http_url_is_valid(optarg)) {
- log_error("Index URL is invalid: %s", optarg);
- return -EINVAL;
- }
-
- arg_dkr_index_url = optarg;
- break;
-
case ARG_FORMAT:
if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
log_error("Unknown format: %s", optarg);
{ "export-raw", 2, 3, 0, export_raw },
{ "pull-tar", 2, 3, 0, pull_tar },
{ "pull-raw", 2, 3, 0, pull_raw },
- { "pull-dkr", 2, 3, 0, pull_dkr },
{ "list-transfers", VERB_ANY, 1, 0, list_transfers },
{ "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer },
{ "set-limit", 2, 3, 0, set_limit },
}
int main(int argc, char*argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
return -EINVAL;
if (pid == 0) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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)
}
static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Machine *machine;
Iterator i;
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
if (leader == 0) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _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)
}
static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(image_hashmap_freep) Hashmap *images = NULL;
Manager *m = userdata;
Image *image;
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,
if (r < 0)
return r;
- 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");
+ /* 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);
if (k < 0 && feof(f))
break;
if (k != 3) {
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EIO;
if (k < 0 && feof(f))
break;
if (k != 3) {
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EIO;
if (k < 0 && feof(f))
break;
if (k != 3) {
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EIO;
if (k < 0 && feof(f))
break;
if (k != 3) {
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EIO;
if (streq(result, "done"))
machine_send_create_reply(machine, NULL);
else {
- _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+ _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);
sd_bus_error *error,
char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
int r;
assert(manager);
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)
}
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
assert(manager);
}
int manager_unit_is_active(Manager *manager, const char *unit) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_free_ char *path = NULL;
const char *state;
int r;
}
int manager_job_is_active(Manager *manager, const char *path) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int manager_connect_bus(Manager *m) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Manager Manager;
-#include "machine.h"
-#include "machine-dbus.h"
#include "image-dbus.h"
+#include "machine-dbus.h"
+#include "machine.h"
struct Manager {
sd_event *event;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
}
static int list_links(int argc, char *argv[], void *userdata) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _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;
for (i = 0; i < c; i++) {
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
- _cleanup_device_unref_ sd_device *d = 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)];
if (memcmp(mac, "\0\0\0", 3) == 0)
return -EINVAL;
- snprintf(modalias, sizeof(modalias), "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac));
+ 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)
int family,
union in_addr_union *gateway,
char **gateway_description) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *m;
int r;
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),
sd_netlink *rtnl,
sd_hwdb *hwdb,
const char *name) {
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
+ _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_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_device_unref_ sd_device *d = 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;
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;
have_mac = false;
}
- sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
+ (void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
- sd_network_link_get_operational_state(ifindex, &operational_state);
+ (void) sd_network_link_get_operational_state(ifindex, &operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
- sd_network_link_get_setup_state(ifindex, &setup_state);
+ (void) sd_network_link_get_setup_state(ifindex, &setup_state);
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
- sd_network_link_get_dns(ifindex, &dns);
- sd_network_link_get_domains(ifindex, &domains);
- r = sd_network_link_get_wildcard_domain(ifindex);
- if (r > 0) {
- char *wildcard;
-
- wildcard = strdup("*");
- if (!wildcard)
- return log_oom();
-
- if (strv_consume(&domains, wildcard) < 0)
- return log_oom();
- }
+ (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);
+ (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);
+ (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);
+ (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);
+ (void) sd_device_get_property_value(d, "ID_MODEL", &model);
}
link_get_type_string(iftype, d, &t);
dump_addresses(rtnl, " Address: ", ifindex);
dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
- if (!strv_isempty(dns))
- dump_list(" DNS: ", dns);
- if (!strv_isempty(domains))
- dump_list(" Domain: ", domains);
+ dump_list(" DNS: ", dns);
+ dump_list(" Search Domains: ", search_domains);
+ dump_list(" Route Domains: ", route_domains);
- (void) sd_network_link_get_ntp(ifindex, &ntp);
- if (!strv_isempty(ntp))
- dump_list(" NTP: ", ntp);
+ dump_list(" NTP: ", ntp);
- if (!strv_isempty(carrier_bound_to))
- dump_list("Carrier Bound To: ", carrier_bound_to);
-
- if (!strv_isempty(carrier_bound_by))
- dump_list("Carrier Bound By: ", carrier_bound_by);
+ 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)
}
static int link_status(int argc, char *argv[], void *userdata) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char **name;
int r;
if (argc <= 1 && !arg_all) {
_cleanup_free_ char *operational_state = NULL;
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = 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",
+ 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);
+ dump_addresses(rtnl, " Address: ", 0);
+ dump_gateways(rtnl, hwdb, " Gateway: ", 0);
sd_network_get_dns(&dns);
- if (!strv_isempty(dns))
- dump_list(" DNS: ", dns);
+ dump_list(" DNS: ", dns);
+
+ sd_network_get_search_domains(&search_domains);
+ dump_list("Search Domains: ", search_domains);
- sd_network_get_domains(&domains);
- if (!strv_isempty(domains))
- dump_list(" Domain: ", domains);
+ sd_network_get_route_domains(&route_domains);
+ dump_list(" Route Domains: ", route_domains);
sd_network_get_ntp(&ntp);
- if (!strv_isempty(ntp))
- dump_list(" NTP: ", ntp);
+ dump_list(" NTP: ", ntp);
return 0;
}
pager_open_if_enabled();
if (arg_all) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_free_ LinkInfo *links = NULL;
int c, i;
}
static int link_lldp_status(int argc, char *argv[], void *userdata) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct AddressPool AddressPool;
+#include "in-addr-util.h"
#include "networkd.h"
struct AddressPool {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int address_remove(Address *address, Link *link,
sd_netlink_message_handler_t callback) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(address);
}
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(address);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Address Address;
-#include "networkd.h"
-#include "networkd-network.h"
#include "networkd-link.h"
+#include "networkd-network.h"
+#include "networkd.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static int link_set_dhcp_routes(Link *link) {
struct in_addr gateway;
- struct sd_dhcp_route *static_routes;
+ _cleanup_free_ sd_dhcp_route **static_routes = NULL;
int r, n, i;
assert(link);
route->family = AF_INET;
route->protocol = RTPROT_DHCP;
- route->gw.in = static_routes[i].gw_addr;
- route->dst.in = static_routes[i].dst_addr;
- route->dst_prefixlen = static_routes[i].dst_prefixlen;
+ 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);
log_link_warning(link, "DHCP lease lost");
- if (link->network->dhcp_routes) {
- struct sd_dhcp_route *routes;
+ 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);
r = route_new(&route);
if (r >= 0) {
route->family = AF_INET;
- route->gw.in = routes[i].gw_addr;
- route->dst.in = routes[i].dst_addr;
- route->dst_prefixlen = routes[i].dst_prefixlen;
+ 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);
}
}
- if (link->network->dhcp_mtu) {
+ if (link->network->dhcp_use_mtu) {
uint16_t mtu;
r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
}
}
- if (link->network->dhcp_hostname) {
+ if (link->network->dhcp_use_hostname) {
const char *hostname = NULL;
- if (link->network->hostname)
- hostname = link->network->hostname;
+ if (link->network->dhcp_hostname)
+ hostname = link->network->dhcp_hostname;
else
(void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
}
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
+ link_dirty(link);
link->dhcp4_configured = false;
return 0;
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)
NULL);
link->dhcp_lease = sd_dhcp_lease_ref(lease);
+ link_dirty(link);
- if (link->network->dhcp_mtu) {
+ if (link->network->dhcp_use_mtu) {
uint16_t mtu;
r = sd_dhcp_lease_get_mtu(lease, &mtu);
}
}
- if (link->network->dhcp_hostname) {
+ if (link->network->dhcp_use_hostname) {
const char *hostname = NULL;
- if (link->network->hostname)
- hostname = link->network->hostname;
+ if (link->network->dhcp_hostname)
+ hostname = link->network->dhcp_hostname;
else
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
}
}
- if (link->network->dhcp_timezone) {
+ if (link->network->dhcp_use_timezone) {
const char *tz = NULL;
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
return r;
}
- if (link->network->dhcp_mtu) {
+ if (link->network->dhcp_use_mtu) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
- DHCP_OPTION_INTERFACE_MTU);
+ SD_DHCP_OPTION_INTERFACE_MTU);
if (r < 0)
return r;
}
- if (link->network->dhcp_routes) {
+ if (link->network->dhcp_use_routes) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
- DHCP_OPTION_STATIC_ROUTE);
+ SD_DHCP_OPTION_STATIC_ROUTE);
if (r < 0)
return r;
r = sd_dhcp_client_set_request_option(link->dhcp_client,
- DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
+ 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, DHCP_OPTION_NTP_SERVER);
+ /* 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, DHCP_OPTION_NEW_TZDB_TIMEZONE);
+ 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_sendhost) {
+ if (link->network->dhcp_send_hostname) {
_cleanup_free_ char *hostname = NULL;
const char *hn = NULL;
- if (!link->network->hostname) {
+ if (!link->network->dhcp_hostname) {
hostname = gethostname_malloc();
if (!hostname)
return -ENOMEM;
hn = hostname;
} else
- hn = link->network->hostname;
+ hn = link->network->dhcp_hostname;
if (!is_localhost(hn)) {
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/* 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_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
sd_netlink *rtnl;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct FdbEntry FdbEntry;
-#include "networkd.h"
#include "networkd-network.h"
+#include "networkd.h"
struct FdbEntry {
Network *network;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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;
- int r;
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;
if (!p)
return -ENOMEM;
- r = strv_consume(&l, p);
- if (r < 0)
- return r;
+ l[c++] = p;
}
+ l[c] = NULL;
*nodes = l;
l = NULL;
assert(found);
r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
- if (r < 0)
+ if (r <= 0)
return 0;
r = parse_ifindex(identifier, &ifindex);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "bus-util.h"
#include "dhcp-lease-internal.h"
-#include "event-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "netlink-util.h"
free(link->lease_file);
- sd_lldp_free(link->lldp);
+ sd_lldp_unref(link->lldp);
free(link->lldp_file);
addresses[n_addresses++] = ia;
}
- if (link->network->dhcp_dns &&
+ if (link->network->dhcp_use_dns &&
link->dhcp_lease) {
const struct in_addr *da = NULL;
int n;
addresses[n_addresses++] = ia;
}
- if (link->network->dhcp_ntp &&
+ if (link->network->dhcp_use_ntp &&
link->dhcp_lease) {
const struct in_addr *da = NULL;
int n;
}
int link_set_mtu(Link *link, uint32_t mtu) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
}
static int link_set_bridge(Link *link) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
}
static int link_up(Link *link) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
uint8_t ipv6ll_mode;
int r;
}
static int link_down(Link *link) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(link->network);
assert(link->state == LINK_STATE_PENDING);
- r = link_drop_foreign_config(link);
- if (r < 0)
- return r;
+ /* 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)
}
int link_initialized(Link *link, struct udev_device *device) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
if (r < 0) {
log_link_debug_errno(link, r, "Failed to extract next address string: %m");
continue;
- } if (r == 0)
+ }
+ if (r == 0)
break;
prefixlen_str = strchr(address_str, '/');
}
if (routes) {
+ p = routes;
+
for (;;) {
Route *route;
_cleanup_free_ char *route_str = NULL;
- _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+ _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
usec_t lifetime;
char *prefixlen_str;
int family;
if (r < 0) {
log_link_debug_errno(link, r, "Failed to extract next route string: %m");
continue;
- } if (r == 0)
+ }
+ if (r == 0)
break;
prefixlen_str = strchr(route_str, '/');
link->ipv6ll_address = *address;
link_check_ready(link);
- if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+ 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);
assert(link);
- if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+ 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);
admin_state, oper_state);
if (link->network) {
- char **address, **domain;
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);
fputs("DNS=", f);
space = false;
- STRV_FOREACH(address, link->network->dns) {
- if (space)
- fputc(' ', f);
- fputs(*address, f);
- space = true;
- }
+ fputstrv(f, link->network->dns, NULL, &space);
- if (link->network->dhcp_dns &&
+ if (link->network->dhcp_use_dns &&
link->dhcp_lease) {
const struct in_addr *addresses;
}
}
- if (link->network->dhcp_dns && dhcp6_lease) {
+ if (link->network->dhcp_use_dns && dhcp6_lease) {
struct in6_addr *in6_addrs;
r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
fputs("NTP=", f);
space = false;
- STRV_FOREACH(address, link->network->ntp) {
- if (space)
- fputc(' ', f);
- fputs(*address, f);
- space = true;
- }
+ fputstrv(f, link->network->ntp, NULL, &space);
- if (link->network->dhcp_ntp &&
+ if (link->network->dhcp_use_ntp &&
link->dhcp_lease) {
const struct in_addr *addresses;
}
}
- if (link->network->dhcp_ntp && dhcp6_lease) {
+ if (link->network->dhcp_use_ntp && dhcp6_lease) {
struct in6_addr *in6_addrs;
char **hosts;
- char **hostname;
r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
&in6_addrs);
}
r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
- if (r > 0) {
- STRV_FOREACH(hostname, hosts) {
- if (space)
- fputc(' ', f);
- fputs(*hostname, f);
- space = true;
- }
- }
+ if (r > 0)
+ fputstrv(f, hosts, NULL, &space);
}
fputc('\n', f);
- fputs("DOMAINS=", f);
- space = false;
- STRV_FOREACH(domain, link->network->domains) {
- if (space)
- fputc(' ', f);
- fputs(*domain, f);
- space = true;
+ 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);
}
- if (link->network->dhcp_domains &&
- link->dhcp_lease) {
- const char *domainname;
+ fputs("DOMAINS=", f);
+ fputstrv(f, link->network->search_domains, NULL, &space);
- r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
- if (r >= 0) {
- if (space)
- fputc(' ', f);
- fputs(domainname, f);
- space = true;
- }
- }
+ if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname)
+ fputs_with_space(f, dhcp_domainname, NULL, &space);
- if (link->network->dhcp_domains && dhcp6_lease) {
- char **domains;
-
- r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
- if (r >= 0) {
- STRV_FOREACH(domain, domains) {
- if (space)
- fputc(' ', f);
- fputs(*domain, f);
- space = true;
- }
- }
- }
+ if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains)
+ fputstrv(f, dhcp6_domains, NULL, &space);
fputc('\n', f);
- fprintf(f, "WILDCARD_DOMAIN=%s\n",
- yes_no(link->network->wildcard_domain));
+ 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;
fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
space = true;
}
-
fputc('\n', f);
fputs("ROUTES=", f);
bool space = false;
fputs("CARRIER_BOUND_TO=", f);
- HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
- if (space)
- fputc(' ', f);
- fputs(carrier->ifname, f);
- space = true;
- }
+ HASHMAP_FOREACH(carrier, link->bound_to_links, i)
+ fputs_with_space(f, carrier->ifname, NULL, &space);
fputc('\n', f);
}
bool space = false;
fputs("CARRIER_BOUND_BY=", f);
- HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
- if (space)
- fputc(' ', f);
- fputs(carrier->ifname, f);
- space = true;
- }
+ HASHMAP_FOREACH(carrier, link->bound_by_links, i)
+ fputs_with_space(f, carrier->ifname, NULL, &space);
fputc('\n', f);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
_LINK_OPERSTATE_INVALID = -1
} LinkOperationalState;
-#include "networkd.h"
-#include "networkd-network.h"
#include "networkd-address.h"
+#include "networkd-network.h"
+#include "networkd.h"
struct Link {
Manager *manager;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
} else if (ifindex <= 0) {
log_warning("rtnl: received link message with invalid ifindex: %d", ifindex);
return 0;
- } else
- link_get(m, ifindex, &link);
+ }
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;
- } else
- netdev_get(m, name, &netdev);
+ }
+
+ (void) link_get(m, ifindex, &link);
+ (void) netdev_get(m, name, &netdev);
switch (type) {
case RTM_NEWLINK:
return 0;
}
-static int set_put_in_addr(Set *s, const struct in_addr *address) {
+static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) {
char *p;
int r;
if (r < 0)
return r;
- r = set_consume(s, p);
+ r = ordered_set_consume(s, p);
if (r == -EEXIST)
return 0;
return r;
}
-static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
+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 = set_put_in_addr(s, addresses+i);
+ r = ordered_set_put_in_addr(s, addresses+i);
if (r < 0)
return r;
return c;
}
-static void print_string_set(FILE *f, const char *field, Set *s) {
+static void print_string_set(FILE *f, const char *field, OrderedSet *s) {
bool space = false;
Iterator i;
char *p;
- if (set_isempty(s))
+ if (ordered_set_isempty(s))
return;
fputs(field, f);
- SET_FOREACH(p, s, i) {
- if (space)
- fputc(' ', f);
- fputs(p, f);
- space = true;
- }
+ ORDERED_SET_FOREACH(p, s, i)
+ fputs_with_space(f, p, NULL, &space);
+
fputc('\n', f);
}
static int manager_save(Manager *m) {
- _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
+ _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;
assert(m->state_file);
/* We add all NTP and DNS server to a set, to filter out duplicates */
- dns = set_new(&string_hash_ops);
+ dns = ordered_set_new(&string_hash_ops);
if (!dns)
return -ENOMEM;
- ntp = set_new(&string_hash_ops);
+ ntp = ordered_set_new(&string_hash_ops);
if (!ntp)
return -ENOMEM;
- domains = set_new(&string_hash_ops);
- if (!domains)
+ 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) {
continue;
/* First add the static configured entries */
- r = set_put_strdupv(dns, link->network->dns);
+ 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 = set_put_strdupv(ntp, link->network->ntp);
+ r = ordered_set_put_strdupv(search_domains, link->network->search_domains);
if (r < 0)
return r;
- r = set_put_strdupv(domains, link->network->domains);
+ r = ordered_set_put_strdupv(route_domains, link->network->route_domains);
if (r < 0)
return r;
continue;
/* Secondly, add the entries acquired via DHCP */
- if (link->network->dhcp_dns) {
+ 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 = set_put_in_addrv(dns, addresses, r);
+ 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_ntp) {
+ 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 = set_put_in_addrv(ntp, addresses, r);
+ 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_domains) {
+ 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) {
- r = set_put_strdup(domains, domainname);
+
+ 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)
print_string_set(f, "DNS=", dns);
print_string_set(f, "NTP=", ntp);
- print_string_set(f, "DOMAINS=", domains);
+ print_string_set(f, "DOMAINS=", search_domains);
+ print_string_set(f, "ROUTE_DOMAINS=", route_domains);
r = fflush_and_check(f);
if (r < 0)
}
int manager_rtnl_enumerate_links(Manager *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *link;
int r;
}
int manager_rtnl_enumerate_addresses(Manager *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *addr;
int r;
}
int manager_rtnl_enumerate_routes(Manager *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *route;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
}
address->prefixlen = prefixlen;
- address->flags = IFA_F_NOPREFIXROUTE;
+ address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
address->cinfo.ifa_prefered = lifetime_preferred;
address->cinfo.ifa_valid = lifetime_valid;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
Bridge *b;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(link);
assert(m);
assert(t);
- assert(t->family == AF_INET);
+ assert(t->family == AF_INET || t->family != -1);
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
assert(link);
assert(m);
assert(t);
- assert(t->family == AF_INET);
+ assert(t->family == AF_INET || t->family != -1);
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
t = GRETAP(netdev);
assert(t);
- assert(t->family == AF_INET);
+ assert(t->family == AF_INET || t->family != -1);
assert(link);
assert(m);
assert(t);
- if (t->remote.in.s_addr == INADDR_ANY) {
- log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
- return -EINVAL;
- }
-
- if (t->family != AF_INET && t->family != AF_INET6) {
+ 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;
}
assert(rvalue);
assert(data);
- 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);
+ if (streq(rvalue, "any")) {
+ t->family = 0;
return 0;
- }
+ } else {
- 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;
+ 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;
assert(t);
t->pmtudisc = true;
+ t->family = -1;
}
static void sit_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
+ t->family = -1;
}
static void vti_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
+ t->family = -1;
}
static void ip6gre_init(NetDev *n) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
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 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
typedef struct VxLan VxLan;
-#include "networkd-netdev.h"
-
#include "in-addr-util.h"
+#include "networkd-netdev.h"
#define VXLAN_VID_MAX (1u << 24) - 1
unsigned ttl;
unsigned max_fdb;
+ uint16_t dest_port;
+
usec_t fdb_ageing;
bool learning;
bool udp6zerocsumtx;
bool udp6zerocsumrx;
bool group_policy;
+
+ struct ifla_vxlan_port_range port_range;
};
extern const NetDevVTable vxlan_vtable;
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
static void netdev_cancel_callbacks(NetDev *netdev) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
netdev_join_callback *callback;
if (!netdev)
}
static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_handler_t callback) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(netdev);
if (r < 0)
return r;
} else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
if (r >= 0)
log_netdev_debug(netdev, "Created");
} else {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
typedef struct NetDev NetDev;
typedef struct NetDevVTable NetDevVTable;
-#include "networkd.h"
#include "networkd-link.h"
+#include "networkd.h"
typedef struct netdev_join_callback netdev_join_callback;
LIST_HEAD(netdev_join_callback, callbacks);
};
-#include "networkd-netdev-bridge.h"
#include "networkd-netdev-bond.h"
-#include "networkd-netdev-vlan.h"
-#include "networkd-netdev-macvlan.h"
+#include "networkd-netdev-bridge.h"
+#include "networkd-netdev-dummy.h"
#include "networkd-netdev-ipvlan.h"
-#include "networkd-netdev-vxlan.h"
-#include "networkd-netdev-veth.h"
+#include "networkd-netdev-macvlan.h"
#include "networkd-netdev-tunnel.h"
-#include "networkd-netdev-dummy.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 */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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, offsetof(Network, domains)
+Network.Domains, config_parse_domains, 0, 0
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
-Network.LLMNR, config_parse_resolve, 0, offsetof(Network, llmnr)
+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)
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_dns)
-DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
-DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
-DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
-DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname)
+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_timezone)
+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)
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_dns)
-DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
*d = '\0';
network->dhcp = ADDRESS_FAMILY_NO;
- network->dhcp_ntp = true;
- network->dhcp_dns = true;
- network->dhcp_hostname = true;
- network->dhcp_routes = true;
- network->dhcp_sendhost = true;
+ 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->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;
free(network->description);
free(network->dhcp_vendor_class_identifier);
- free(network->hostname);
+ free(network->dhcp_hostname);
free(network->mac);
strv_free(network->ntp);
strv_free(network->dns);
- strv_free(network->domains);
+ strv_free(network->search_domains);
+ strv_free(network->route_domains);
strv_free(network->bind_carrier);
netdev_unref(network->bridge);
free(network->dhcp_server_dns);
free(network->dhcp_server_ntp);
+ set_free_free(network->dnssec_negative_trust_anchors);
+
free(network);
}
route->protocol = RTPROT_STATIC;
}
- if (network->dns || network->ntp || network->domains) {
+ 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_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) {
- Network *network = userdata;
- char ***domains = data;
- char **domain;
+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;
- r = config_parse_strv(unit, filename, line, section, section_line,
- lvalue, ltype, rvalue, domains, userdata);
- if (r < 0)
- return r;
+ assert(n);
+ assert(lvalue);
+ assert(rvalue);
- strv_uniq(*domains);
- network->wildcard_domain = !!strv_find(*domains, "*");
+ if (isempty(rvalue)) {
+ n->search_domains = strv_free(n->search_domains);
+ n->route_domains = strv_free(n->route_domains);
+ return 0;
+ }
- STRV_FOREACH(domain, *domains) {
- if (is_localhost(*domain))
- log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
- else {
- r = dns_name_is_valid(*domain);
- if (r <= 0 && !streq(*domain, "*")) {
- if (r < 0)
- log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
- if (r == 0)
- log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
- } else
+ 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;
+ }
}
- strv_remove(*domains, *domain);
+ if (is_route) {
+ r = strv_extend(&n->route_domains, domain);
+ if (r < 0)
+ return log_oom();
- /* We removed one entry, make sure we don't skip the next one */
- domain--;
+ } 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;
}
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "condition.h"
+#include "resolve-util.h"
typedef struct Network Network;
-#include "networkd.h"
-#include "networkd-netdev.h"
#include "networkd-address.h"
-#include "networkd-route.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
_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;
AddressFamilyBoolean dhcp;
DCHPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
- char *hostname;
- bool dhcp_dns;
- bool dhcp_ntp;
- bool dhcp_mtu;
- bool dhcp_hostname;
- bool dhcp_domains;
- bool dhcp_sendhost;
+ 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_routes;
- bool dhcp_timezone;
+ bool dhcp_use_routes;
+ bool dhcp_use_timezone;
unsigned dhcp_route_metric;
/* DHCP Server Support */
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
- bool wildcard_domain;
- char **domains, **dns, **ntp, **bind_carrier;
+ 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);
};
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 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_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "conf-parser.h"
-#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
#include "networkd-route.h"
int route_remove(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
int route_configure(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
- _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+ _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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct Route Route;
-#include "networkd.h"
#include "networkd-network.h"
+#include "networkd.h"
struct Route {
Network *network;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return 0;
}
-
-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(resolve_support, ResolveSupport);
-
-int config_parse_resolve(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ResolveSupport *resolve = data;
- int k;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(resolve);
-
- /* 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)
- *resolve = RESOLVE_SUPPORT_YES;
- else if (k == 0)
- *resolve = RESOLVE_SUPPORT_NO;
- else {
- ResolveSupport s;
-
- s = resolve_support_from_string(rvalue);
- if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue);
- return 0;
- }
-
- *resolve = s;
- }
-
- return 0;
-}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
} AddressFamilyBoolean;
-typedef enum ResolveSupport {
- RESOLVE_SUPPORT_NO,
- RESOLVE_SUPPORT_YES,
- RESOLVE_SUPPORT_RESOLVE,
- _RESOLVE_SUPPORT_MAX,
- _RESOLVE_SUPPORT_INVALID = -1,
-} ResolveSupport;
-
-int config_parse_resolve(const char *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(const char *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* resolve_support_to_string(ResolveSupport i) _const_;
-ResolveSupport resolve_support_from_string(const char *s) _pure_;
-
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int manager_rtnl_listen(Manager *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *i;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <arpa/inet.h>
+#include "sd-bus.h"
#include "sd-event.h"
#include "sd-netlink.h"
-#include "sd-bus.h"
-#include "udev.h"
#include "hashmap.h"
#include "list.h"
+#include "udev.h"
typedef struct Manager Manager;
-#include "networkd-network.h"
#include "networkd-address-pool.h"
#include "networkd-link.h"
+#include "networkd-network.h"
#include "networkd-util.h"
struct Manager {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
"tasks",
"notify_on_release",
"cgroup.procs",
+ "cgroup.events",
"cgroup.clone_children",
"cgroup.controllers",
"cgroup.subtree_control",
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
int chown_cgroup(pid_t pid, uid_t uid_shift);
int sync_cgroup(pid_t pid, bool unified_requested);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
sd_netlink_message_handler_t handler,
union in_addr_union *exposed,
sd_netlink **ret) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int fd, r;
assert(event);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-event.h"
#include "sd-netlink.h"
-#include "list.h"
+
#include "in-addr-util.h"
+#include "list.h"
typedef struct ExposePort {
int protocol;
%struct-type
%includes
%%
-Exec.Boot, config_parse_tristate, 0, offsetof(Settings, boot)
+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.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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
const char *ifname_container,
const struct ether_addr *mac_container) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(rtnl);
char iface_name[IFNAMSIZ],
bool bridge) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
struct ether_addr mac_host, mac_container;
int r, i;
pid_t pid,
char **pairs) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
uint64_t idx = 0;
char **a, **b;
int r;
}
int setup_bridge(const char *veth_name, const char *bridge_name) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _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);
int move_network_interfaces(pid_t pid, char **ifaces) {
_cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char **i;
int r;
}
STRV_FOREACH(i, ifaces) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int ifi;
ifi = parse_interface(udev, *i);
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
_cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
unsigned idx = 0;
char **i;
int r;
}
STRV_FOREACH(i, ifaces) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
_cleanup_free_ char *n = NULL;
struct ether_addr mac;
int ifi;
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
_cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char **i;
int r;
}
STRV_FOREACH(i, ifaces) {
- _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
_cleanup_free_ char *n = NULL;
int ifi;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <net/if.h>
-
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
bool keep_unit,
const char *service) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
strempty(directory),
local_ifindex > 0 ? 1 : 0, local_ifindex);
} else {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char **i;
unsigned j;
return bus_log_create_error(r);
}
- r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
- 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);
}
STRV_FOREACH(i, properties) {
- r = sd_bus_message_open_container(m, 'r', "sv");
- if (r < 0)
- return bus_log_create_error(r);
-
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_message_close_container(m);
}
int terminate_machine(pid_t pid) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *path;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
if (!s)
return -ENOMEM;
- s->boot = -1;
+ s->start_mode = _START_MODE_INVALID;
s->personality = PERSONALITY_INVALID;
s->read_only = -1;
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);
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdio.h>
#include "macro.h"
-
-#include "nspawn-mount.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_BOOT = 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,
- _SETTINGS_MASK_ALL = (1 << 12) -1
+ 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] */
- int boot;
+ StartMode start_mode;
char **parameters;
char **environment;
char *user;
int kill_signal;
unsigned long personality;
sd_id128_t machine_id;
+ char *working_directory;
/* [Image] */
int read_only;
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return log_error_errno(errno, "Failed to set auxiliary groups: %m");
if (setresgid(gid, gid, gid) < 0)
- return log_error_errno(errno, "setregid() failed: %m");
+ return log_error_errno(errno, "setresgid() failed: %m");
if (setresuid(uid, uid, uid) < 0)
- return log_error_errno(errno, "setreuid() failed: %m");
+ return log_error_errno(errno, "setresuid() failed: %m");
if (_home) {
*_home = home;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/reboot.h>
+#include <sys/unistd.h>
+#include <sys/wait.h>
+
+#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);
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+int stub_pid1(void);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "copy.h"
#include "dev-setup.h"
#include "env-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "fileio.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"
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_slice = NULL;
static bool arg_private_network = false;
static bool arg_read_only = false;
-static bool arg_boot = 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;
" -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"
" 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, host,\n"
- " try-guest, try-host\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"
ARG_PRIVATE_USERS,
ARG_KILL_SIGNAL,
ARG_SETTINGS,
+ ARG_CHDIR,
};
static const struct option options[] = {
{ "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 },
{ "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 },
{}
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hD:u:bL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
switch (c) {
break;
case 'b':
- arg_boot = true;
- arg_settings_mask |= SETTING_BOOT;
+ 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:
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;
if (arg_share_system)
arg_register = false;
- if (arg_boot && arg_share_system) {
+ if (arg_start_mode != START_PID1 && arg_share_system) {
log_error("--boot and --share-system may not be combined.");
return -EINVAL;
}
if (!arg_parameters)
return log_oom();
- arg_settings_mask |= SETTING_BOOT;
+ arg_settings_mask |= SETTING_START_MODE;
}
/* Load all settings from .nspawn files */
return -EINVAL;
}
- if (arg_boot && arg_kill_signal <= 0)
+ if (arg_start_mode == START_BOOT && arg_kill_signal <= 0)
arg_kill_signal = SIGRTMIN+3;
return 0;
}
check = strjoina("/usr/share/zoneinfo/", z);
- check = prefix_root(dest, check);
+ 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;
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;
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 && arg_link_journal == LINK_AUTO)
+ 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) && arg_link_journal == LINK_AUTO)
+ if (isempty(id) && try)
return 0;
/* Verify validity */
return log_error_errno(r, "Failed to retrieve machine ID: %m");
if (sd_id128_equal(machine_id, this_id)) {
- log_full(arg_link_journal == LINK_AUTO ? LOG_WARNING : LOG_ERR,
+ log_full(try ? LOG_WARNING : LOG_ERR,
"Host and machine ids are equal (%s): refusing to link journals", id);
- if (arg_link_journal == LINK_AUTO)
+ if (try)
return 0;
return -EEXIST;
}
- if (arg_link_journal == LINK_NO)
- return 0;
-
r = userns_mkdir(directory, "/var", 0755, 0, 0);
if (r < 0)
return log_error_errno(r, "Failed to create /var: %m");
q = prefix_roota(directory, p);
if (path_is_mount_point(p, 0) > 0) {
- if (arg_link_journal != LINK_AUTO) {
- log_error("%s: already a mount point, refusing to use for journal", p);
- return -EEXIST;
- }
+ if (try)
+ return 0;
- 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 (arg_link_journal != LINK_AUTO) {
- log_error("%s: already a mount point, refusing to use for journal", q);
- return -EEXIST;
- }
+ if (try)
+ return 0;
- 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 (arg_link_journal == LINK_GUEST) {
if (symlink(q, p) < 0) {
- if (arg_link_journal_try) {
+ if (try) {
log_debug_errno(errno, "Failed to symlink %s to %s, skipping journal setup: %m", q, p);
return 0;
} else
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 */
- r = mkdir(p, 0755);
- if (r < 0) {
- if (arg_link_journal_try) {
+
+ 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
}
static int drop_capabilities(void) {
- return capability_bounding_set_drop(~arg_retain, false);
+ return capability_bounding_set_drop(arg_retain, false);
}
static int reset_audit_loginuid(void) {
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
log_close();
(void) fdset_close_others(fds);
- if (arg_boot) {
+ if (arg_start_mode == START_BOOT) {
char **a;
size_t m;
} else if (!strv_isempty(arg_parameters))
execvpe(arg_parameters[0], arg_parameters, env_use);
else {
- chdir(home ?: "/root");
+ if (!arg_chdir)
+ chdir(home ?: "/root");
+
execle("/bin/bash", "-bash", NULL, env_use);
execle("/bin/sh", "-sh", NULL, env_use);
}
/* Copy over bits from the settings, unless they have been
* explicitly masked by command line switches. */
- if ((arg_settings_mask & SETTING_BOOT) == 0 &&
- settings->boot >= 0) {
- arg_boot = settings->boot;
+ 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);
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 (arg_boot) {
+ 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;
};
int ifi = 0;
ssize_t l;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char last_char = 0;
r = barrier_create(&barrier);
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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "local-addresses.h"
#include "macro.h"
#include "nss-util.h"
+#include "signal-util.h"
#include "string-util.h"
#include "util.h"
char *r_name;
unsigned n;
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
assert(name);
assert(pat);
assert(buffer);
uint32_t local_address_ipv4 = 0;
int n_addresses = 0;
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
assert(name);
assert(host);
assert(buffer);
bool additional_from_hostname = false;
unsigned n;
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
assert(addr);
assert(host);
assert(buffer);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "bus-common-errors.h"
-#include "bus-util.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_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;
int32_t *ttlp) {
struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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;
char *r_name;
int n_ifindices, r;
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
assert(name);
assert(pat);
assert(buffer);
int32_t *ttlp,
char **canonp) {
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
char *buffer, size_t buflen,
int *errnop) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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_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);
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;
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;
char *buffer, size_t buflen,
int *errnop) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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_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 < 0x10000)
+ if (uid < HOST_UID_LIMIT)
goto not_found;
r = sd_bus_open_system(&bus);
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;
char *buffer, size_t buflen,
int *errnop) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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_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);
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;
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;
char *buffer, size_t buflen,
int *errnop) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = 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_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 < 0x10000)
+ if (gid < HOST_GID_LIMIT)
goto not_found;
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
+ if (mapped == gid)
+ goto not_found;
+
if (buflen < sizeof(char*) + 1) {
*errnop = ENOMEM;
return NSS_STATUS_TRYAGAIN;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-bus.h"
#include "bus-common-errors.h"
-#include "bus-util.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);
int *errnop, int *h_errnop,
int32_t *ttlp) {
- _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ 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_bus_flush_close_unref_ sd_bus *bus = 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);
r = sd_bus_open_system(&bus);
if (r < 0)
- goto fail;
+ goto fallback;
r = sd_bus_message_new_method_call(
bus,
return NSS_STATUS_NOTFOUND;
}
- if (bus_error_shall_fallback(&error)) {
-
- enum nss_status (*fallback)(
- const char *name,
- struct gaih_addrtuple **pat,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp);
-
- 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);
- }
+ if (bus_error_shall_fallback(&error))
+ goto fallback;
- *errnop = -r;
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ goto fail;
}
c = count_addresses(reply, AF_UNSPEC, &canonical);
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_DATA;
+ *h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
int32_t *ttlp,
char **canonp) {
- _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ 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_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
r = sd_bus_open_system(&bus);
if (r < 0)
- goto fail;
+ goto fallback;
r = sd_bus_message_new_method_call(
bus,
return NSS_STATUS_NOTFOUND;
}
- if (bus_error_shall_fallback(&error)) {
-
- 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);
-
- 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);
- }
+ if (bus_error_shall_fallback(&error))
+ goto fallback;
- *errnop = -r;
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ goto fail;
}
c = count_addresses(reply, af, &canonical);
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_DATA;
+ *h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
int *errnop, int *h_errnop,
int32_t *ttlp) {
- _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ 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_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
r = sd_bus_open_system(&bus);
if (r < 0)
- goto fail;
+ goto fallback;
r = sd_bus_message_new_method_call(
bus,
return NSS_STATUS_NOTFOUND;
}
- if (bus_error_shall_fallback(&error)) {
+ if (bus_error_shall_fallback(&error))
+ goto fallback;
- 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);
-
- 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);
- }
*errnop = -r;
*h_errnop = NO_RECOVERY;
p = buffer + idx;
memcpy(p, n, l+1);
- if (i > 1)
+ if (i > 0)
((char**) r_aliases)[i-1] = p;
i++;
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_DATA;
+ *h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
_cleanup_free_ void* buf = NULL;
size_t buf_size = 0;
ssize_t k;
- int r;
+ int r, open_rw_error;
FILE *f;
bool refresh_seed_file = true;
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) {
- r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
+ 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;
}
-
- refresh_seed_file = false;
}
random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
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)
+ else if (k == 0) {
+ r = 0;
log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
- else {
+ } else {
(void) lseek(seed_fd, 0, SEEK_SET);
r = loop_write(random_fd, buf, (size_t) k, false);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
+++ /dev/null
-../Makefile
\ No newline at end of file
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-#include <net/if.h>
-
-#include "sd-bus.h"
-
-#include "af-list.h"
-#include "alloc-util.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "in-addr-util.h"
-#include "parse-util.h"
-#include "resolved-def.h"
-#include "resolved-dns-packet.h"
-
-#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
-
-static int arg_family = AF_UNSPEC;
-static int arg_ifindex = 0;
-static int arg_type = 0;
-static uint16_t arg_class = 0;
-static bool arg_legend = true;
-static uint64_t arg_flags = 0;
-
-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",
- flags & SD_RESOLVED_DNS ? " DNS" :"",
- flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
- flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "");
-
- assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
-
- printf(" in %s", rtt_str);
-
- fputc('.', stdout);
- fputc('\n', stdout);
-}
-
-static int resolve_host(sd_bus *bus, const char *name) {
-
- _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_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) {
- 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', "(iiay)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
- const void *a;
- size_t sz;
- _cleanup_free_ char *pretty = NULL;
- int ifindex, family;
-
- 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");
- continue;
- }
-
- 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_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_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) {
-
- _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_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(arg_class), dns_type_to_string(arg_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);
-
- assert((uint16_t) arg_type == arg_type);
- r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, arg_class, arg_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;
- _cleanup_free_ char *s = NULL;
- 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);
- if (r < 0) {
- log_error("Failed to parse RR.");
- return r;
- }
-
- r = dns_resource_record_to_string(rr, &s);
- if (r < 0) {
- log_error("Failed to format RR.");
- 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\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 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...]\n\n"
- "Resolve IPv4 or IPv6 addresses.\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 Look on interface\n"
- " -p --protocol=PROTOCOL Look via protocol\n"
- " -t --type=TYPE Query RR with DNS type\n"
- " -c --class=CLASS Query RR with DNS class\n"
- " --legend[=BOOL] Do [not] print column headers\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_LEGEND,
- };
-
- 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", optional_argument, NULL, ARG_LEGEND },
- { "protocol", required_argument, NULL, 'p' },
- {}
- };
-
- 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;
- }
-
- arg_type = dns_type_from_string(optarg);
- if (arg_type < 0) {
- log_error("Failed to parse RR record type %s", optarg);
- return arg_type;
- }
- assert(arg_type > 0 && (uint16_t) arg_type == arg_type);
-
- break;
-
- case 'c':
- if (streq(optarg, "help")) {
- help_dns_classes();
- return 0;
- }
-
- r = dns_class_from_string(optarg, &arg_class);
- if (r < 0) {
- log_error("Failed to parse RR record class %s", optarg);
- return r;
- }
-
- break;
-
- case ARG_LEGEND:
- if (optarg) {
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --legend= argument");
- return r;
- }
-
- arg_legend = !!r;
- } else
- arg_legend = false;
- break;
-
- case 'p':
- 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 '?':
- 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_class == 0)
- arg_class = DNS_CLASS_IN;
-
- return 1 /* work to do */;
-}
-
-int main(int argc, char **argv) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
- int r;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- if (optind >= argc) {
- log_error("No arguments passed");
- r = -EINVAL;
- goto finish;
- }
-
- r = sd_bus_open_system(&bus);
- if (r < 0) {
- log_error_errno(r, "sd_bus_open_system: %m");
- goto finish;
- }
-
- while (argv[optind]) {
- int family, ifindex, k;
- union in_addr_union a;
-
- if (arg_type != 0)
- k = resolve_record(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++;
- }
-
-finish:
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
--- /dev/null
+Y = 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/
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sys/socket.h>
+
#include "dns-type.h"
+#include "parse-util.h"
+#include "string-util.h"
typedef const struct {
uint16_t type;
assert(s);
sc = lookup_dns_type(s, strlen(s));
- if (!sc)
- return _DNS_TYPE_INVALID;
+ 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 sc->id;
+ 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);
}
-/* XXX: find an authoritative list of all pseudo types? */
-bool dns_type_is_pseudo(int n) {
- return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT);
+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
+ * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
+
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "macro.h"
-const char *dns_type_to_string(int type);
-int dns_type_from_string(const char *s);
-bool dns_type_is_pseudo(int n);
-
/* DNS record types, taken from
* http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
*/
DNS_TYPE_TALINK,
DNS_TYPE_CDS,
DNS_TYPE_CDNSKEY,
+ DNS_TYPE_OPENPGPKEY,
DNS_TYPE_SPF = 0x63,
DNS_TYPE_NID,
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);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <getopt.h>
+#include <net/if.h>
+
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "dns-domain.h"
#include "resolved-bus.h"
#include "resolved-def.h"
+#include "resolved-link-bus.h"
static int reply_query_state(DnsQuery *q) {
- _cleanup_free_ char *ip = NULL;
- const char *name;
- int r;
-
- if (q->request_hostname)
- name = q->request_hostname;
- else {
- r = in_addr_to_string(q->request_family, &q->request_address, &ip);
- if (r < 0)
- return r;
-
- name = ip;
- }
switch (q->state) {
case DNS_TRANSACTION_INVALID_REPLY:
return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
- case DNS_TRANSACTION_RESOURCES:
- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
+ 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_FAILURE: {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ 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", name);
+ sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
else {
const char *rc, *n;
- char p[3]; /* the rcode is 4 bits long */
+ char p[DECIMAL_STR_MAX(q->answer_rcode)];
rc = dns_rcode_to_string(q->answer_rcode);
if (!rc) {
}
n = strjoina(_BUS_ERROR_DNS, rc);
- sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, 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 void bus_method_resolve_hostname_complete(DnsQuery *q) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
- int r;
+ _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);
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;
if (r < 0)
goto finish;
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
-
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->items[i].rr);
- if (r < 0)
- goto finish;
- if (r == 0) {
- /* Hmm, if this is not an address record,
- maybe it's a cname? If so, remember this */
- r = dns_question_matches_cname(q->question, answer->items[i].rr);
- if (r < 0)
- goto finish;
- if (r > 0)
- cname = dns_resource_record_ref(answer->items[i].rr);
-
- continue;
- }
-
- r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
- if (r < 0)
- goto finish;
+ DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
+ DnsQuestion *question;
- if (!canonical)
- canonical = dns_resource_record_ref(answer->items[i].rr);
-
- added ++;
- }
- }
+ question = dns_query_question_for_protocol(q, q->answer_protocol);
- if (added == 0) {
- if (!cname) {
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of requested type", q->request_hostname);
+ r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
+ if (r < 0)
goto finish;
- }
-
- /* This has a cname? Then update the query with the
- * new cname. */
- r = dns_query_cname_redirect(q, cname);
- if (r < 0) {
- if (r == -ELOOP)
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
- else
- r = sd_bus_reply_method_errno(q->request, -r, NULL);
+ if (r == 0)
+ continue;
+ r = append_address(reply, rr, ifindex);
+ if (r < 0)
goto finish;
- }
-
- /* Before we restart the query, let's see if any of
- * the RRs we already got already answers our query */
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->items[i].rr);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
-
- r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
- if (r < 0)
- goto finish;
- if (!canonical)
- canonical = dns_resource_record_ref(answer->items[i].rr);
-
- added++;
- }
+ if (!canonical)
+ canonical = dns_resource_record_ref(rr);
- /* If we didn't find anything, then let's restart the
- * query, this time with the cname */
- if (added <= 0) {
- r = dns_query_go(q);
- if (r < 0) {
- r = sd_bus_reply_method_errno(q->request, -r, NULL);
- goto finish;
- }
+ added ++;
+ }
- return;
- }
+ 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 reported by the server */
+ /* 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));
+ 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;
finish:
if (r < 0) {
log_error_errno(r, "Failed to send hostname reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
+ sd_bus_reply_method_errno(q->request, r, NULL);
}
dns_query_free(q);
}
-static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
+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_FLAGS_ALL)
+ 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 == 0)
- *flags = SD_RESOLVED_FLAGS_DEFAULT;
+ 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 = NULL;
+ _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
Manager *m = userdata;
const char *hostname;
int family, ifindex;
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_normalize(hostname, NULL);
+ 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, error);
+ r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
if (r < 0)
return r;
- question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
- if (!question)
- 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, hostname);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(question, 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, hostname);
- if (!key)
- return -ENOMEM;
+ r = dns_question_new_address(&question_utf8, family, hostname, false);
+ if (r < 0)
+ return r;
- r = dns_question_add(question, key);
- 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, ifindex, flags);
+ 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->request_hostname = hostname;
q->complete = bus_method_resolve_hostname_complete;
+ q->suppress_unroutable_family = family == AF_UNSPEC;
r = dns_query_bus_track(q, message);
if (r < 0)
- return r;
+ goto fail;
r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
- return r;
- }
+ if (r < 0)
+ goto fail;
return 1;
+
+fail:
+ dns_query_free(q);
+ return r;
}
static void bus_method_resolve_address_complete(DnsQuery *q) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
- int r;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ DnsQuestion *question;
+ DnsResourceRecord *rr;
+ unsigned added = 0;
+ int ifindex, r;
assert(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;
if (r < 0)
goto finish;
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
+ question = dns_query_question_for_protocol(q, q->answer_protocol);
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->items[i].rr);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
+ 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)", answer->items[i].ifindex, answer->items[i].rr->ptr.name);
- if (r < 0)
- goto finish;
+ r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
+ if (r < 0)
+ goto finish;
- added ++;
- }
+ added ++;
}
- if (added == 0) {
+ 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", 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;
}
if (r < 0)
goto finish;
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+ 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;
finish:
if (r < 0) {
log_error_errno(r, "Failed to send address reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
+ 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_resource_key_unrefp) DnsResourceKey *key = NULL;
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- _cleanup_free_ char *reverse = NULL;
Manager *m = userdata;
int family, ifindex;
uint64_t flags;
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 (r < 0)
return r;
- r = check_ifindex_flags(ifindex, &flags, error);
- if (r < 0)
- return r;
-
- r = dns_name_reverse(family, d, &reverse);
+ 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_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
- if (!key)
- return -ENOMEM;
-
- reverse = NULL;
-
- r = dns_question_add(question, key);
+ r = dns_question_new_reverse(&question, family, d);
if (r < 0)
return r;
- r = dns_query_new(m, &q, question, ifindex, flags);
+ r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
r = dns_query_bus_track(q, message);
if (r < 0)
- return r;
+ goto fail;
r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
- return r;
- }
+ 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_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ DnsResourceRecord *rr;
+ DnsQuestion *question;
+ unsigned added = 0;
+ int ifindex;
int r;
assert(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;
if (r < 0)
goto finish;
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
-
- for (i = 0; i < answer->n_rrs; i++) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- size_t start;
-
- r = dns_question_matches_rr(q->question, answer->items[i].rr);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
-
- r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
- if (r < 0)
- goto finish;
-
- p->refuse_compression = true;
-
- r = dns_packet_append_rr(p, answer->items[i].rr, &start);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_open_container(reply, 'r', "iqqay");
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "iqq",
- answer->items[i].ifindex,
- answer->items[i].rr->key->class,
- answer->items[i].rr->key->type);
- if (r < 0)
- goto finish;
+ question = dns_query_question_for_protocol(q, q->answer_protocol);
- r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
- if (r < 0)
- goto finish;
+ 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_close_container(reply);
- if (r < 0)
- goto finish;
+ r = bus_message_append_rr(reply, rr, ifindex);
+ if (r < 0)
+ goto finish;
- added ++;
- }
+ 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", q->request_hostname);
+ 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;
}
if (r < 0)
goto finish;
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+ 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;
finish:
if (r < 0) {
log_error_errno(r, "Failed to send record reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
+ sd_bus_reply_method_errno(q->request, r, NULL);
}
dns_query_free(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_normalize(name, NULL);
+ 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);
- r = check_ifindex_flags(ifindex, &flags, error);
+ 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;
if (r < 0)
return r;
- r = dns_query_new(m, &q, question, ifindex, flags);
+ 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_hostname = name;
q->complete = bus_method_resolve_record_complete;
r = dns_query_bus_track(q, message);
if (r < 0)
- return r;
+ goto fail;
r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
- return r;
- }
+ if (r < 0)
+ goto fail;
return 1;
+
+fail:
+ dns_query_free(q);
+ return r;
}
-static const sd_bus_vtable resolve_vtable[] = {
- SD_BUS_VTABLE_START(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_VTABLE_END,
-};
+static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
+ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
+ DnsQuery *aux;
+ int r;
-static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
- Manager *m = userdata;
+ assert(q);
+ assert(reply);
+ assert(rr);
+ assert(rr->key);
- assert(s);
- assert(m);
+ if (rr->key->type != DNS_TYPE_SRV)
+ return 0;
- m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
+ 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;
- manager_connect_bus(m);
- return 0;
-}
+ if (aux->state != DNS_TRANSACTION_SUCCESS)
+ continue;
+ if (aux->auxiliary_result != 0)
+ continue;
-static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
- Manager *m = userdata;
- int b, r;
+ question = dns_query_question_for_protocol(aux, aux->answer_protocol);
- assert(message);
- assert(m);
+ r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0) {
- log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
- return 0;
- }
+ DNS_ANSWER_FOREACH(zz, aux->answer) {
- if (b)
- return 0;
+ r = dns_question_matches_rr(question, zz, NULL);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
- log_debug("Coming back from suspend, verifying all RRs...");
+ canonical = dns_resource_record_ref(zz);
+ break;
+ }
- manager_verify_all(m);
- return 0;
-}
+ if (canonical)
+ break;
+ }
-int manager_connect_bus(Manager *m) {
- int r;
+ /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
+ if (!canonical)
+ return 0;
+ }
- assert(m);
+ r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
+ if (r < 0)
+ return r;
- if (m->bus)
- return 0;
+ 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_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... */
+ r = sd_bus_message_open_container(reply, 'a', "(iiay)");
+ if (r < 0)
+ return r;
- log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
+ if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
+ LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
+ DnsResourceRecord *zz;
+ DnsQuestion *question;
+ int ifindex;
- 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");
+ if (aux->state != DNS_TRANSACTION_SUCCESS)
+ continue;
+ if (aux->auxiliary_result != 0)
+ continue;
- return 0;
- }
+ question = dns_query_question_for_protocol(aux, aux->answer_protocol);
- 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 = 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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "resolved-manager.h"
int manager_connect_bus(Manager *m);
+int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "resolved-conf.h"
#include "string-util.h"
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) {
- DnsServer *first;
+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);
- first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
-
for(;;) {
_cleanup_free_ char *word = NULL;
- union in_addr_union addr;
- bool found = false;
- DnsServer *s;
- int family;
r = extract_first_word(&string, &word, NULL, 0);
if (r < 0)
- return log_error_errno(r, "Failed to parse resolved dns server syntax \"%s\": %m", string);
+ return r;
if (r == 0)
break;
- r = in_addr_from_string_auto(word, &family, &addr);
- if (r < 0) {
- log_warning("Ignoring invalid DNS address '%s'", word);
- continue;
- }
+ 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;
- /* Filter out duplicates */
- LIST_FOREACH(servers, s, first)
- if (s->family == family && in_addr_equal(family, &s->address, &addr)) {
- found = true;
- break;
- }
+ assert(m);
+ assert(string);
- if (found)
- continue;
+ for(;;) {
+ _cleanup_free_ char *word = NULL;
- r = dns_server_new(m, NULL, type, NULL, family, &addr);
+ 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_dnsv(
+int config_parse_dns_servers(
const char *unit,
const char *filename,
unsigned line,
if (isempty(rvalue))
/* Empty assignment means clear the list */
- manager_flush_dns_servers(m, ltype);
+ dns_server_unlink_all(manager_get_first_dns_server(m, ltype));
else {
/* Otherwise, add to the list */
- r = manager_parse_dns_server(m, ltype, rvalue);
+ 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;
* /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_support(
+int config_parse_search_domains(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
- Support support, *v = data;
+ Manager *m = userdata;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
+ assert(m);
- support = support_from_string(rvalue);
- if (support < 0) {
- r = parse_boolean(rvalue);
+ 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 support level '%s'. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue);
return 0;
}
-
- support = r ? SUPPORT_YES : SUPPORT_NO;
}
- *v = support;
+ /* 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);
- return config_parse_many(PKGSYSCONFDIR "/resolved.conf",
- CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
- "Resolve\0",
- config_item_perf_lookup, resolved_gperf_lookup,
- false, 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;
+
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "resolved-manager.h"
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string);
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_dnsv(const char *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_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_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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#define SD_RESOLVED_DNS ((uint64_t) 1)
-#define SD_RESOLVED_LLMNR_IPV4 ((uint64_t) 2)
-#define SD_RESOLVED_LLMNR_IPV6 ((uint64_t) 4)
+#include <inttypes.h>
+
+#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_FLAGS_ALL (SD_RESOLVED_DNS|SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
-#define SD_RESOLVED_FLAGS_DEFAULT SD_RESOLVED_FLAGS_ALL
+#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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) {
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) {
- unsigned i;
-
- for (i = 0; i < a->n_rrs; i++)
- dns_resource_record_unref(a->items[i].rr);
-
+ dns_answer_flush(a);
free(a);
} else
a->n_ref--;
return NULL;
}
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
+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;
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)
if (r < 0)
return r;
if (r > 0) {
- /* Entry already exists, keep the entry with
- * the higher RR, or the one with TTL 0 */
+ /* Don't mix contradicting TTLs (see below) */
+ if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+ return -EINVAL;
- if (rr->ttl == 0 || (rr->ttl > a->items[i].rr->ttl && a->items[i].rr->ttl != 0)) {
+ /* 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;
+ }
}
- if (a->n_rrs >= a->n_allocated)
- return -ENOSPC;
+ return dns_answer_add_raw(a, rr, ifindex, flags);
+}
- a->items[a->n_rrs].rr = dns_resource_record_ref(rr);
- a->items[a->n_rrs].ifindex = ifindex;
- a->n_rrs++;
+static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
+ DnsResourceRecord *rr;
+ DnsAnswerFlags flags;
+ int ifindex, r;
- return 1;
+ 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) {
soa->soa.expire = 1;
soa->soa.minimum = ttl;
- return dns_answer_add(a, soa, 0);
+ return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
}
-int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key) {
- unsigned i;
+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);
- if (!a)
- return 0;
+ 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;
- for (i = 0; i < a->n_rrs; i++) {
- r = dns_resource_key_match_rr(key, a->items[i].rr);
+ 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)
+ if (r == 0)
+ continue;
+
+ if (!ret_flags)
return 1;
+
+ if (found)
+ flags &= i_flags;
+ else {
+ flags = i_flags;
+ found = true;
+ }
}
- return 0;
+ if (ret_flags)
+ *ret_flags = flags;
+
+ return found;
}
-int dns_answer_match_soa(DnsResourceKey *key, DnsResourceKey *soa) {
- if (soa->class != DNS_CLASS_IN)
- return 0;
+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);
- if (soa->type != DNS_TYPE_SOA)
+ /* For a SOA record we can never find a matching SOA record */
+ if (key->type == DNS_TYPE_SOA)
return 0;
- if (!dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa)))
+ 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_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret) {
- unsigned i;
+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 (!a)
+ if (dns_answer_size(a) <= 0) {
+ *ret = dns_answer_ref(b);
return 0;
+ }
- /* For a SOA record we can never find a matching SOA record */
- if (key->type == DNS_TYPE_SOA)
+ if (dns_answer_size(b) <= 0) {
+ *ret = dns_answer_ref(a);
return 0;
+ }
- for (i = 0; i < a->n_rrs; i++) {
+ k = dns_answer_new(a->n_rrs + b->n_rrs);
+ if (!k)
+ return -ENOMEM;
- if (dns_answer_match_soa(key, a->items[i].rr->key)) {
- *ret = a->items[i].rr;
- return 1;
- }
- }
+ 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;
}
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *ret = NULL;
- DnsAnswer *k;
+int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
+ bool found = false, other = false;
+ DnsResourceRecord *rr;
unsigned i;
int r;
- if (a && (!b || b->n_rrs <= 0))
- return dns_answer_ref(a);
- if ((!a || a->n_rrs <= 0) && b)
- return dns_answer_ref(b);
+ assert(a);
+ assert(key);
- ret = dns_answer_new((a ? a->n_rrs : 0) + (b ? b->n_rrs : 0));
- if (!ret)
- return NULL;
+ /* 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 (a) {
- for (i = 0; i < a->n_rrs; i++) {
- r = dns_answer_add(ret, a->items[i].rr, a->items[i].ifindex);
+ 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 NULL;
+ 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 (b) {
- for (i = 0; i < b->n_rrs; i++) {
- r = dns_answer_add(ret, b->items[i].rr, b->items[i].ifindex);
+ 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 NULL;
+ 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;
}
- k = ret;
- ret = NULL;
+ return 0;
+}
- return k;
+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) {
int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
DnsAnswer *n;
+ assert(a);
+
if (n_free <= 0)
return 0;
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;
*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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
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. */
+ * 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 {
DnsAnswer *dns_answer_ref(DnsAnswer *a);
DnsAnswer *dns_answer_unref(DnsAnswer *a);
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex);
+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_contains(DnsAnswer *a, DnsResourceKey *key);
-int dns_answer_match_soa(DnsResourceKey *key, DnsResourceKey *soa);
-int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret);
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b);
+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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#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 1K entries */
-#define CACHE_MAX 1024
+/* 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 10min in our cache */
-#define CACHE_TTL_MAX_USEC (10 * USEC_PER_MINUTE)
+/* 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;
};
struct DnsCacheItem {
+ DnsCacheItemType type;
DnsResourceKey *key;
DnsResourceRecord *rr;
+
usec_t until;
- DnsCacheItemType type;
- unsigned prioq_idx;
+ 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);
};
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
-static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) {
+static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) {
DnsCacheItem *first;
assert(c);
dns_cache_item_free(i);
}
-void dns_cache_flush(DnsCache *c) {
- DnsCacheItem *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);
- while ((i = hashmap_first(c->by_key)))
- dns_cache_item_remove_and_free(c, i);
+ first = hashmap_remove(c->by_key, key);
+ if (!first)
+ return false;
- assert(hashmap_size(c->by_key) == 0);
- assert(prioq_size(c->by_expiry) == 0);
+ LIST_FOREACH_SAFE(by_key, i, n, first) {
+ prioq_remove(c->by_expiry, i, &i->prioq_idx);
+ dns_cache_item_free(i);
+ }
- c->by_key = hashmap_free(c->by_key);
- c->by_expiry = prioq_free(c->by_expiry);
+ return true;
}
-static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) {
- DnsCacheItem *i;
- bool exist = false;
+void dns_cache_flush(DnsCache *c) {
+ DnsResourceKey *key;
assert(c);
- assert(key);
- while ((i = hashmap_get(c->by_key, key))) {
- dns_cache_item_remove_and_free(c, i);
- exist = true;
- }
+ while ((key = hashmap_first_key(c->by_key)))
+ dns_cache_remove_by_key(c, key);
- return exist;
+ 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) {
/* 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(c, key);
+ dns_cache_remove_by_key(c, key);
}
}
/* Remove all entries that are past their TTL */
for (;;) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
DnsCacheItem *i;
i = prioq_peek(c->by_expiry);
if (i->until > t)
break;
- /* 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(c, key);
+ /* 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);
+ }
}
}
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 {
return NULL;
}
-static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, usec_t timestamp) {
+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;
dns_resource_key_unref(i->key);
i->key = dns_resource_key_ref(rr->key);
- i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
+ 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;
+ int r, k;
assert(c);
assert(rr);
assert(owner_address);
- /* New TTL is 0? Delete the entry... */
+ /* 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) {
- r = dns_resource_key_to_string(rr->key, &key_str);
- if (r < 0)
- return r;
+ k = dns_cache_remove_by_rr(c, rr);
- if (dns_cache_remove(c, rr->key))
- log_debug("Removed zero TTL entry from cache: %s", key_str);
- else
- log_debug("Not caching zero TTL cache entry: %s", key_str);
+ if (log_get_max_level() >= LOG_DEBUG) {
+ r = dns_resource_key_to_string(rr->key, &key_str);
+ if (r < 0)
+ return r;
- return 0;
- }
+ 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);
+ }
- if (rr->key->class == DNS_CLASS_ANY)
- return 0;
- if (rr->key->type == DNS_TYPE_ANY)
return 0;
+ }
- /* Entry exists already? Update TTL and timestamp */
+ /* Entry exists already? Update TTL, timestamp and owner*/
existing = dns_cache_get(c, rr);
if (existing) {
- dns_cache_item_update_positive(c, existing, rr, timestamp);
+ dns_cache_item_update_positive(
+ c,
+ existing,
+ rr,
+ authenticated,
+ shared_owner,
+ timestamp,
+ ifindex,
+ owner_family,
+ owner_address);
return 0;
}
i->type = DNS_CACHE_POSITIVE;
i->key = dns_resource_key_ref(rr->key);
i->rr = dns_resource_record_ref(rr);
- i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
- i->prioq_idx = PRIOQ_IDX_NULL;
+ 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;
- r = dns_resource_key_to_string(i->key, &key_str);
- 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 cache entry for %s", key_str);
+ log_debug("Added positive cache entry for %s", key_str);
+ }
i = NULL;
return 0;
DnsCache *c,
DnsResourceKey *key,
int rcode,
+ bool authenticated,
+ uint32_t nsec_ttl,
usec_t timestamp,
- uint32_t soa_ttl,
+ DnsResourceRecord *soa,
int owner_family,
const union in_addr_union *owner_address) {
assert(c);
assert(key);
+ assert(soa);
assert(owner_address);
- dns_cache_remove(c, key);
-
- if (key->class == DNS_CLASS_ANY)
+ /* 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 (key->type == DNS_TYPE_ANY)
+ if (dns_type_is_pseudo(key->type))
return 0;
- if (soa_ttl <= 0) {
- r = dns_resource_key_to_string(key, &key_str);
- if (r < 0)
- return r;
- log_debug("Not caching negative entry with zero SOA TTL: %s", key_str);
+ 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;
}
return -ENOMEM;
i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN;
- i->key = dns_resource_key_ref(key);
- i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
- i->prioq_idx = PRIOQ_IDX_NULL;
+ 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;
- r = dns_resource_key_to_string(i->key, &key_str);
- 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);
+ 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,
- unsigned max_rrs,
+ bool authenticated,
+ uint32_t nsec_ttl,
usec_t timestamp,
int owner_family,
const union in_addr_union *owner_address) {
- DnsResourceRecord *soa = NULL;
- unsigned cache_keys, i;
- int r;
+ DnsResourceRecord *soa = NULL, *rr;
+ DnsAnswerFlags flags;
+ unsigned cache_keys;
+ int r, ifindex;
assert(c);
+ assert(owner_address);
- if (key) {
- /* First, if we were passed a key, delete all matching old RRs,
- * so that we only keep complete by_key in place. */
- dns_cache_remove(c, key);
- }
+ dns_cache_remove_previous(c, key, answer);
- if (!answer)
- return 0;
+ 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);
+ }
- for (i = 0; i < answer->n_rrs; i++)
- dns_cache_remove(c, answer->items[i].rr->key);
+ 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 = answer->n_rrs;
-
+ cache_keys = dns_answer_size(answer);
if (key)
cache_keys ++;
timestamp = now(clock_boottime_or_monotonic());
/* Second, add in positive entries for all contained RRs */
- for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) {
- r = dns_cache_put_positive(c, answer->items[i].rr, timestamp, owner_family, owner_address);
+ 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)
+ 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_contains(answer, key);
+ r = dns_answer_match_key(answer, key, 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. */
+ /* 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;
- r = dns_answer_find_soa(answer, key, &soa);
+ /* 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;
- /* Also, if the requested key is an alias, the negative response should
- be cached for each name in the redirect chain. Any CNAME record in
- the response is from the redirection chain, though only the final one
- is guaranteed to be included. This means that we cannot verify the
- chain and that we need to cache them all as it may be incomplete. */
- for (i = 0; i < answer->n_rrs; i++) {
- DnsResourceRecord *answer_rr = answer->items[i].rr;
-
- if (answer_rr->key->type == DNS_TYPE_CNAME) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *canonical_key = NULL;
-
- canonical_key = dns_resource_key_new_redirect(key, answer_rr);
- if (!canonical_key)
- goto fail;
-
- /* Let's not add negative cache entries for records outside the current zone. */
- if (!dns_answer_match_soa(canonical_key, soa->key))
- continue;
-
- r = dns_cache_put_negative(c, canonical_key, rcode, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
- if (r < 0)
- goto fail;
- }
- }
+ /* 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, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
+ r = dns_cache_put_negative(
+ c,
+ key,
+ rcode,
+ authenticated,
+ nsec_ttl,
+ timestamp,
+ soa,
+ owner_family, owner_address);
if (r < 0)
goto fail;
* added, just in case */
if (key)
- dns_cache_remove(c, key);
+ dns_cache_remove_by_key(c, key);
- for (i = 0; i < answer->n_rrs; i++)
- dns_cache_remove(c, answer->items[i].rr->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(DnsCache *c, DnsResourceKey *k) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *cname_key = NULL;
- DnsCacheItem *i, *j;
+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 || k->type == DNS_TYPE_CNAME)
+ 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;
- /* check if we have a CNAME record instead */
- cname_key = dns_resource_key_new_cname(k);
- if (!cname_key)
- return NULL;
+ 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;
- j = hashmap_get(c->by_key, cname_key);
- if (j)
- return j;
+ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n));
+ if (i)
+ return 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) {
+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;
+ 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 simply refresh */
+ /* If we have ANY lookups we don't use the cache, so
+ * that the caller refreshes via the network. */
- r = dns_resource_key_to_string(key, &key_str);
- if (r < 0)
- return r;
+ 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);
+ }
- 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(c, key);
+ first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key);
if (!first) {
/* If one question cannot be answered we need to refresh */
- r = dns_resource_key_to_string(key, &key_str);
- if (r < 0)
- return r;
+ 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);
+ }
- log_debug("Cache miss for %s", key_str);
+ c->n_miss++;
*ret = NULL;
*rcode = DNS_RCODE_SUCCESS;
}
LIST_FOREACH(by_key, j, first) {
- if (j->rr)
+ if (j->rr) {
+ if (j->rr->key->type == DNS_TYPE_NSEC)
+ nsec = j;
+
n++;
- else if (j->type == DNS_CACHE_NXDOMAIN)
+ } else if (j->type == DNS_CACHE_NXDOMAIN)
nxdomain = true;
+
+ if (j->authenticated)
+ have_authenticated = true;
+ else
+ have_non_authenticated = true;
}
- r = dns_resource_key_to_string(key, &key_str);
- if (r < 0)
- return r;
+ 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;
- log_debug("%s cache hit for %s",
- nxdomain ? "NXDOMAIN" :
- n > 0 ? "Positive" : "NODATA",
- key_str);
+ 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;
}
if (!j->rr)
continue;
- r = dns_answer_add(answer, j->rr, 0);
+ 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;
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;
DnsCacheItem *j;
LIST_FOREACH(by_key, j, i) {
- _cleanup_free_ char *t = NULL;
fputc('\t', f);
if (j->rr) {
- r = dns_resource_record_to_string(j->rr, &t);
- if (r < 0) {
+ const char *t;
+ t = dns_resource_record_to_string(j->rr);
+ if (!t) {
log_oom();
continue;
}
fputs(t, f);
fputc('\n', f);
} else {
- r = dns_resource_key_to_string(j->key, &t);
+ _cleanup_free_ char *z = NULL;
+ r = dns_resource_key_to_string(j->key, &z);
if (r < 0) {
log_oom();
continue;
}
- fputs(t, f);
+ fputs(z, f);
fputs(" -- ", f);
fputs(j->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", f);
fputc('\n', f);
return hashmap_isempty(cache->by_key);
}
+
+unsigned dns_cache_size(DnsCache *cache) {
+ if (!cache)
+ return 0;
+
+ return hashmap_size(cache->by_key);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
#include "hashmap.h"
+#include "list.h"
#include "prioq.h"
#include "time-util.h"
-#include "list.h"
typedef struct DnsCache {
Hashmap *by_key;
Prioq *by_expiry;
+ unsigned n_hit;
+ unsigned n_miss;
} DnsCache;
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
#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, unsigned max_rrs, 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);
+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);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
+#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);
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+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_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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;
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;
}
-int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
- DnsPacket *p;
- DnsPacketHeader *h;
- int r;
+void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
- assert(ret);
+ DnsPacketHeader *h;
- r = dns_packet_new(&p, protocol, mtu);
- if (r < 0)
- return r;
+ assert(p);
h = DNS_PACKET_HEADER(p);
- if (protocol == DNS_PROTOCOL_LLMNR)
+ switch(p->protocol) {
+ case DNS_PROTOCOL_LLMNR:
+ assert(!truncated);
+
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
0 /* opcode */,
0 /* c */,
0 /* ad */,
0 /* cd */,
0 /* rcode */));
- else
+ 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 */,
1 /* rd (ask for recursion) */,
0 /* ra */,
0 /* ad */,
- 0 /* cd */,
+ 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;
if (!p)
return NULL;
+ assert(!p->on_stack);
+
assert(p->n_ref > 0);
p->n_ref++;
return 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);
- free(p);
+
+ if (!p->on_stack)
+ free(p);
}
DnsPacket *dns_packet_unref(DnsPacket *p) {
assert(p->n_ref > 0);
+ dns_packet_unref(p->more);
+
if (p->n_ref == 1)
dns_packet_free(p);
else
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)
break;
+ case DNS_PROTOCOL_MDNS:
+ /* RFC 6762, Section 18 */
+ if (DNS_PACKET_RCODE(p) != 0)
+ return -EBADMSG;
+
+ break;
+
default:
break;
}
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)
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 0;
}
-static void dns_packet_truncate(DnsPacket *p, size_t sz) {
+void dns_packet_truncate(DnsPacket *p, size_t sz) {
Iterator i;
char *s;
void *n;
}
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;
- size_t l;
int r;
assert(p);
- assert(s);
+ assert(s || size == 0);
- l = strlen(s);
- if (l > 255)
+ if (size > 255)
return -E2BIG;
- r = dns_packet_extend(p, 1 + l, &d, start);
+ r = dns_packet_extend(p, 1 + size, &d, start);
if (r < 0)
return r;
- ((uint8_t*) d)[0] = (uint8_t) l;
- memcpy(((uint8_t*) d) + 1, s, l);
+ ((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, size_t *start) {
- void *w;
+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, &w, start);
+ r = dns_packet_extend(p, 1 + l, (void**) &w, start);
if (r < 0)
return r;
- ((uint8_t*) w)[0] = (uint8_t) l;
- memcpy(((uint8_t*) w) + 1, d, l);
+ *(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;
}
DnsPacket *p,
const char *name,
bool allow_compression,
+ bool canonical_candidate,
size_t *start) {
size_t saved_size;
saved_size = p->size;
- while (*name) {
- _cleanup_free_ char *s = NULL;
+ while (!dns_name_is_root(name)) {
+ const char *z = name;
char label[DNS_LABEL_MAX];
size_t n = 0;
- int k;
if (allow_compression)
n = PTR_TO_SIZE(hashmap_get(p->names, name));
}
}
- s = strdup(name);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
goto fail;
- if (p->protocol == DNS_PROTOCOL_DNS)
- k = dns_label_apply_idna(label, r, label, sizeof(label));
- else
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0) {
- r = k;
- goto fail;
- }
- if (k > 0)
- r = k;
-
- r = dns_packet_append_label(p, label, r, &n);
+ 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;
saved_size = p->size;
- r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
+ r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL);
if (r < 0)
goto fail;
return r;
}
-static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
+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;
int r;
assert(p);
- assert(types);
saved_size = p->size;
}
window = n >> 8;
-
entry = n & 255;
bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
}
- r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
+ 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_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
- size_t saved_size, rdlength_offset, end, rdlength;
+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);
if (r < 0)
goto fail;
+ rds = p->size - saved_size;
+
switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
if (r < 0)
goto fail;
- r = dns_packet_append_name(p, rr->srv.name, true, NULL);
+ 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, NULL);
+ r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
break;
case DNS_TYPE_HINFO:
break;
case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT: {
- char **s;
+ case DNS_TYPE_TXT:
- if (strv_isempty(rr->txt.strings)) {
+ if (!rr->txt.items) {
/* RFC 6763, section 6.1 suggests to generate
* single empty string for an empty array. */
- r = dns_packet_append_string(p, "", NULL);
+ r = dns_packet_append_raw_string(p, NULL, 0, NULL);
if (r < 0)
goto fail;
} else {
- STRV_FOREACH(s, rr->txt.strings) {
- r = dns_packet_append_string(p, *s, NULL);
+ 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_SOA:
- r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
+ 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, NULL);
+ r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
if (r < 0)
goto fail;
if (r < 0)
goto fail;
- r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
+ r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
break;
case DNS_TYPE_LOC:
break;
case DNS_TYPE_DNSKEY:
- r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
+ r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
if (r < 0)
goto fail;
- r = dns_packet_append_uint8(p, 3u, NULL);
+ r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
if (r < 0)
goto fail;
if (r < 0)
goto fail;
- r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
+ r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
if (r < 0)
goto fail;
break;
case DNS_TYPE_NSEC:
- r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
+ r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
if (r < 0)
goto fail;
goto fail;
break;
+
case DNS_TYPE_NSEC3:
r = dns_packet_append_uint8(p, rr->nsec3.algorithm, 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.size, NULL);
+ r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
break;
}
if (r < 0)
/* Let's calculate the actual data size and update the field */
rdlength = p->size - rdlength_offset - sizeof(uint16_t);
if (rdlength > 0xFFFF) {
- r = ENOSPC;
+ r = -ENOSPC;
goto fail;
}
if (start)
*start = saved_size;
+ if (rdata_start)
+ *rdata_start = rds;
+
return 0;
fail:
return r;
}
-
int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
assert(p);
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,
/* End of name */
break;
else if (c <= 63) {
- _cleanup_free_ char *t = NULL;
const char *label;
/* Literal label */
if (r < 0)
goto fail;
- r = dns_label_escape(label, c, &t);
- if (r < 0)
- goto fail;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
r = -ENOMEM;
goto fail;
}
- if (!first)
- ret[n++] = '.';
- else
+ if (first)
first = false;
+ else
+ ret[n++] = '.';
+
+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ goto fail;
- memcpy(ret + n, t, r);
n += r;
continue;
} else if (allow_compression && (c & 0xc0) == 0xc0) {
return r;
}
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
+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;
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;
name = NULL;
*ret = key;
+ if (ret_cache_flush)
+ *ret_cache_flush = cache_flush;
if (start)
*start = saved_rindex;
return m <= 9 && e <= 9 && (m > 0 || e == 0);
}
-static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
- assert(rr);
-
- if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
- return -EBADMSG;
-
- rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
- rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
- return 0;
-}
-
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
+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);
saved_rindex = p->rindex;
- r = dns_packet_read_key(p, &key, NULL);
+ r = dns_packet_read_key(p, &key, &cache_flush, NULL);
if (r < 0)
goto fail;
- if (key->class == DNS_CLASS_ANY ||
- key->type == DNS_TYPE_ANY) {
+ if (!dns_class_is_valid_rr(key->class)||
+ !dns_type_is_valid_rr(key->type)) {
r = -EBADMSG;
goto fail;
}
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;
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. */
- r = strv_extend(&rr->txt.strings, "");
- if (r < 0)
- goto fail;
+ 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) {
- char *s;
+ DnsTxtItem *i;
+ const void *data;
+ size_t sz;
- r = dns_packet_read_string(p, &s, NULL);
+ r = dns_packet_read_raw_string(p, &data, &sz, NULL);
if (r < 0)
- goto fail;
+ return r;
- r = strv_consume(&rr->txt.strings, s);
- if (r < 0)
- goto fail;
+ 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;
}
}
}
break;
+
case DNS_TYPE_SSHFP:
r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
if (r < 0)
break;
- case DNS_TYPE_DNSKEY: {
- uint16_t flags;
- uint8_t proto;
-
- r = dns_packet_read_uint16(p, &flags, NULL);
- if (r < 0)
- goto fail;
-
- r = dnskey_parse_flags(rr, flags);
+ 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, &proto, NULL);
+ r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
if (r < 0)
goto fail;
- /* protocol is required to be always 3 */
- if (proto != 3) {
- r = -EBADMSG;
- goto fail;
- }
-
r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
if (r < 0)
goto fail;
}
break;
- }
case DNS_TYPE_RRSIG:
r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
break;
- case DNS_TYPE_NSEC:
- r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
+ 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;
if (r < 0)
goto fail;
- /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means
- something went wrong */
- if (bitmap_isclear(rr->nsec.types)) {
- r = -EBADMSG;
- 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;
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.size, NULL);
+ r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
if (r < 0)
goto fail;
break;
*ret = rr;
rr = NULL;
+ if (ret_cache_flush)
+ *ret_cache_flush = cache_flush;
if (start)
*start = 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;
for (i = 0; i < n; i++) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+ bool cache_flush;
- r = dns_packet_read_key(p, &key, NULL);
+ 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;
for (i = 0; i < n; i++) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+ bool cache_flush;
- r = dns_packet_read_rr(p, &rr, NULL);
+ r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
if (r < 0)
goto finish;
- r = dns_answer_add(answer, rr, p->ifindex);
- 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;
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_PROTOCOL_LLMNR] = "llmnr",
};
DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
-
-static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
- [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_INDIRECT] = "INDIRECT",
- [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
- [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/udp.h>
#include <netinet/ip.h>
+#include <netinet/udp.h>
-#include "macro.h"
-#include "sparse-endian.h"
#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-dns-rr.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
#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,
/* 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 {
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;
uint16_t sender_port, destination_port;
uint32_t ttl;
- bool extracted;
- bool refuse_compression;
+ /* 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) {
#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)
-#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
+
+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)
}
int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-int dns_packet_new_query(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);
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_label(DnsPacket *p, const char *s, size_t l, size_t *start);
-int dns_packet_append_name(DnsPacket *p, const char *name,
- bool allow_compression, 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);
+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_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_name(DnsPacket *p, char **ret,
- bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start);
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **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,
#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 DNSKEY_FLAG_ZONE_KEY (1u << 8)
-#define DNSKEY_FLAG_SEP (1u << 0)
+#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 uint16_t dnskey_to_flags(const DnsResourceRecord *rr) {
- return (rr->dnskey.zone_key_flag * DNSKEY_FLAG_ZONE_KEY |
- rr->dnskey.sep_flag * DNSKEY_FLAG_SEP);
-}
+static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
+ uint64_t f;
-/* http://tools.ietf.org/html/rfc4034#appendix-A.1 */
-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_INDIRECT = 252,
- DNSSEC_ALGORITHM_PRIVATEDNS,
- DNSSEC_ALGORITHM_PRIVATEOID,
- _DNSSEC_ALGORITHM_MAX_DEFINED
-};
+ /* Converts a protocol + family into a flags field as used in queries and responses */
-const char* dnssec_algorithm_to_string(int i) _const_;
-int dnssec_algorithm_from_string(const char *s) _pure_;
-
-static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family) {
-
- /* Converts a protocol + family into a flags field as used in queries */
+ f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
switch (protocol) {
case DNS_PROTOCOL_DNS:
- return SD_RESOLVED_DNS;
+ return f|SD_RESOLVED_DNS;
case DNS_PROTOCOL_LLMNR:
- return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4;
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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 void dns_query_stop(DnsQuery *q) {
- DnsTransaction *t;
+static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
+ DnsQueryCandidate *c;
+ assert(ret);
assert(q);
+ assert(s);
- q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
+ c = new0(DnsQueryCandidate, 1);
+ if (!c)
+ return -ENOMEM;
- while ((t = set_steal_first(q->transactions))) {
- set_remove(t->queries, q);
- dns_transaction_gc(t);
- }
-}
+ c->query = q;
+ c->scope = s;
-DnsQuery *dns_query_free(DnsQuery *q) {
- if (!q)
- return NULL;
+ LIST_PREPEND(candidates_by_query, q->candidates, c);
+ LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
- dns_query_stop(q);
- set_free(q->transactions);
+ *ret = c;
+ return 0;
+}
- dns_question_unref(q->question);
- dns_answer_unref(q->answer);
+static void dns_query_candidate_stop(DnsQueryCandidate *c) {
+ DnsTransaction *t;
- sd_bus_message_unref(q->request);
- sd_bus_track_unref(q->bus_track);
+ assert(c);
- if (q->manager) {
- LIST_REMOVE(queries, q->manager->dns_queries, q);
- q->manager->n_dns_queries--;
+ while ((t = set_steal_first(c->transactions))) {
+ set_remove(t->notify_query_candidates, c);
+ dns_transaction_gc(t);
}
-
- free(q);
-
- return NULL;
}
-int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
- _cleanup_(dns_query_freep) DnsQuery *q = NULL;
- unsigned i;
- int r;
-
- assert(m);
- assert(question);
+DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
- r = dns_question_is_valid(question);
- if (r < 0)
- return r;
+ if (!c)
+ return NULL;
- if (m->n_dns_queries >= QUERIES_MAX)
- return -EBUSY;
+ dns_query_candidate_stop(c);
- q = new0(DnsQuery, 1);
- if (!q)
- return -ENOMEM;
+ set_free(c->transactions);
+ dns_search_domain_unref(c->search_domain);
- q->question = dns_question_ref(question);
- q->ifindex = ifindex;
- q->flags = flags;
+ if (c->query)
+ LIST_REMOVE(candidates_by_query, c->query->candidates, c);
- for (i = 0; i < question->n_keys; i++) {
- _cleanup_free_ char *p;
+ if (c->scope)
+ LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
- r = dns_resource_key_to_string(question->keys[i], &p);
- if (r < 0)
- return r;
+ free(c);
- log_debug("Looking up RR for %s", p);
- }
-
- LIST_PREPEND(queries, m->dns_queries, q);
- m->n_dns_queries++;
- q->manager = m;
-
- if (ret)
- *ret = q;
- q = NULL;
-
- return 0;
+ return NULL;
}
-static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
- assert(q);
- assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
- assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
+static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
+ DnsSearchDomain *next = NULL;
- /* Note that this call might invalidate the query. Callers
- * should hence not attempt to access the query or transaction
- * after calling this function. */
+ assert(c);
- q->state = state;
+ if (c->search_domain && c->search_domain->linked)
+ next = c->search_domain->domains_next;
+ else
+ next = dns_scope_get_search_domains(c->scope);
- dns_query_stop(q);
- if (q->complete)
- q->complete(q);
-}
+ for (;;) {
+ if (!next) /* We hit the end of the list */
+ return 0;
-static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
- DnsQuery *q = userdata;
+ if (!next->route_only)
+ break;
- assert(s);
- assert(q);
+ /* Skip over route-only domains */
+ next = next->domains_next;
+ }
- dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
- return 0;
+ dns_search_domain_unref(c->search_domain);
+ c->search_domain = dns_search_domain_ref(next);
+
+ return 1;
}
-static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
+static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
DnsTransaction *t;
int r;
- assert(q);
- assert(s);
+ assert(c);
assert(key);
- r = set_ensure_allocated(&q->transactions, NULL);
- if (r < 0)
- return r;
-
- t = dns_scope_find_transaction(s, key, true);
+ t = dns_scope_find_transaction(c->scope, key, true);
if (!t) {
- r = dns_transaction_new(&t, s, key);
+ 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(&t->queries, NULL);
+ 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->queries, q);
+ r = set_put(t->notify_query_candidates, c);
if (r < 0)
goto gc;
- r = set_put(q->transactions, t);
+ r = set_put(c->transactions, t);
if (r < 0) {
- set_remove(t->queries, q);
+ (void) set_remove(t->notify_query_candidates, c);
goto gc;
}
- return 0;
+ return 1;
gc:
dns_transaction_gc(t);
return r;
}
-static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
- unsigned i;
+static int dns_query_candidate_go(DnsQueryCandidate *c) {
+ DnsTransaction *t;
+ Iterator i;
int r;
+ unsigned n = 0;
- assert(q);
- assert(s);
+ assert(c);
- /* Create one transaction per question key */
+ /* Start the transactions that are not started yet */
+ SET_FOREACH(t, c->transactions, i) {
+ if (t->state != DNS_TRANSACTION_NULL)
+ continue;
- for (i = 0; i < q->question->n_keys; i++) {
- r = dns_query_add_transaction(q, s, q->question->keys[i]);
+ 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 int SYNTHESIZE_IFINDEX(int ifindex) {
+static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
+ DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
+ DnsTransaction *t;
+ Iterator i;
- /* 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. */
+ assert(c);
- if (ifindex > 0)
- return ifindex;
+ if (c->error_code != 0)
+ return DNS_TRANSACTION_ERRNO;
- return LOOPBACK_IFINDEX;
-}
+ 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. */
-static int SYNTHESIZE_FAMILY(uint64_t flags) {
+ 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;
- /* 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. */
+ default:
+ if (state != DNS_TRANSACTION_SUCCESS)
+ state = t->state;
- if (!(flags & SD_RESOLVED_DNS)) {
- if (flags & SD_RESOLVED_LLMNR_IPV4)
- return AF_INET;
- if (flags & SD_RESOLVED_LLMNR_IPV6)
- return AF_INET6;
+ break;
+ }
}
- return AF_UNSPEC;
+ return state;
}
-static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
+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. */
- /* Similar as 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 (!c->query->suppress_unroutable_family)
+ return true;
- if (flags & SD_RESOLVED_DNS)
- return DNS_PROTOCOL_DNS;
- if (flags & SD_RESOLVED_LLMNR)
- return DNS_PROTOCOL_LLMNR;
+ if (c->scope->protocol != DNS_PROTOCOL_DNS)
+ return true;
- return DNS_PROTOCOL_DNS;
+ 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_type_to_af(uint16_t t) {
- switch (t) {
+static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
+ DnsQuestion *question;
+ DnsResourceKey *key;
+ int n = 0, r;
- case DNS_TYPE_A:
- return AF_INET;
+ assert(c);
- case DNS_TYPE_AAAA:
- return AF_INET6;
+ dns_query_candidate_stop(c);
- case DNS_TYPE_ANY:
- return AF_UNSPEC;
+ question = dns_query_question_for_protocol(c->query, c->scope->protocol);
- default:
- return -EINVAL;
+ /* 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;
}
-static int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
+void dns_query_candidate_notify(DnsQueryCandidate *c) {
+ DnsTransactionState state;
int r;
- assert(q);
- assert(key);
- assert(answer);
+ assert(c);
- 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;
+ state = dns_query_candidate_state(c);
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
- if (!rr)
- return -ENOMEM;
+ if (DNS_TRANSACTION_IS_LIVE(state))
+ return;
- rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
+ if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
- r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
+ r = dns_query_candidate_next_search_domain(c);
if (r < 0)
- return r;
- }
+ goto fail;
+
+ if (r > 0) {
+ /* OK, there's another search domain to try, let's do so. */
- if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+ r = dns_query_candidate_setup_transactions(c);
+ if (r < 0)
+ goto fail;
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
- if (!rr)
- return -ENOMEM;
+ if (r > 0) {
+ /* New transactions where queued. Start them and wait */
- rr->aaaa.in6_addr = in6addr_loopback;
+ r = dns_query_candidate_go(c);
+ if (r < 0)
+ goto fail;
+
+ return;
+ }
+ }
- r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
- if (r < 0)
- return r;
}
- return 0;
+ 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 int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+static void dns_query_stop(DnsQuery *q) {
+ DnsQueryCandidate *c;
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
- if (!rr)
- return -ENOMEM;
+ assert(q);
- rr->ptr.name = strdup(to);
- if (!rr->ptr.name)
- return -ENOMEM;
+ q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
- return dns_answer_add(*answer, rr, ifindex);
+ LIST_FOREACH(candidates_by_query, c, q->candidates)
+ dns_query_candidate_stop(c);
}
-static int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
- int r;
-
+static void dns_query_free_candidates(DnsQuery *q) {
assert(q);
- assert(key);
- assert(answer);
- r = dns_answer_reserve(answer, 1);
- if (r < 0)
- return r;
+ while (q->candidates)
+ dns_query_candidate_free(q->candidates);
+}
- if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
- r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
- if (r < 0)
- return r;
- }
+static void dns_query_reset_answer(DnsQuery *q) {
+ assert(q);
- return 0;
+ 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);
}
-static int answer_add_addresses_rr(
- DnsAnswer **answer,
- const char *name,
- struct local_address *addresses,
- unsigned n_addresses) {
+DnsQuery *dns_query_free(DnsQuery *q) {
+ if (!q)
+ return NULL;
- unsigned j;
- int r;
+ while (q->auxiliary_queries)
+ dns_query_free(q->auxiliary_queries);
- assert(answer);
- assert(name);
+ 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);
+ }
- r = dns_answer_reserve(answer, n_addresses);
- if (r < 0)
- return r;
+ dns_query_free_candidates(q);
- for (j = 0; j < n_addresses; j++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+ dns_question_unref(q->question_idna);
+ dns_question_unref(q->question_utf8);
- r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
- if (r < 0)
- return r;
+ dns_query_reset_answer(q);
- r = dns_answer_add(*answer, rr, addresses[j].ifindex);
- if (r < 0)
- return r;
+ 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--;
}
- return 0;
+ free(q);
+
+ return NULL;
}
-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) {
+int dns_query_new(
+ Manager *m,
+ DnsQuery **ret,
+ DnsQuestion *question_utf8,
+ DnsQuestion *question_idna,
+ int ifindex, uint64_t flags) {
- unsigned j;
+ _cleanup_(dns_query_freep) DnsQuery *q = NULL;
+ DnsResourceKey *key;
+ bool good = false;
int r;
- assert(answer);
- assert(name);
+ assert(m);
- for (j = 0; j < n_addresses; j++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+ 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;
- if (af != AF_UNSPEC) {
+ good = true;
+ }
- if (addresses[j].family != af)
- continue;
+ /* 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;
- if (match && !in_addr_equal(af, match, &addresses[j].address))
- continue;
+ 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;
- r = dns_answer_reserve(answer, 1);
+ /* 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;
- r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
+ 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_answer_add(*answer, rr, addresses[j].ifindex);
+ 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;
}
-static int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n = 0, af;
-
+int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
assert(q);
- assert(key);
- assert(answer);
-
- af = dns_type_to_af(key->type);
- if (af >= 0) {
- n = local_addresses(q->manager->rtnl, q->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 = SYNTHESIZE_IFINDEX(q->ifindex),
- .address.in.s_addr = htobe32(0x7F000002),
- };
-
- if (af == AF_INET6 || af == AF_UNSPEC)
- buffer[n++] = (struct local_address) {
- .family = AF_INET6,
- .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
- .address.in6 = in6addr_loopback,
- };
-
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
- }
- }
+ assert(auxiliary_for);
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
-
-static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n, r;
+ /* 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);
- assert(q);
- assert(address);
- assert(answer);
+ /* Ensure that the unit we shall be made auxiliary for isn't
+ * auxiliary itself */
+ assert(!auxiliary_for->auxiliary_for);
- if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
+ if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
+ return -EAGAIN;
- /* Always map the IPv4 address 127.0.0.2 to the local
- * hostname, in addition to "localhost": */
+ LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
+ q->auxiliary_for = auxiliary_for;
- r = dns_answer_reserve(answer, 3);
- if (r < 0)
- return r;
+ auxiliary_for->n_auxiliary_queries++;
+ return 0;
+}
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
- if (r < 0)
- return r;
+static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
+ assert(q);
+ assert(!DNS_TRANSACTION_IS_LIVE(state));
+ assert(DNS_TRANSACTION_IS_LIVE(q->state));
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
- if (r < 0)
- return r;
+ /* Note that this call might invalidate the query. Callers
+ * should hence not attempt to access the query or transaction
+ * after calling this function. */
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
- if (r < 0)
- return r;
+ q->state = state;
- return 0;
- }
+ dns_query_stop(q);
+ if (q->complete)
+ q->complete(q);
+}
- n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
+static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
+ DnsQuery *q = userdata;
- r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
- if (r < 0)
- return r;
+ assert(s);
+ assert(q);
- return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
+ dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
+ return 0;
}
-static int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n = 0, af;
+static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
+ DnsQueryCandidate *c;
+ int r;
assert(q);
- assert(key);
- assert(answer);
+ assert(s);
- af = dns_type_to_af(key->type);
- if (af >= 0) {
- n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
- }
+ r = dns_query_candidate_new(&c, q, s);
+ if (r < 0)
+ return r;
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
+ /* 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 */
-static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n;
+ 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;
+ }
+ }
- assert(q);
- assert(address);
- assert(answer);
+ r = dns_query_candidate_setup_transactions(c);
+ if (r < 0)
+ goto fail;
- n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
+ return 0;
- return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
+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;
- unsigned i;
int r;
assert(q);
assert(state);
- /* Tries to synthesize localhost RR replies where appropriate */
+ /* 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_FAILURE,
+ DNS_TRANSACTION_RCODE_FAILURE,
DNS_TRANSACTION_NO_SERVERS,
DNS_TRANSACTION_TIMEOUT,
- DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
+ DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
+ DNS_TRANSACTION_NETWORK_DOWN,
+ DNS_TRANSACTION_NOT_FOUND))
return 0;
- for (i = 0; i < q->question->n_keys; i++) {
- union in_addr_union address;
- const char *name;
- int af;
-
- if (q->question->keys[i]->class != DNS_CLASS_IN &&
- q->question->keys[i]->class != DNS_CLASS_ANY)
- continue;
-
- name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
-
- if (is_localhost(name)) {
+ r = dns_synthesize_answer(
+ q->manager,
+ q->question_utf8,
+ q->ifindex,
+ &answer);
- r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
-
- } else if (manager_is_own_hostname(q->manager, name)) {
+ if (r <= 0)
+ return r;
- r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
+ dns_query_reset_answer(q);
- } else if (is_gateway_hostname(name)) {
+ 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;
- r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
+ *state = DNS_TRANSACTION_SUCCESS;
- } 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) {
+ return 1;
+}
- r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
+static int dns_query_try_etc_hosts(DnsQuery *q) {
+ _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+ int r;
- } else if (dns_name_address(name, &af, &address) > 0) {
+ assert(q);
- r = synthesize_system_hostname_ptr(q, af, &address, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
+ /* 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 = synthesize_gateway_ptr(q, af, &address, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
- }
- }
+ r = manager_etc_hosts_lookup(
+ q->manager,
+ q->question_utf8,
+ &answer);
+ if (r <= 0)
+ return r;
- if (!answer)
- return 0;
+ dns_query_reset_answer(q);
- dns_answer_unref(q->answer);
q->answer = answer;
answer = NULL;
-
- q->answer_family = SYNTHESIZE_FAMILY(q->flags);
- q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
q->answer_rcode = DNS_RCODE_SUCCESS;
-
- *state = DNS_TRANSACTION_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;
- DnsTransaction *t;
- const char *name;
- Iterator i;
+ DnsQueryCandidate *c;
int r;
assert(q);
if (q->state != DNS_TRANSACTION_NULL)
return 0;
- assert(q->question);
- assert(q->question->n_keys > 0);
-
- name = DNS_RESOURCE_KEY_NAME(q->question->keys[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)
if (found == DNS_SCOPE_NO) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
- dns_query_synthesize_reply(q, &state);
+ r = dns_query_synthesize_reply(q, &state);
+ if (r < 0)
+ return r;
+
dns_query_complete(q, state);
return 1;
}
- r = dns_query_add_transaction_split(q, first);
+ 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)
if (match != found)
continue;
- r = dns_query_add_transaction_split(q, s);
+ r = dns_query_add_candidate(q, s);
if (r < 0)
goto fail;
}
- q->answer = dns_answer_unref(q->answer);
- q->answer_rcode = 0;
- q->answer_family = AF_UNSPEC;
- q->answer_protocol = _DNS_PROTOCOL_INVALID;
+ dns_query_reset_answer(q);
r = sd_event_add_time(
q->manager->event,
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 that are not started yet */
- SET_FOREACH(t, q->transactions, i) {
- if (t->state != DNS_TRANSACTION_NULL)
- continue;
-
- r = dns_transaction_go(t);
- if (r < 0)
+ /* 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--;
return r;
}
-void dns_query_ready(DnsQuery *q) {
- DnsTransaction *t;
+static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- int rcode = 0;
- DnsScope *scope = NULL;
- bool pending = false;
+ 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);
- assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
- /* 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 (!c) {
+ r = dns_query_synthesize_reply(q, &state);
+ if (r < 0)
+ goto fail;
- if (q->block_ready > 0)
+ dns_query_complete(q, state);
return;
+ }
- SET_FOREACH(t, q->transactions, i) {
-
- /* If we found a successful answer, ignore all answers from other scopes */
- if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
- continue;
-
- /* One of the transactions is still going on, let's maybe wait for it */
- if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
- pending = true;
- continue;
- }
+ 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;
+ }
- /* One of the transactions is successful, let's use
- * it, and copy its data out */
- if (t->state == DNS_TRANSACTION_SUCCESS) {
- DnsAnswer *a;
+ SET_FOREACH(t, c->transactions, i) {
- if (t->received) {
- rcode = DNS_PACKET_RCODE(t->received);
- a = t->received->answer;
- } else {
- rcode = t->cached_rcode;
- a = t->cached;
- }
+ switch (t->state) {
- if (state == DNS_TRANSACTION_SUCCESS) {
- DnsAnswer *merged;
+ 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;
- merged = dns_answer_merge(answer, a);
- if (!merged) {
- dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
- return;
- }
+ q->answer_rcode = t->answer_rcode;
+ q->answer_errno = 0;
- dns_answer_unref(answer);
- answer = merged;
+ if (t->answer_authenticated) {
+ has_authenticated = true;
+ dnssec_result_authenticated = t->answer_dnssec_result;
} else {
- dns_answer_unref(answer);
- answer = dns_answer_ref(a);
+ has_non_authenticated = true;
+ dnssec_result_non_authenticated = t->answer_dnssec_result;
}
- scope = t->scope;
state = DNS_TRANSACTION_SUCCESS;
- continue;
+ break;
}
- /* One of the transactions has failed, let's see
- * whether we find anything better, but if not, return
- * its response data */
- if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
- DnsAnswer *a;
+ case DNS_TRANSACTION_NULL:
+ case DNS_TRANSACTION_PENDING:
+ case DNS_TRANSACTION_VALIDATING:
+ case DNS_TRANSACTION_ABORTED:
+ /* Ignore transactions that didn't complete */
+ continue;
- if (t->received) {
- rcode = DNS_PACKET_RCODE(t->received);
- a = t->received->answer;
- } else {
- rcode = t->cached_rcode;
- a = t->cached;
- }
+ default:
+ /* Any kind of failure? Store the data away,
+ * if there's nothing stored yet. */
- dns_answer_unref(answer);
- answer = dns_answer_ref(a);
+ if (state == DNS_TRANSACTION_SUCCESS)
+ continue;
- scope = t->scope;
- state = DNS_TRANSACTION_FAILURE;
- 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;
- if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
state = t->state;
+ break;
+ }
}
- if (pending) {
+ 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;
- /* If so far we weren't successful, and there's
- * something still pending, then wait for it */
- if (state != DNS_TRANSACTION_SUCCESS)
+ 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;
- /* If we already were successful, then only wait for
- * other transactions on the same scope to finish. */
- SET_FOREACH(t, q->transactions, i) {
- if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
- 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;
- if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
- q->answer = dns_answer_ref(answer);
- q->answer_rcode = rcode;
- q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
- q->answer_family = scope ? scope->family : AF_UNSPEC;
+ default:
+ /* Any kind of failure */
+ bad = c;
+ break;
+ }
}
- /* Try to synthesize a reply if we couldn't resolve something. */
- dns_query_synthesize_reply(q, &state);
+ if (pending)
+ return;
- dns_query_complete(q, state);
+ dns_query_accept(q, bad);
}
-int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
- _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
- int r;
+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, cname, &nq);
+ 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));
+ }
- dns_question_unref(q->question);
- q->question = nq;
- nq = NULL;
+ if (r == 0 && k == 0) /* No actual cname happened? */
+ return -ELOOP;
- q->n_cname_redirects++;
+ 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);
- dns_query_stop(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;
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);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-bus.h"
+
#include "set.h"
+typedef struct DnsQueryCandidate DnsQueryCandidate;
typedef struct DnsQuery DnsQuery;
-#include "resolved-dns-question.h"
#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;
- DnsQuestion *question;
+
+ /* 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_family;
- DnsProtocol answer_protocol;
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;
- const char *request_hostname;
+ 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;
- Set *transactions;
-
sd_bus_track *bus_track;
LIST_FIELDS(DnsQuery, queries);
+ LIST_FIELDS(DnsQuery, auxiliary_queries);
};
-int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question, int family, uint64_t flags);
+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_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "alloc-util.h"
#include "dns-domain.h"
+#include "dns-type.h"
#include "resolved-dns-question.h"
DnsQuestion *dns_question_new(unsigned n) {
return 0;
}
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
+int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
unsigned i;
int r;
return 0;
for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_match_rr(q->keys[i], rr);
+ r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
if (r != 0)
return r;
}
return 0;
}
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
+int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
unsigned i;
int r;
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++) {
- r = dns_resource_key_match_cname(q->keys[i], rr);
+ /* 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(DnsQuestion *q) {
+int dns_question_is_valid_for_query(DnsQuestion *q) {
const char *name;
unsigned i;
int r;
return 0;
/* Check that all keys in this question bear the same name */
- for (i = 1; i < q->n_keys; i++) {
+ for (i = 0; i < q->n_keys; i++) {
assert(q->keys[i]);
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
- if (r <= 0)
- return r;
- }
-
- return 1;
-}
-
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) {
- unsigned j;
- int r;
-
- /* Checks if all keys in "other" are also contained in "q" */
-
- if (!other)
- return 1;
-
- for (j = 0; j < other->n_keys; j++) {
- DnsResourceKey *b = other->keys[j];
- bool found = false;
- unsigned i;
-
- if (!q)
- return 0;
-
- for (i = 0; i < q->n_keys; i++) {
- DnsResourceKey *a = q->keys[i];
-
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
- if (r < 0)
+ if (i > 0) {
+ r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
+ if (r <= 0)
return r;
-
- if (r == 0)
- continue;
-
- if (a->class != b->class && a->class != DNS_CLASS_ANY)
- continue;
-
- if (a->type != b->type && a->type != DNS_TYPE_ANY)
- continue;
-
- found = true;
- break;
}
- if (!found)
+ if (!dns_type_is_valid_query(q->keys[i]->type))
return 0;
}
return 1;
}
-int dns_question_contains(DnsQuestion *a, DnsResourceKey *k) {
+int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
unsigned j;
int r;
unsigned j;
int r;
+ if (a == b)
+ return 1;
+
if (!a)
return !b || b->n_keys == 0;
if (!b)
int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
_cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
+ DnsResourceKey *key;
bool same = true;
- unsigned i;
int r;
assert(cname);
assert(ret);
+ assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
- if (!q) {
- n = dns_question_new(0);
- if (!n)
- return -ENOMEM;
-
- *ret = n;
- n = 0;
+ if (dns_question_size(q) <= 0) {
+ *ret = NULL;
return 0;
}
- for (i = 0; i < q->n_keys; i++) {
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), cname->cname.name);
+ 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;
}
}
+ /* Fully the same, indicate we didn't do a thing */
if (same) {
- /* Shortcut, the names are already right */
- *ret = dns_question_ref(q);
+ *ret = NULL;
return 0;
}
return -ENOMEM;
/* Create a new question, and patch in the new name */
- for (i = 0; i < q->n_keys; i++) {
+ DNS_QUESTION_FOREACH(key, q) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
- k = dns_resource_key_new_redirect(q->keys[i], cname);
+ k = dns_resource_key_new_redirect(key, cname);
if (!k)
return -ENOMEM;
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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct DnsQuestion DnsQuestion;
+#include "macro.h"
#include "resolved-dns-rr.h"
-/* A simple array of resources keys */
+/* A simple array of resource keys */
struct DnsQuestion {
unsigned n_ref;
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);
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr);
-int dns_question_is_valid(DnsQuestion *q);
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other);
-int dns_question_contains(DnsQuestion *a, DnsResourceKey *k);
+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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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;
return k;
}
-DnsResourceKey* dns_resource_key_new_cname(const DnsResourceKey *key) {
+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));
- return dns_resource_key_new(key->class, DNS_TYPE_CNAME, DNS_RESOURCE_KEY_NAME(key));
+ 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;
+ }
}
-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 *new_key;
+ char *joined;
+ int r;
+
+ assert(ret);
assert(key);
- assert(cname);
+ assert(name);
- return dns_resource_key_new(key->class, key->type, cname->cname.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) {
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++;
if (!k)
return NULL;
+ assert(k->n_ref != (unsigned) -1);
assert(k->n_ref > 0);
if (k->n_ref == 1) {
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;
return 1;
}
-int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
+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;
- return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
+ 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(const DnsResourceKey *key, const DnsResourceRecord *rr) {
+int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
+ int r;
+
assert(key);
- assert(rr);
+ assert(cname);
- if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
+ 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 (rr->key->type != DNS_TYPE_CNAME)
+ if (soa->type != DNS_TYPE_SOA)
return 0;
- return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
+ 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) {
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;
+ 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);
t = tbuf;
}
- if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
+ 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->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;
}
case DNS_TYPE_TXT:
case DNS_TYPE_SPF:
- strv_free(rr->txt.strings);
+ dns_txt_item_free_all(rr->txt.items);
break;
case DNS_TYPE_SOA:
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;
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;
case DNS_TYPE_SPF: /* exactly the same as TXT */
case DNS_TYPE_TXT:
- return strv_equal(a->txt.strings, b->txt.strings);
+ 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;
return a->ds.key_tag == b->ds.key_tag &&
a->ds.algorithm == b->ds.algorithm &&
a->ds.digest_type == b->ds.digest_type &&
- a->ds.digest_size == b->ds.digest_size &&
- memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
+ FIELD_EQUAL(a->ds, b->ds, digest);
case DNS_TYPE_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
- a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
- memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
+ FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
case DNS_TYPE_DNSKEY:
- return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
- a->dnskey.sep_flag == b->dnskey.sep_flag &&
+ return a->dnskey.flags == b->dnskey.flags &&
+ a->dnskey.protocol == b->dnskey.protocol &&
a->dnskey.algorithm == b->dnskey.algorithm &&
- a->dnskey.key_size == b->dnskey.key_size &&
- memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
+ FIELD_EQUAL(a->dnskey, b->dnskey, key);
case DNS_TYPE_RRSIG:
/* do the fast comparisons first */
- if (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 ||
- a->rrsig.signature_size != b->rrsig.signature_size ||
- memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
- return false;
-
- return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
+ 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) &&
case DNS_TYPE_NSEC3:
return a->nsec3.algorithm == b->nsec3.algorithm &&
- a->nsec3.flags == b->nsec3.flags &&
- a->nsec3.iterations == b->nsec3.iterations &&
- a->nsec3.salt_size == b->nsec3.salt_size &&
- memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
- memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
- bitmap_equal(a->nsec3.types, b->nsec3.types);
+ 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 a->generic.size == b->generic.size &&
- memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
+ return FIELD_EQUAL(a->generic, b->generic, data);
}
}
return strjoin("( ", str, " )", NULL);
}
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
+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 r;
+ return NULL;
switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
rr->srv.port,
strna(rr->srv.name));
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_PTR:
case DNS_TYPE_DNAME:
s = strjoin(k, " ", rr->ptr.name, NULL);
if (!s)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_HINFO:
s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
if (!s)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_SPF: /* exactly the same as TXT */
case DNS_TYPE_TXT:
- t = strv_join_quoted(rr->txt.strings);
+ t = format_txt(rr->txt.items);
if (!t)
- return -ENOMEM;
+ return NULL;
s = strjoin(k, " ", t, NULL);
if (!s)
- return -ENOMEM;
-
+ return NULL;
break;
case DNS_TYPE_A: {
r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
if (r < 0)
- return r;
+ return NULL;
s = strjoin(k, " ", x, NULL);
if (!s)
- return -ENOMEM;
+ 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 r;
+ return NULL;
s = strjoin(k, " ", t, NULL);
if (!s)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_SOA:
rr->soa.expire,
rr->soa.minimum);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_MX:
rr->mx.priority,
rr->mx.exchange);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_LOC:
rr->loc.horiz_pre,
rr->loc.vert_pre);
if (!t)
- return -ENOMEM;
+ return NULL;
s = strjoin(k, " ", t, NULL);
if (!s)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_DS:
t = hexmem(rr->ds.digest, rr->ds.digest_size);
if (!t)
- return -ENOMEM;
+ return NULL;
r = asprintf(&s, "%s %u %u %u %s",
k,
rr->ds.digest_type,
t);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_SSHFP:
t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
if (!t)
- return -ENOMEM;
+ return NULL;
r = asprintf(&s, "%s %u %u %s",
k,
rr->sshfp.fptype,
t);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_DNSKEY: {
- const char *alg;
+ _cleanup_free_ char *alg = NULL;
+ char *ss;
+ int n, n1;
+ uint16_t key_tag;
- alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
+ key_tag = dnssec_keytag(rr, true);
- t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
- if (!t)
- return -ENOMEM;
+ r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
+ if (r < 0)
+ return NULL;
- r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
+ r = asprintf(&s, "%s %n%u %u %s %n",
k,
- dnskey_to_flags(rr),
- alg ? -1 : 0, alg,
- alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
- t);
+ &n1,
+ rr->dnskey.flags,
+ rr->dnskey.protocol,
+ alg,
+ &n);
if (r < 0)
- return -ENOMEM;
+ 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: {
- const char *type, *alg;
+ _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);
- alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
- t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
- if (!t)
- return -ENOMEM;
+ 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 r;
+ return NULL;
r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
if (r < 0)
- return r;
+ return NULL;
/* TYPE?? follows
* http://tools.ietf.org/html/rfc3597#section-5 */
- r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
+ 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 ? -1 : 0, alg,
- alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
+ alg,
rr->rrsig.labels,
rr->rrsig.original_ttl,
expiration,
inception,
rr->rrsig.key_tag,
rr->rrsig.signer,
- t);
+ &n);
if (r < 0)
- return -ENOMEM;
+ 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 -ENOMEM;
+ return NULL;
r = asprintf(&s, "%s %s %s",
k,
rr->nsec.next_domain_name,
t);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
case DNS_TYPE_NSEC3: {
if (rr->nsec3.salt_size > 0) {
salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
if (!salt)
- return -ENOMEM;
+ return NULL;
}
hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
if (!hash)
- return -ENOMEM;
+ return NULL;
t = format_types(rr->nsec3.types);
if (!t)
- return -ENOMEM;
+ return NULL;
r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
k,
hash,
t);
if (r < 0)
- return -ENOMEM;
+ 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.size);
+ t = hexmem(rr->generic.data, rr->generic.data_size);
if (!t)
- return -ENOMEM;
+ return NULL;
- r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
+ /* Format as documented in RFC 3597, Section 5 */
+ r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
if (r < 0)
- return -ENOMEM;
+ return NULL;
break;
}
- *ret = s;
+ 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;
}
-const char *dns_class_to_string(uint16_t class) {
+int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
+ const char *n;
+ int r;
- switch (class) {
+ assert(rr);
+ assert(ret);
- case DNS_CLASS_IN:
- return "IN";
+ /* Returns the RRset's signer, if it is known. */
- case DNS_CLASS_ANY:
- return "ANY";
- }
+ if (rr->n_skip_labels_signer == (unsigned) -1)
+ return -ENODATA;
- return NULL;
+ 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_class_from_string(const char *s, uint16_t *class) {
- assert(s);
- assert(class);
+int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
+ const char *n;
+ int r;
+
+ assert(rr);
+ assert(ret);
- if (strcaseeq(s, "IN"))
- *class = DNS_CLASS_IN;
- else if (strcaseeq(s, "ANY"))
- *class = DNS_CLASS_ANY;
- else
+ /* 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <netinet/in.h>
#include "bitmap.h"
+#include "dns-type.h"
#include "hashmap.h"
#include "in-addr-util.h"
-#include "dns-type.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
+};
-/* DNS record classes, see RFC 1035 */
+/* DNSSEC NSEC3 hash algorithms, see
+ * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
enum {
- DNS_CLASS_IN = 0x01,
- DNS_CLASS_ANY = 0xFF,
- _DNS_CLASS_MAX,
- _DNS_CLASS_INVALID = -1
+ NSEC3_ALGORITHM_SHA1 = 1,
+ _NSEC3_ALGORITHM_MAX_DEFINED
};
struct DnsResourceKey {
- unsigned n_ref;
+ 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;
- bool unparseable;
+ 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 size;
- } generic;
+ size_t data_size;
+ } generic, opt;
struct {
uint16_t priority;
} hinfo;
struct {
- char **strings;
+ DnsTxtItem *items;
} txt, spf;
struct {
char *exchange;
} mx;
+ /* https://tools.ietf.org/html/rfc1876 */
struct {
uint8_t version;
uint8_t size;
uint32_t altitude;
} loc;
- struct {
- uint16_t key_tag;
- uint8_t algorithm;
- uint8_t digest_type;
- void *digest;
- size_t digest_size;
- } ds;
-
/* https://tools.ietf.org/html/rfc4255#section-3.1 */
struct {
uint8_t algorithm;
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
struct {
- bool zone_key_flag:1;
- bool sep_flag:1;
+ uint16_t flags;
+ uint8_t protocol;
uint8_t algorithm;
void* key;
size_t key_size;
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;
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 (_unlikely_(!key))
+ if (!key)
return NULL;
if (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_cname(const DnsResourceKey *key);
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, const DnsResourceRecord *rr);
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr);
+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);
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);
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret);
+const char* dns_resource_record_to_string(DnsResourceRecord *rr);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
-const char *dns_class_to_string(uint16_t type);
-int dns_class_from_string(const char *name, uint16_t *class);
+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_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "random-util.h"
#include "resolved-dns-scope.h"
#include "resolved-llmnr.h"
+#include "resolved-mdns.h"
#include "socket-util.h"
#include "strv.h"
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));
return 0;
}
-DnsScope* dns_scope_free(DnsScope *s) {
- DnsTransaction *t;
- 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));
+static void dns_scope_abort_transactions(DnsScope *s) {
+ assert(s);
- dns_scope_llmnr_membership(s, false);
+ while (s->transactions) {
+ DnsTransaction *t = s->transactions;
- while ((t = hashmap_steal_first(s->transactions))) {
/* Abort the transaction, but make sure it is not
* freed while we still look at it */
t->block_gc++;
- dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
+ if (DNS_TRANSACTION_IS_LIVE(t->state))
+ dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
t->block_gc--;
dns_transaction_free(t);
}
+}
- hashmap_free(s->transactions);
+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);
dns_zone_flush(&s->zone);
LIST_REMOVE(scopes, s->manager->dns_scopes, s);
- strv_free(s->domains);
free(s);
return NULL;
void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
assert(s);
- if (rtt > s->max_rtt) {
- s->max_rtt = rtt;
- s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2),
- MULTICAST_RESEND_TIMEOUT_MAX_USEC);
- }
+ 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) {
s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
}
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
+static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
union in_addr_union addr;
int ifindex = 0, r;
int family;
- uint16_t port;
uint32_t mtu;
assert(s);
assert(p);
assert(p->protocol == s->protocol);
- assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
if (s->link) {
mtu = s->link->mtu;
mtu = manager_find_mtu(s->manager);
switch (s->protocol) {
+
case DNS_PROTOCOL_DNS:
+ assert(fd >= 0);
+
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
break;
case DNS_PROTOCOL_LLMNR:
+ assert(fd < 0);
+
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
return -EBUSY;
family = s->family;
- port = LLMNR_PORT;
if (family == AF_INET) {
addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
if (fd < 0)
return fd;
- r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
+ 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;
return 1;
}
-static int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
- DnsServer *srv = NULL;
+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;
int ret, r;
assert(s);
- assert((family == AF_UNSPEC) == !address);
- if (family == AF_UNSPEC) {
- srv = dns_scope_get_dns_server(s);
- if (!srv)
- return -ESRCH;
+ if (server) {
+ assert(family == AF_UNSPEC);
+ assert(!address);
- sa.sa.sa_family = srv->family;
- if (srv->family == AF_INET) {
+ sa.sa.sa_family = server->family;
+ if (server->family == AF_INET) {
sa.in.sin_port = htobe16(port);
- sa.in.sin_addr = srv->address.in;
+ sa.in.sin_addr = server->address.in;
salen = sizeof(sa.in);
- } else if (srv->family == AF_INET6) {
+ } else if (server->family == AF_INET6) {
sa.in6.sin6_port = htobe16(port);
- sa.in6.sin6_addr = srv->address.in6;
+ 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) {
if (r < 0 && errno != EINPROGRESS)
return -errno;
- if (server)
- *server = srv;
-
ret = fd;
fd = -1;
return ret;
}
-int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server) {
- return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, 53, server);
+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_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
- return dns_scope_socket(s, SOCK_STREAM, family, address, port, server);
+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) {
- char **i;
+ DnsSearchDomain *d;
assert(s);
assert(domain);
- if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
- return DNS_SCOPE_NO;
+ /* 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 ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
+ if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
return DNS_SCOPE_NO;
- if (dns_name_root(domain) != 0)
+ 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,
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;
- STRV_FOREACH(i, s->domains)
- if (dns_name_endswith(domain, *i) > 0)
+ /* 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, "0.8.e.f.ip6.arpa") == 0 &&
- dns_name_single_label(domain) == 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_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_single_label(domain) > 0 && /* only resolve single label names via LLMNR */
+ (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;
}
}
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
+bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
+ int key_family;
+
assert(s);
assert(key);
- if (s->protocol == DNS_PROTOCOL_DNS)
- return true;
+ /* 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 */
- if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
- return false;
-
- if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
- return false;
+ key_family = dns_type_to_af(key->type);
+ if (key_family < 0)
+ return true;
- return true;
+ return key_family == s->family;
}
-int dns_scope_llmnr_membership(DnsScope *s, bool b) {
+static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
int fd;
assert(s);
-
- if (s->protocol != DNS_PROTOCOL_LLMNR)
- return 0;
-
assert(s->link);
if (s->family == AF_INET) {
struct ip_mreqn mreqn = {
- .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
+ .imr_multiaddr = in,
.imr_ifindex = s->link->ifindex,
};
} else if (s->family == AF_INET6) {
struct ipv6_mreq mreq = {
- .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
+ .ipv6mr_multiaddr = in6,
.ipv6mr_interface = s->link->ifindex,
};
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,
if (answer) {
for (i = 0; i < answer->n_rrs; i++) {
- r = dns_packet_append_rr(p, answer->items[i].rr, NULL);
+ r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
if (r < 0)
return r;
}
if (soa) {
for (i = 0; i < soa->n_rrs; i++) {
- r = dns_packet_append_rr(p, soa->items[i].rr, NULL);
+ r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
if (r < 0)
return r;
}
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;
return;
}
- r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
+ 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;
/* Try to find an ongoing transaction that is a equal to the
* specified question */
- t = hashmap_get(scope->transactions, key);
+ 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_FAILURE) &&
- !t->received)
+ IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
+ t->answer_source != DNS_TRANSACTION_NETWORK)
return NULL;
return t;
0 /* (ad) */,
0 /* (cd) */,
0));
- random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
+
+ /* 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);
if (r < 0)
return r;
- r = dns_packet_append_rr(p, rr, NULL);
+ r = dns_packet_append_rr(p, rr, NULL, NULL);
if (r < 0)
return r;
return 0;
}
- r = dns_scope_emit(scope, -1, p);
+ r = dns_scope_emit_udp(scope, -1, p);
if (r < 0)
log_debug_errno(r, "Failed to send conflict packet: %m");
}
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;
}
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);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct DnsScope DnsScope;
-#include "resolved-dns-server.h"
-#include "resolved-dns-packet.h"
#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"
DnsProtocol protocol;
int family;
+ DnssecMode dnssec_mode;
Link *link;
- char **domains;
-
DnsCache cache;
DnsZone zone;
usec_t resend_timeout;
usec_t max_rtt;
- Hashmap *transactions;
+ 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);
};
void dns_scope_packet_received(DnsScope *s, usec_t rtt);
void dns_scope_packet_lost(DnsScope *s, usec_t usec);
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p);
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);
-int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server);
+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);
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
+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);
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);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sd-messages.h>
+
#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,
int family,
const union in_addr_union *in_addr) {
- DnsServer *s, *tail;
+ 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;
- if (type == DNS_SERVER_LINK) {
- LIST_FIND_TAIL(servers, l->dns_servers, tail);
- LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
+ switch (type) {
+
+ case DNS_SERVER_LINK:
s->link = l;
- } else if (type == DNS_SERVER_SYSTEM) {
- LIST_FIND_TAIL(servers, m->dns_servers, tail);
- LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
- } else if (type == DNS_SERVER_FALLBACK) {
- LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
- LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
- } else
+ 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->manager = m;
+ 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
return NULL;
assert(s->n_ref > 0);
-
s->n_ref ++;
return s;
}
-static DnsServer* dns_server_free(DnsServer *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 && s->manager->current_dns_server == s)
+ if (s->manager->current_dns_server == s)
manager_set_dns_server(s->manager, NULL);
- free(s);
+ dns_server_unref(s);
+}
- return NULL;
+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");
+ }
}
-DnsServer* dns_server_unref(DnsServer *s) {
- if (!s)
- return NULL;
+static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) {
+ assert(s);
- assert(s->n_ref > 0);
+ if (s->verified_feature_level > level)
+ return;
- if (s->n_ref == 1)
- dns_server_free(s);
- else
- s->n_ref --;
+ 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;
+ }
- return NULL;
+ assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0);
}
-void dns_server_packet_received(DnsServer *s, usec_t rtt) {
+void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) {
assert(s);
- if (rtt > s->max_rtt) {
+ 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 = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2),
- DNS_TIMEOUT_MAX_USEC);
+ s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
}
}
-void dns_server_packet_lost(DnsServer *s, usec_t 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);
- if (s->resend_timeout <= usec)
- s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
+ /* 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) {
.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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "in-addr-util.h"
typedef struct DnsServer DnsServer;
-typedef enum DnsServerSource DnsServerSource;
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 **s,
+ DnsServer **ret,
DnsServerType type,
- Link *l,
+ 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_packet_received(DnsServer *s, usec_t rtt);
-void dns_server_packet_lost(DnsServer *s, usec_t usec);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_free);
int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
- static const int one = 1;
_cleanup_(dns_stream_freep) DnsStream *s = NULL;
int r;
s->fd = -1;
s->protocol = protocol;
- r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
- if (r < 0)
- return -errno;
-
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,
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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sd-messages.h>
+
#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) {
- DnsQuery *q;
+ DnsQueryCandidate *c;
DnsZoneItem *i;
+ DnsTransaction *z;
if (!t)
return NULL;
- sd_event_source_unref(t->timeout_event_source);
+ log_debug("Freeing transaction %" PRIu16 ".", t->id);
- dns_packet_unref(t->sent);
- dns_packet_unref(t->received);
- dns_answer_unref(t->cached);
+ dns_transaction_close_connection(t);
+ dns_transaction_stop_timeout(t);
- sd_event_source_unref(t->dns_udp_event_source);
- safe_close(t->dns_udp_fd);
+ dns_packet_unref(t->sent);
+ dns_transaction_reset_answer(t);
dns_server_unref(t->server);
- dns_stream_free(t->stream);
if (t->scope) {
- hashmap_remove(t->scope->transactions, t->key);
+ 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));
}
- dns_resource_key_unref(t->key);
-
- while ((q = set_steal_first(t->queries)))
- set_remove(q->transactions, t);
- set_free(t->queries);
+ 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->zone_items)))
+ while ((i = set_steal_first(t->notify_zone_items)))
i->probe_transaction = NULL;
- set_free(t->zone_items);
+ 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);
-void dns_transaction_gc(DnsTransaction *t) {
+bool dns_transaction_gc(DnsTransaction *t) {
assert(t);
if (t->block_gc > 0)
- return;
+ return true;
- if (set_isempty(t->queries) && set_isempty(t->zone_items))
+ 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) {
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, &dns_resource_key_hash_ops);
+ r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
if (r < 0)
return r;
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;
- /* Find a fresh, unused transaction id */
- do
- random_bytes(&t->id, sizeof(t->id));
- while (t->id == 0 ||
- hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
+ t->id = pick_new_id(s->manager);
r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
if (r < 0) {
return r;
}
- r = hashmap_put(s->transactions, t->key, t);
+ 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;
return 0;
}
-static void dns_transaction_stop(DnsTransaction *t) {
+static void dns_transaction_shuffle_id(DnsTransaction *t) {
+ uint16_t new_id;
assert(t);
- t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
- t->stream = dns_stream_free(t->stream);
+ /* 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) {
in_addr_to_string(p->family, &p->sender, &pretty);
- log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
+ 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),
log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
t->block_gc++;
- while ((z = set_first(t->zone_items))) {
+ 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);
}
void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
- DnsQuery *q;
+ DnsQueryCandidate *c;
DnsZoneItem *z;
+ DnsTransaction *d;
Iterator i;
+ const char *st;
assert(t);
- assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
+ 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. */
- log_debug("Transaction on scope %s on %s/%s now complete with <%s>",
+ 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),
- dns_transaction_state_to_string(state));
+ st,
+ t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
+ t->answer_authenticated ? "authenticated" : "unsigned");
t->state = state;
- dns_transaction_stop(t);
+ 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(q, t->queries, i)
- dns_query_ready(q);
- SET_FOREACH(z, t->zone_items, i)
- dns_zone_item_ready(z);
- 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;
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) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+ t->answer_errno = error;
+ dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
return 0;
}
if (dns_packet_validate_reply(p) <= 0) {
- log_debug("Invalid LLMNR TCP packet.");
+ log_debug("Invalid TCP reply packet.");
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
return 0;
}
dns_transaction_process_reply(t, p);
t->block_gc--;
- /* If the response wasn't useful, then complete the transition now */
+ /* 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) {
- DnsServer *server = NULL;
_cleanup_close_ int fd = -1;
int r;
assert(t);
- if (t->stream)
- return 0;
+ dns_transaction_close_connection(t);
switch (t->scope->protocol) {
+
case DNS_PROTOCOL_DNS:
- fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
+ 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_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
+ 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;
if (family != t->scope->family)
return -ESRCH;
- fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
+ fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT);
}
break;
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);
return r;
}
- dns_server_unref(t->server);
- t->server = dns_server_ref(server);
- t->received = dns_packet_unref(t->received);
t->stream->complete = on_stream_complete;
t->stream->transaction = t;
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_next_dns_server(DnsTransaction *t) {
+static void dns_transaction_cache_answer(DnsTransaction *t) {
assert(t);
- t->server = dns_server_unref(t->server);
- t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
- t->dns_udp_fd = safe_close(t->dns_udp_fd);
+ /* 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;
- dns_scope_next_dns_server(t->scope);
+ /* 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) {
assert(t);
assert(p);
- assert(t->state == DNS_TRANSACTION_PENDING);
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);
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:
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 */
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);
- dns_server_packet_received(t->server, ts - t->start_usec);
+ 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:
- break;
+ 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) {
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_LLMNR) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return;
- }
+ if (t->scope->protocol != DNS_PROTOCOL_DNS)
+ goto fail;
/* On DNS, couldn't send? Try immediately again, with a new server */
- dns_transaction_next_dns_server(t);
-
- r = dns_transaction_go(t);
- if (r < 0) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return;
- }
-
- return;
+ dns_transaction_retry(t);
}
+
+ return;
}
- /* Parse and update the cache */
+ /* 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;
}
- /* Only consider responses with equivalent query section to the request */
- if (p->question->n_keys != 1 || dns_resource_key_equal(p->question->keys[0], t->key) <= 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);
}
- /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
- dns_cache_put(&t->scope->cache, t->key, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
+ /* 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 (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
- dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
- else
- dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
+ 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) {
assert(t->scope);
r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
- if (r <= 0)
- return r;
+ if (ERRNO_IS_DISCONNECT(-r)) {
+ usec_t usec;
- if (dns_packet_validate_reply(p) > 0 &&
- DNS_PACKET_ID(p) == t->id)
- dns_transaction_process_reply(t, p);
- else
- log_debug("Invalid DNS packet.");
+ /* 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(DnsTransaction *t) {
+static int dns_transaction_emit_udp(DnsTransaction *t) {
int r;
assert(t);
- if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
- DnsServer *server = NULL;
- _cleanup_close_ int fd = -1;
+ if (t->scope->protocol == DNS_PROTOCOL_DNS) {
- fd = dns_scope_udp_dns_socket(t->scope, &server);
- 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);
+ r = dns_transaction_pick_server(t);
if (r < 0)
return r;
- t->dns_udp_fd = fd;
- fd = -1;
- t->server = dns_server_ref(server);
- }
+ if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP)
+ return -EAGAIN;
- r = dns_scope_emit(t->scope, t->dns_udp_fd, t->sent);
- if (r < 0)
- return r;
+ if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
+ return -EOPNOTSUPP;
- return 0;
-}
+ if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
+ int fd;
-static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
- DnsTransaction *t = userdata;
- int r;
+ dns_transaction_close_connection(t);
- assert(s);
- assert(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;
+ }
- /* Timeout reached? Try again, with a new server */
- dns_transaction_next_dns_server(t);
+ (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp");
+ t->dns_udp_fd = fd;
+ }
- /* ... and possibly increased timeout */
- if (t->server)
- dns_server_packet_lost(t->server, usec - t->start_usec);
- else
- dns_scope_packet_lost(t->scope, usec - t->start_usec);
+ 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_transaction_go(t);
+ r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent);
if (r < 0)
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+ return r;
+
+ dns_transaction_reset_answer(t);
return 0;
}
-static int dns_transaction_make_packet(DnsTransaction *t) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- int r;
+static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
+ DnsTransaction *t = userdata;
+ assert(s);
assert(t);
- if (t->sent)
- return 0;
+ if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
+ /* Timeout reached? Increase the timeout for the server used */
+ switch (t->scope->protocol) {
- r = dns_packet_new_query(&p, t->scope->protocol, 0);
- if (r < 0)
- return r;
+ 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;
- r = dns_scope_good_key(t->scope, t->key);
- if (r < 0)
- return r;
- if (r == 0)
- return -EDOM;
+ case DNS_PROTOCOL_LLMNR:
+ case DNS_PROTOCOL_MDNS:
+ dns_scope_packet_lost(t->scope, usec - t->start_usec);
+ break;
- r = dns_packet_append_key(p, t->key, NULL);
- if (r < 0)
- return r;
+ default:
+ assert_not_reached("Invalid DNS protocol.");
+ }
- DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
- DNS_PACKET_HEADER(p)->id = t->id;
+ if (t->initial_jitter_scheduled)
+ t->initial_jitter_elapsed = true;
+ }
- t->sent = p;
- p = NULL;
+ log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
+ dns_transaction_retry(t);
return 0;
}
assert(t->scope);
switch (t->scope->protocol) {
+
case DNS_PROTOCOL_DNS:
assert(t->server);
-
return t->server->resend_timeout;
- case DNS_PROTOCOL_LLMNR:
+
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.");
}
}
-int dns_transaction_go(DnsTransaction *t) {
- bool had_stream;
- usec_t ts;
+static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
int r;
assert(t);
- had_stream = !!t->stream;
-
- dns_transaction_stop(t);
+ dns_transaction_stop_timeout(t);
- log_debug("Excercising transaction on scope %s on %s/%s",
- 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));
+ 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 && had_stream) {
+ 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;
}
- assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
-
t->n_attempts++;
t->start_usec = ts;
- t->received = dns_packet_unref(t->received);
- t->cached = dns_answer_unref(t->cached);
- t->cached_rcode = 0;
+
+ 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->zone_items)) {
+ 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
/* Let's then prune all outdated entries */
dns_cache_prune(&t->scope->cache);
- r = dns_cache_lookup(&t->scope->cache, t->key, &t->cached_rcode, &t->cached);
+ 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) {
- if (t->cached_rcode == DNS_RCODE_SUCCESS)
+ 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_FAILURE);
+ dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
return 0;
}
}
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR && !t->initial_jitter) {
- usec_t jitter;
+ 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 = true;
+ t->initial_jitter_scheduled = true;
random_bytes(&jitter, sizeof(jitter));
- jitter %= LLMNR_JITTER_INTERVAL_USEC;
+
+ 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,
- LLMNR_JITTER_INTERVAL_USEC,
+ 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 LLMNR transaction for " USEC_FMT "us.", jitter);
+ 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 == -EDOM) {
- /* Not the right request to make on this network?
- * (i.e. an A request made on IPv6 or an AAAA request
- * made on IPv4, on LLMNR or mDNS.) */
- dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
- return 0;
- }
if (r < 0)
return r;
* 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 try via TCP */
- r = dns_transaction_emit(t);
+ /* 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;
- } else if (r < 0) {
- if (t->scope->protocol != DNS_PROTOCOL_DNS) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- 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_transaction_next_dns_server(t);
+ 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 + transaction_get_resend_timeout(t), 0,
+ 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 const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
- [DNS_TRANSACTION_NULL] = "null",
- [DNS_TRANSACTION_PENDING] = "pending",
- [DNS_TRANSACTION_FAILURE] = "failure",
- [DNS_TRANSACTION_SUCCESS] = "success",
- [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
- [DNS_TRANSACTION_TIMEOUT] = "timeout",
- [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
+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_RESOURCES] = "resources",
+ [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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct DnsTransaction DnsTransaction;
typedef enum DnsTransactionState DnsTransactionState;
+typedef enum DnsTransactionSource DnsTransactionSource;
enum DnsTransactionState {
DNS_TRANSACTION_NULL,
DNS_TRANSACTION_PENDING,
- DNS_TRANSACTION_FAILURE,
+ 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_RESOURCES,
+ 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
};
-#include "resolved-dns-scope.h"
+#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-answer.h"
+#include "resolved-dns-scope.h"
struct DnsTransaction {
DnsScope *scope;
DnsResourceKey *key;
+ char *key_string;
DnsTransactionState state;
+
uint16_t id;
- bool initial_jitter;
+ bool tried_stream:1;
+
+ bool initial_jitter_scheduled:1;
+ bool initial_jitter_elapsed:1;
DnsPacket *sent, *received;
- DnsAnswer *cached;
- int cached_rcode;
+
+ 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;
- /* TCP connection logic, if we need it */
- DnsStream *stream;
+ /* The features of the DNS server at time of transaction start */
+ DnsServerFeatureLevel current_feature_level;
- /* Queries this transaction is referenced by and that shall be
- * notified about this specific transaction completing. */
- Set *queries;
+ /* 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 *zone_items;
+ 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;
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
DnsTransaction* dns_transaction_free(DnsTransaction *t);
-void dns_transaction_gc(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)
+#define TRANSACTION_ATTEMPTS_MAX(p) ((p) == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX)
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <sd-messages.h>
+
+#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);
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
t = i->probe_transaction;
i->probe_transaction = NULL;
- set_remove(t->zone_items, i);
+ set_remove(t->notify_zone_items, i);
dns_transaction_gc(t);
}
}
static int dns_zone_item_probe_start(DnsZoneItem *i) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
DnsTransaction *t;
int r;
if (i->probe_transaction)
return 0;
- key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key));
- if (!key)
- return -ENOMEM;
-
- t = dns_scope_find_transaction(i->scope, key, false);
+ 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->zone_items, NULL);
+ r = set_ensure_allocated(&t->notify_zone_items, NULL);
if (r < 0)
goto gc;
- r = set_put(t->zone_items, i);
+ r = set_put(t->notify_zone_items, i);
if (r < 0)
goto gc;
}
}
- dns_zone_item_ready(i);
+ dns_zone_item_notify(i);
return 0;
gc:
assert(s);
assert(rr);
- if (rr->key->class == DNS_CLASS_ANY)
+ if (dns_class_is_pseudo(rr->key->class))
return -EINVAL;
- if (rr->key->type == DNS_TYPE_ANY)
+ if (dns_type_is_pseudo(rr->key->type))
return -EINVAL;
existing = dns_zone_get(z, rr);
return 0;
}
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+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 i, n_answer = 0, n_soa = 0;
- bool tentative = true;
+ unsigned n_answer = 0;
+ DnsZoneItem *j, *first;
+ bool tentative = true, need_soa = false;
int r;
assert(z);
- assert(q);
+ assert(key);
assert(ret_answer);
- assert(ret_soa);
- if (q->n_keys <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
+ /* First iteration, count what we have */
- return 0;
- }
+ if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+ bool found = false, added = false;
+ int k;
- /* First iteration, count what we have */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
+ /* If this is a generic match, then we have to
+ * go through the list by the name and look
+ * for everything manually */
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->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;
- /* If this is a generic match, then we have to
- * go through the list by the name and look
- * for everything manually */
+ found = true;
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
+ k = dns_resource_key_match_rr(key, j->rr, NULL);
+ if (k < 0)
+ return k;
+ if (k > 0) {
+ n_answer++;
+ added = true;
+ }
- found = true;
+ }
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- n_answer++;
- added = true;
- }
+ if (found && !added)
+ need_soa = true;
- }
+ } else {
+ bool found = false;
- if (found && !added)
- n_soa++;
+ /* If this is a specific match, then look for
+ * the right key immediately */
- } 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;
- /* If this is a specific match, then look for
- * the right key immediately */
+ found = true;
+ n_answer++;
+ }
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
+ 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;
- found = true;
- n_answer++;
- }
-
- if (!found) {
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- n_soa++;
- break;
- }
+ need_soa = true;
+ break;
}
}
}
- if (n_answer <= 0 && n_soa <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
-
- return 0;
- }
+ if (n_answer <= 0 && !need_soa)
+ goto return_empty;
if (n_answer > 0) {
answer = dns_answer_new(n_answer);
return -ENOMEM;
}
- if (n_soa > 0) {
- soa = dns_answer_new(n_soa);
+ if (need_soa) {
+ soa = dns_answer_new(1);
if (!soa)
return -ENOMEM;
}
/* Second iteration, actually add the RRs to the answers */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
-
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- bool found = false, added = false;
- int k;
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- 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 (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+ bool found = false, added = false;
+ int k;
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = 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;
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- r = dns_answer_add(answer, j->rr, 0);
- if (r < 0)
- return r;
+ found = true;
- added = true;
- }
- }
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
- if (found && !added) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+ 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;
}
- } else {
- bool found = false;
+ }
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
+ 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;
- found = true;
+ 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;
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
+ found = true;
- r = dns_answer_add(answer, j->rr, 0);
- if (r < 0)
- return r;
- }
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
- if (!found) {
- bool add_soa = false;
+ r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED);
+ if (r < 0)
+ return r;
+ }
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- 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 (!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;
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
- add_soa = true;
- }
+ add_soa = true;
+ }
- if (add_soa) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
- if (r < 0)
- return r;
- }
+ 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;
- *ret_soa = soa;
- soa = 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) {
- _cleanup_free_ char *pretty = NULL;
-
assert(i);
if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED))
return;
- dns_resource_record_to_string(i->rr, &pretty);
- log_info("Detected conflict on %s", strna(pretty));
+ log_info("Detected conflict on %s", strna(dns_resource_record_to_string(i->rr)));
dns_zone_item_probe_stop(i);
manager_next_hostname(i->scope->manager);
}
-void dns_zone_item_ready(DnsZoneItem *i) {
- _cleanup_free_ char *pretty = NULL;
-
+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))
+ 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) {
log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost.");
}
- dns_resource_record_to_string(i->rr, &pretty);
- log_debug("Record %s successfully probed.", strna(pretty));
+ 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) {
- _cleanup_free_ char *pretty = NULL;
int r;
assert(i);
if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
return 0;
- dns_resource_record_to_string(i->rr, &pretty);
- log_debug("Verifying RR %s", strna(pretty));
+ 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);
void dns_zone_dump(DnsZone *zone, FILE *f) {
Iterator iterator;
DnsZoneItem *i;
- int r;
if (!zone)
return;
DnsZoneItem *j;
LIST_FOREACH(by_key, j, i) {
- _cleanup_free_ char *t = NULL;
+ const char *t;
- r = dns_resource_record_to_string(j->rr, &t);
- if (r < 0) {
+ t = dns_resource_record_to_string(j->rr);
+ if (!t) {
log_oom();
continue;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct DnsZoneItem DnsZoneItem;
typedef enum DnsZoneItemState DnsZoneItemState;
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
#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 */
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, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
+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_ready(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);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
%struct-type
%includes
%%
-Resolve.DNS, config_parse_dnsv, DNS_SERVER_SYSTEM, 0
-Resolve.FallbackDNS, config_parse_dnsv, DNS_SERVER_FALLBACK, 0
-Resolve.LLMNR, config_parse_support, 0, offsetof(Manager, llmnr_support)
+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)
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
return -ENOMEM;
l->ifindex = ifindex;
- l->llmnr_support = SUPPORT_YES;
+ 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 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)
- link_address_free(l->addresses);
+ (void) link_address_free(l->addresses);
if (l->manager)
hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
- while (l->dns_servers) {
- DnsServer *s = l->dns_servers;
-
- LIST_REMOVE(servers, l->dns_servers, s);
- dns_server_unref(s);
- }
-
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;
}
-static void link_allocate_scopes(Link *l) {
+void link_allocate_scopes(Link *l) {
int r;
assert(l);
- if (l->dns_servers) {
+ 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)
} else
l->unicast_scope = dns_scope_free(l->unicast_scope);
- if (link_relevant(l, AF_INET) &&
- l->llmnr_support != SUPPORT_NO &&
- l->manager->llmnr_support != SUPPORT_NO) {
+ 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)
} else
l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
- if (link_relevant(l, AF_INET6) &&
- l->llmnr_support != SUPPORT_NO &&
- l->manager->llmnr_support != SUPPORT_NO &&
+ 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);
}
} 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) {
if (r < 0)
return r;
- sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
+ (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);
static int link_update_dns_servers(Link *l) {
_cleanup_strv_free_ char **nameservers = NULL;
char **nameserver;
- DnsServer *s, *nx;
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;
- LIST_FOREACH(servers, s, l->dns_servers)
- s->marked = true;
+ 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 = link_find_dns_server(l, family, &a);
+ s = dns_server_find(l->dns_servers, family, &a);
if (s)
- s->marked = false;
+ dns_server_move_back_and_unmark(s);
else {
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
if (r < 0)
}
}
- LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
- if (s->marked) {
- LIST_REMOVE(servers, l->dns_servers, s);
- dns_server_unref(s);
- }
-
+ dns_server_unlink_marked(l->dns_servers);
return 0;
clear:
- while (l->dns_servers) {
- s = l->dns_servers;
+ 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);
- LIST_REMOVE(servers, l->dns_servers, s);
- dns_server_unref(s);
+ 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_llmnr_support(Link *l) {
+static int link_update_mdns_support(Link *l) {
_cleanup_free_ char *b = NULL;
int r;
assert(l);
- r = sd_network_link_get_llmnr(l->ifindex, &b);
+ r = sd_network_link_get_mdns(l->ifindex, &b);
+ if (r == -ENODATA) {
+ r = 0;
+ goto clear;
+ }
if (r < 0)
goto clear;
- r = parse_boolean(b);
- if (r < 0) {
- if (streq(b, "resolve"))
- l->llmnr_support = SUPPORT_RESOLVE;
- else
- 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;
+}
- } else if (r > 0)
- l->llmnr_support = SUPPORT_YES;
- else
- l->llmnr_support = SUPPORT_NO;
+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->llmnr_support = SUPPORT_YES;
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
return r;
}
-static int link_update_domains(Link *l) {
+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;
- if (!l->unicast_scope)
- return 0;
+ 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;
+}
- l->unicast_scope->domains = strv_free(l->unicast_scope->domains);
+static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
+ DnsSearchDomain *d;
+ int r;
- r = sd_network_link_get_domains(l->ifindex,
- &l->unicast_scope->domains);
+ 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_update_dns_servers(l);
- link_update_llmnr_support(l);
+ link_read_settings(l);
link_allocate_scopes(l);
- link_update_domains(l);
link_add_rrs(l, false);
return 0;
}
-bool link_relevant(Link *l, int family) {
+bool link_relevant(Link *l, int family, bool local_multicast) {
_cleanup_free_ char *state = NULL;
LinkAddress *a;
assert(l);
- /* A link is relevant if it isn't a loopback or pointopoint
- * device, has a link beat, can do multicast and has at least
- * one relevant IP address */
+ /* 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_POINTOPOINT|IFF_DORMANT))
+ if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
return false;
- if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
+ if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
return false;
- sd_network_link_get_operational_state(l->ifindex, &state);
+ 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 (a->family == family && link_address_relevant(a))
+ if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
return true;
return false;
return NULL;
}
-DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr) {
- DnsServer *s;
-
- assert(l);
-
- LIST_FOREACH(servers, s, l->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr))
- return s;
- return NULL;
-}
-
DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
assert(l);
if (l->current_dns_server == s)
return s;
- if (s) {
- _cleanup_free_ char *ip = NULL;
-
- in_addr_to_string(s->family, &s->address, &ip);
- log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name);
- }
+ if (s)
+ log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
- l->current_dns_server = s;
+ 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);
if (!l->current_dns_server)
return;
- if (l->current_dns_server->servers_next) {
+ /* 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;
if (a->family == AF_INET) {
if (!force_remove &&
- link_address_relevant(a) &&
+ link_address_relevant(a, true) &&
a->link->llmnr_ipv4_scope &&
- a->link->llmnr_support == SUPPORT_YES &&
- a->link->manager->llmnr_support == SUPPORT_YES) {
+ 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->family == AF_INET6) {
if (!force_remove &&
- link_address_relevant(a) &&
+ link_address_relevant(a, true) &&
a->link->llmnr_ipv6_scope &&
- a->link->llmnr_support == SUPPORT_YES &&
- a->link->manager->llmnr_support == SUPPORT_YES) {
+ 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);
return 0;
}
-bool link_address_relevant(LinkAddress *a) {
+bool link_address_relevant(LinkAddress *a, bool local_multicast) {
assert(a);
if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
return false;
- if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
+ if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
return false;
return true;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#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;
LIST_HEAD(DnsServer, dns_servers);
DnsServer *current_dns_server;
+ unsigned n_dns_servers;
+
+ LIST_HEAD(DnsSearchDomain, search_domains);
+ unsigned n_search_domains;
- Support llmnr_support;
+ 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 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_find_dns_server(Link *l, int family, const union in_addr_union *in_addr);
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 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
assert(m);
- if (m->llmnr_support == SUPPORT_NO)
+ if (m->llmnr_support == RESOLVE_SUPPORT_NO)
return 0;
r = manager_llmnr_ipv4_udp_fd(m);
eaddrinuse:
log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
- m->llmnr_support = SUPPORT_NO;
+ m->llmnr_support = RESOLVE_SUPPORT_NO;
manager_llmnr_stop(m);
return 0;
dns_scope_process_query(scope, NULL, p);
} else
- log_debug("Invalid LLMNR UDP packet.");
+ log_debug("Invalid LLMNR UDP packet, ignoring.");
return 0;
}
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:
}
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) {
- r = -errno;
+ 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;
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:
}
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) {
- r = -errno;
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <netinet/in.h>
#include <poll.h>
-#include <resolv.h>
#include <sys/ioctl.h>
#include "af-list.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"
}
static int manager_rtnl_listen(Manager *m) {
- _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *i;
int r;
if (r < 0)
return r;
- r = sd_netlink_attach_event(m->rtnl, m->event, 0);
+ r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
if (r < 0)
return r;
r = manager_write_resolv_conf(m);
if (r < 0)
- log_warning_errno(r, "Could not update resolv.conf: %m");
+ log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
return 0;
}
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;
}
return -EINVAL;
}
- r = dns_label_escape(label, r, &n);
+ r = dns_label_escape_new(label, r, &n);
if (r < 0)
return log_error_errno(r, "Failed to escape host name: %m");
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_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 = SUPPORT_YES;
+ 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 = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
+ r = dns_trust_anchor_load(&m->trust_anchor);
+ if (r < 0)
+ return r;
+
+ r = manager_parse_config_file(m);
if (r < 0)
return r;
if (r < 0)
return r;
+ r = manager_mdns_start(m);
+ if (r < 0)
+ return r;
+
return 0;
}
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);
- manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
- manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
-
dns_scope_free(m->unicast_scope);
hashmap_free(m->links);
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);
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_read_resolv_conf(Manager *m) {
- _cleanup_fclose_ FILE *f = NULL;
- struct stat st, own;
- char line[LINE_MAX];
- DnsServer *s, *nx;
- 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)
- log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
- r = -errno;
- goto clear;
- }
-
- /* Have we already seen the file? */
- t = timespec_load(&st.st_mtim);
- if (t == m->resolv_conf_mtime)
- return 0;
-
- m->resolv_conf_mtime = t;
-
- /* 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) {
- r = 0;
- goto clear;
- }
-
- f = fopen("/etc/resolv.conf", "re");
- if (!f) {
- if (errno != ENOENT)
- log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
- r = -errno;
- goto clear;
- }
-
- if (fstat(fileno(f), &st) < 0) {
- r = log_error_errno(errno, "Failed to stat open file: %m");
- goto clear;
- }
-
- LIST_FOREACH(servers, s, m->dns_servers)
- s->marked = true;
-
- FOREACH_LINE(line, f, r = -errno; goto clear) {
- union in_addr_union address;
- int family;
- char *l;
- const char *a;
-
- truncate_nl(line);
-
- l = strstrip(line);
- if (*l == '#' || *l == ';')
- continue;
-
- a = first_word(l, "nameserver");
- if (!a)
- continue;
-
- r = in_addr_from_string_auto(a, &family, &address);
- if (r < 0) {
- log_warning("Failed to parse name server %s.", a);
- continue;
- }
-
- LIST_FOREACH(servers, s, m->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
- break;
-
- if (s)
- s->marked = false;
- else {
- r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
- if (r < 0)
- goto clear;
- }
- }
-
- LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
- if (s->marked) {
- LIST_REMOVE(servers, m->dns_servers, s);
- dns_server_unref(s);
- }
-
- /* 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);
-
- return 0;
-
-clear:
- while (m->dns_servers) {
- s = m->dns_servers;
-
- LIST_REMOVE(servers, m->dns_servers, s);
- dns_server_unref(s);
- }
-
- return r;
-}
-
-static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(s);
- assert(f);
- assert(count);
-
- r = in_addr_to_string(s->family, &s->address, &t);
- if (r < 0) {
- log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
- return;
- }
-
- if (*count == MAXNS)
- fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
-
- fprintf(f, "nameserver %s\n", t);
- (*count) ++;
-}
-
-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;
- }
-
- fprintf(f, " %s", domain);
-
- (*length) += strlen(domain);
- (*count) ++;
-}
-
-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 {
- DnsServer *s;
- unsigned count = 0;
-
- 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) {
- static const char path[] = "/run/systemd/resolve/resolv.conf";
- _cleanup_free_ char *temp_path = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
- DnsServer *s;
- Iterator i;
- Link *l;
- 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 */
- dns = ordered_set_new(&dns_server_hash_ops);
- if (!dns)
- return -ENOMEM;
-
- domains = ordered_set_new(&dns_name_hash_ops);
- if (!domains)
- return -ENOMEM;
-
- /* First add the system-wide servers */
- 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 and domains */
- HASHMAP_FOREACH(l, m->links, i) {
- char **domain;
-
- LIST_FOREACH(servers, s, l->dns_servers) {
- r = ordered_set_put(dns, s);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
-
- if (!l->unicast_scope)
- continue;
-
- STRV_FOREACH(domain, l->unicast_scope->domains) {
- r = ordered_set_put(domains, *domain);
- 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;
- }
- }
-
- r = fopen_temporary_label(path, path, &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, path) < 0) {
- r = -errno;
- goto fail;
- }
-
- return 0;
-
-fail:
- (void) unlink(path);
- (void) unlink(temp_path);
- return r;
-}
-
int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
union {
int manager_write(Manager *m, int fd, DnsPacket *p) {
int r;
- log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
+ 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)
assert(port > 0);
assert(p);
- log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
+ 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);
return -EAFNOSUPPORT;
}
-DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
- DnsServer *s;
-
- assert(m);
- assert(in_addr);
-
- LIST_FOREACH(servers, s, m->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
- return s;
-
- LIST_FOREACH(servers, s, m->fallback_dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
- return s;
-
- return NULL;
-}
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
- assert(m);
-
- if (m->current_dns_server == s)
- return s;
-
- if (s) {
- _cleanup_free_ char *ip = NULL;
-
- in_addr_to_string(s->family, &s->address, &ip);
- log_info("Switching to system DNS server %s.", strna(ip));
- }
-
- m->current_dns_server = 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 (!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 */
- if (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);
-}
-
uint32_t manager_find_mtu(Manager *m) {
uint32_t mtu = 0;
Link *l;
if (!l)
return NULL;
- if (p->protocol == DNS_PROTOCOL_LLMNR) {
+ 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;
dns_zone_verify_all(&s->zone);
}
-void manager_flush_dns_servers(Manager *m, DnsServerType t) {
+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);
- if (t == DNS_SERVER_SYSTEM)
- while (m->dns_servers) {
- s = m->dns_servers;
+ r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
+ if (r < 0)
+ return r;
- LIST_REMOVE(servers, m->dns_servers, s);
- dns_server_unref(s);
- }
+ /* 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;
+ }
- if (t == DNS_SERVER_FALLBACK)
- while (m->fallback_dns_servers) {
- s = m->fallback_dns_servers;
+ /* 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;
+ }
+ }
- LIST_REMOVE(servers, m->fallback_dns_servers, s);
- dns_server_unref(s);
+ /* 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_is_own_hostname(Manager *m, const char *name) {
+int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
+ DnsSearchDomain *d;
+ Iterator i;
+ Link *l;
int r;
assert(m);
- assert(name);
+ assert(domains);
- if (m->llmnr_hostname) {
- r = dns_name_equal(name, m->llmnr_hostname);
- if (r != 0)
+ 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;
}
- if (m->mdns_hostname)
- return dns_name_equal(name, m->mdns_hostname);
+ 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;
}
-static const char* const support_table[_SUPPORT_MAX] = {
- [SUPPORT_NO] = "no",
- [SUPPORT_YES] = "yes",
- [SUPPORT_RESOLVE] = "resolve",
-};
-DEFINE_STRING_TABLE_LOOKUP(support, Support);
+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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "sd-network.h"
#include "sd-netlink.h"
-#include "list.h"
+#include "sd-network.h"
+
#include "hashmap.h"
+#include "list.h"
+#include "ordered-set.h"
+#include "resolve-util.h"
typedef struct Manager Manager;
-typedef enum Support Support;
-
-enum Support {
- SUPPORT_NO,
- SUPPORT_YES,
- SUPPORT_RESOLVE,
- _SUPPORT_MAX,
- _SUPPORT_INVALID = -1
-};
#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;
- Support llmnr_support;
+ ResolveSupport llmnr_support;
+ ResolveSupport mdns_support;
+ DnssecMode dnssec_mode;
/* Network */
Hashmap *links;
/* 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;
- bool read_resolv_conf;
+ 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;
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;
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 */
Manager* manager_free(Manager *m);
int manager_start(Manager *m);
-int manager_read_resolv_conf(Manager *m);
-int manager_write_resolv_conf(Manager *m);
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
-DnsServer *manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr);
-DnsServer *manager_get_dns_server(Manager *m);
-void manager_next_dns_server(Manager *m);
uint32_t manager_find_mtu(Manager *m);
void manager_verify_all(Manager *m);
-void manager_flush_dns_servers(Manager *m, DnsServerType t);
-
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
#define EXTRA_CMSG_SPACE 1024
int manager_is_own_hostname(Manager *m, const char *name);
-const char* support_to_string(Support p) _const_;
-int support_from_string(const char *s) _pure_;
+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);
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <resolv.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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;
+}
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
--- /dev/null
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <resolv.h>
+
+#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;
+}
--- /dev/null
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
goto finish;
}
- r = manager_parse_config_file(m);
- if (r < 0)
- log_warning_errno(r, "Failed to parse configuration file: %m");
-
r = manager_start(m);
if (r < 0) {
log_error_errno(r, "Failed to start manager: %m");
* symlink */
r = manager_write_resolv_conf(m);
if (r < 0)
- log_warning_errno(r, "Could not create resolv.conf: %m");
+ log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m");
sd_notify(false,
"READY=1\n"
[Resolve]
#DNS=
#FallbackDNS=@DNS_SERVERS@
+#Domains=
#LLMNR=yes
+#DNSSEC=no
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ip.h>
+
+#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;
+}
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#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;
+}
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include "dns-type.h"
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table_sparse(dns_type, DNS_TYPE);
+
+ return EXIT_SUCCESS;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-util.h"
#include "calendarspec.h"
#include "env-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "parse-util.h"
return r;
STRV_FOREACH(i, properties) {
- r = sd_bus_message_open_container(m, 'r', "sv");
- if (r < 0)
- return r;
-
r = bus_append_unit_property_assignment(m, *i);
if (r < 0)
return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
}
return 0;
sd_bus *bus,
char **argv) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
return log_error_errno(errno, "Failed to unlock tty: %m");
} else if (arg_transport == BUS_TRANSPORT_MACHINE) {
- _cleanup_bus_unref_ sd_bus *system_bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
const char *s;
r = sd_bus_default_system(&system_bus);
if (master >= 0) {
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
char last_char = 0;
r = sd_event_default(&event);
sd_bus *bus,
char **argv) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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;
sd_bus *bus,
char **argv) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _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 main(int argc, char* argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *description = NULL, *command = NULL;
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
int calc_acl_mask_if_needed(acl_t *acl_p) {
acl_entry_t i;
int r;
+ bool need = false;
assert(acl_p);
if (tag == ACL_MASK)
return 0;
- if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
- if (acl_calc_mask(acl_p) < 0)
- return -errno;
-
- return 1;
- }
+ if (IN_SET(tag, ACL_USER, ACL_GROUP))
+ need = true;
}
if (r < 0)
return -errno;
- return 0;
+ 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) {
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);
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#ifdef HAVE_ACL
+#include <acl/libacl.h>
#include <stdbool.h>
#include <sys/acl.h>
-#include <acl/libacl.h>
#include "macro.h"
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. */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <fcntl.h>
+#include <stddef.h>
#include <stdint.h>
-#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "fd-util.h"
#include "fileio.h"
#include "time-util.h"
-#include "util.h"
struct acpi_table_header {
char signature[4];
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
+
#include "alloc-util.h"
#include "apparmor-util.h"
#include "fileio.h"
#include "parse-util.h"
-#include "util.h"
bool mac_apparmor_use(void) {
static int cached_use = -1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <sys/utsname.h>
#include "architecture.h"
+#include "macro.h"
#include "string-table.h"
#include "string-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <endian.h>
+#include "macro.h"
#include "util.h"
/* A cleaned up architecture definition. We don't want to get lost in
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
#include <poll.h>
+#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <termios.h>
#include <unistd.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 "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)
serial = request_key("user", keyname, NULL, 0);
if (serial == -1)
- return -errno;
+ return negative_errno();
*ret = serial;
return 0;
char **ret) {
struct termios old_termios, new_termios;
- char passphrase[LINE_MAX], *x;
- size_t p = 0;
+ 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];
passphrase[p++] = c;
- if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0)
- loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false);
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <sys/stat.h>
+#include <syslog.h>
#include <unistd.h>
#include "alloc-util.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
#include <sys/socket.h>
+#include <unistd.h>
+#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-error.h"
#include "bus-internal.h"
#include "bus-label.h"
#include "bus-message.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 "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"
}
int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
int r, has_owner = 0;
assert(c);
}
static int check_good_user(sd_bus_message *m, uid_t good_user) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t sender_uid;
int r;
return 1;
#ifdef ENABLE_POLKIT
else {
- _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
AsyncPolkitQuery *q = userdata;
int r;
sd_bus_error *error) {
#ifdef ENABLE_POLKIT
- _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
AsyncPolkitQuery *q;
const char *sender, **k, **v;
sd_bus_message_handler_t callback;
}
int bus_connect_system_systemd(sd_bus **_bus) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
assert(_bus);
}
int bus_connect_user_systemd(sd_bus **_bus) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *ee = NULL;
const char *e;
int r;
}
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
const struct bus_properties_map *map,
void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
const struct bus_properties_map *map,
void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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);
int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
const char *eq, *field;
- int r;
+ int r, rl;
assert(m);
assert(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_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
-
- } else if (endswith(eq, "%")) {
+ 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) {
return -EINVAL;
}
- r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
+ 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;
}
- if (r < 0)
- return bus_log_create_error(r);
+ goto finish;
- return 0;
} else if (streq(field, "EnvironmentFile")) {
- r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "v", "a(sb)", 1,
+ 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 r;
- return 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);
- if (STR_IN_SET(field,
+ 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")) {
+ "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
r = parse_boolean(eq);
- if (r < 0) {
- log_error("Failed to parse boolean assignment %s.", assignment);
- return -EINVAL;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
r = sd_bus_message_append(m, "v", "b", r);
r = sd_bus_message_append(m, "v", "a(st)", path, u);
}
- } else if (rlimit_from_string(field) >= 0) {
- uint64_t rl;
-
- if (streq(eq, "infinity"))
- rl = (uint64_t) -1;
- else {
- r = safe_atou64(eq, &rl);
- if (r < 0) {
- log_error("Invalid resource limit: %s", eq);
- return -EINVAL;
- }
- }
-
- r = sd_bus_message_append(m, "v", "t", rl);
-
} else if (streq(field, "Nice")) {
int32_t i;
r = sd_bus_message_append(m, "v", "i", sig);
- } else if (streq(field, "AccuracySec")) {
- usec_t u;
-
- r = parse_sec(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 (streq(field, "TimerSlackNSec")) {
nsec_t n;
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);
{ "start-limit", "start of the service was attempted too often" }
};
-static void log_job_error_with_service_result(const char* service, const char *result) {
- _cleanup_free_ char *service_shell_quoted = NULL;
+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;
break;
if (i < ELEMENTSOF(explanations)) {
- log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+ 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 \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+ 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 \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
+ 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) {
+static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) {
int r = 0;
assert(d->result);
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("Job for %s invalid.", strna(d->name));
+ 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"))
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);
+ log_job_error_with_service_result(d->name, result, extra_args);
} else
log_error("Job failed. See \"journalctl -xe\" for details.");
}
return r;
}
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
+int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) {
int r = 0;
assert(d);
return log_error_errno(q, "Failed to wait for response: %m");
if (d->result) {
- q = check_wait_response(d, quiet);
+ 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)
if (r < 0)
return log_oom();
- return bus_wait_for_jobs(d, quiet);
+ 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) {
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 = rl->rlim_max;
+ 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(property, "Limit"));
+ z = rlimit_from_string(strstr(s, "Limit"));
assert(z >= 0);
getrlimit(z, &buf);
- x = buf.rlim_max;
+ x = is_soft ? buf.rlim_cur : buf.rlim_max;
}
/* rlim_t might have different sizes, let's map
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#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"
int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_flush_close_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref);
-
-#define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
-#define _cleanup_bus_flush_close_unref_ _cleanup_(sd_bus_flush_close_unrefp)
-#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp)
-#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
-#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
-#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp)
-#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
-
#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
int function(sd_bus *bus, \
const char *path, \
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);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <dirent.h>
#include <errno.h>
+#include <stddef.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "alloc-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"
-#include "util.h"
static int compare(const void *a, const void *b) {
const pid_t *p = a, *q = b;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include <stdbool.h>
#include <sys/types.h>
+
#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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <mqueue.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
+#include <unistd.h>
#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"
-#include "util.h"
static int clean_sysvipc_shm(uid_t delete_uid) {
_cleanup_fclose_ FILE *f = NULL;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <fcntl.h>
#include <fnmatch.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
#include <unistd.h>
#include "sd-id128.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"
assert(c->type == CONDITION_SECURITY);
if (streq(c->parameter, "selinux"))
- return mac_selinux_use();
+ return mac_selinux_have();
if (streq(c->parameter, "smack"))
return mac_smack_use();
if (streq(c->parameter, "apparmor"))
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
***/
#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include "sd-messages.h"
+#include <sys/types.h>
#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 "string-util.h"
#include "strv.h"
#include "syslog-util.h"
+#include "time-util.h"
#include "utf8.h"
-#include "util.h"
int config_item_table_lookup(
const void *table,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
+#include <errno.h>
#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <syslog.h>
+#include "alloc-util.h"
+#include "log.h"
#include "macro.h"
/* An abstract parser for simple, line based, shallow configuration
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <stringprep.h>
#endif
+#include <endian.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+
#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;
assert(name);
assert(*name);
- assert(dest);
n = *name;
d = dest;
if (*n == 0)
break;
- if (sz <= 0)
- return -ENOSPC;
-
if (r >= DNS_LABEL_MAX)
return -EINVAL;
+ if (sz <= 0)
+ return -ENOBUFS;
+
if (*n == '\\') {
/* Escaped character */
else if (*n == '\\' || *n == '.') {
/* Escaped backslash or dot */
- *(d++) = *(n++);
+
+ if (d)
+ *(d++) = *n;
sz--;
r++;
+ n++;
} else if (n[0] >= '0' && n[0] <= '9') {
unsigned k;
((unsigned) (n[1] - '0') * 10) +
((unsigned) (n[2] - '0'));
- /* Don't allow CC characters or anything that doesn't fit in 8bit */
- if (k < ' ' || k > 255 || k == 127)
+ /* 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;
- *(d++) = (char) k;
+ if (d)
+ *(d++) = (char) k;
sz--;
r++;
} else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
/* Normal character */
- *(d++) = *(n++);
+
+ if (d)
+ *(d++) = *n;
sz--;
r++;
+ n++;
} else
return -EINVAL;
}
if (r == 0 && *n)
return -EINVAL;
- if (sz >= 1)
+ if (sz >= 1 && d)
*d = 0;
*name = n;
return 0;
}
- assert(**label_terminal == '.' || **label_terminal == 0);
+ terminal = *label_terminal;
+ assert(*terminal == '.' || *terminal == 0);
- /* skip current terminal character */
- terminal = *label_terminal - 1;
+ /* 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) */
+ /* 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 */
+ /* Reached the first label, so indicate that there are no more */
terminal = NULL;
break;
}
- /* find the start of the last label */
+ /* Find the start of the last label */
if (*terminal == '.') {
const char *y;
unsigned slashes = 0;
slashes ++;
if (slashes % 2 == 0) {
- /* the '.' was not escaped */
+ /* The '.' was not escaped */
name = terminal + 1;
break;
} else {
return r;
}
-int dns_label_escape(const char *p, size_t l, char **ret) {
- _cleanup_free_ char *s = NULL;
+int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
char *q;
- int r;
- assert(p);
- assert(ret);
+ /* DNS labels must be between 1 and 63 characters long. A
+ * zero-length label does not exist. See RFC 2182, Section
+ * 11. */
- if (l > DNS_LABEL_MAX)
+ if (l <= 0 || l > DNS_LABEL_MAX)
return -EINVAL;
+ if (sz < 1)
+ return -ENOBUFS;
- s = malloc(l * 4 + 1);
- if (!s)
- return -ENOMEM;
+ assert(p);
+ assert(dest);
- q = s;
+ 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')) {
/* Proper character */
+
+ if (sz < 2)
+ return -ENOBUFS;
+
*(q++) = *p;
- } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
+ 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);
- } else
- return -EINVAL;
+ 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;
- r = q - 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;
+ size_t input_size, l;
const char *p;
bool contains_8bit = false;
+ char buffer[DNS_LABEL_MAX+1];
assert(encoded);
assert(decoded);
- assert(decoded_max >= DNS_LABEL_MAX);
+
+ /* Converts an U-label into an A-label */
if (encoded_size <= 0)
- return 0;
+ return -EINVAL;
for (p = encoded; p < encoded + encoded_size; p++)
if ((uint8_t) *p > 127)
contains_8bit = true;
- if (!contains_8bit)
+ 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, decoded, 0) != 0)
+ 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;
- return strlen(decoded);
+ 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
uint32_t *output = NULL;
size_t w;
- /* To be invoked after unescaping */
+ /* 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 (!result)
return -ENOMEM;
if (w <= 0)
- return 0;
- if (w+1 > decoded_max)
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;
- memcpy(decoded, result, w+1);
return w;
#else
return 0;
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 = a;
+ const char *p;
bool first = true;
int r;
- assert(a);
+ if (a)
+ p = a;
+ else if (b) {
+ p = b;
+ b = NULL;
+ } else
+ goto finish;
for (;;) {
- _cleanup_free_ char *t = NULL;
char label[DNS_LABEL_MAX];
- int k;
r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0)
break;
}
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
-
- r = dns_label_escape(label, r, &t);
- if (r < 0)
- return r;
-
if (_ret) {
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
+ 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
- first = false;
+ ret[n] = '.';
+ } else {
+ char escaped[DNS_LABEL_ESCAPED_MAX];
- memcpy(ret + n, t, r);
+ r = dns_label_escape(label, r, escaped, sizeof(escaped));
+ if (r < 0)
+ return r;
}
+ if (!first)
+ n++;
+ else
+ first = false;
+
n += r;
}
- if (n > DNS_NAME_MAX)
+finish:
+ if (n > DNS_HOSTNAME_MAX)
return -EINVAL;
if (_ret) {
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
- return -ENOMEM;
+ 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;
assert(p);
- while (*p) {
+ for (;;) {
char label[DNS_LABEL_MAX+1];
- int k;
r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0)
break;
-
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0)
- break;
- if (k > 0)
- r = k;
-
if (r == 0)
break;
- label[r] = 0;
- ascii_strlower(label);
-
- string_hash_func(label, state);
+ 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 */
int dns_name_compare_func(const void *a, const void *b) {
const char *x, *y;
- int r, q, k, w;
+ int r, q;
assert(a);
assert(b);
y = (const char *) b + strlen(b);
for (;;) {
- char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
+ char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
if (x == NULL && y == NULL)
return 0;
if (r < 0 || q < 0)
return r - q;
- k = dns_label_undo_idna(la, r, la, sizeof(la));
- w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
- if (k < 0 || w < 0)
- return k - w;
- if (k > 0)
- r = k;
- if (w > 0)
- r = w;
-
- la[r] = lb[q] = 0;
- r = strcasecmp(la, lb);
+ r = ascii_strcasecmp_nn(la, r, lb, q);
if (r != 0)
return r;
}
};
int dns_name_equal(const char *x, const char *y) {
- int r, q, k, w;
+ int r, q;
assert(x);
assert(y);
for (;;) {
- char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
-
- if (*x == 0 && *y == 0)
- return true;
+ char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
r = dns_label_unescape(&x, la, sizeof(la));
if (r < 0)
return r;
- k = dns_label_undo_idna(la, r, la, sizeof(la));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
-
q = dns_label_unescape(&y, lb, sizeof(lb));
if (q < 0)
return q;
- w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
- if (w < 0)
- return w;
- if (w > 0)
- q = w;
-
- la[r] = lb[q] = 0;
- if (strcasecmp(la, lb))
+
+ 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, k, w;
+ int r, q;
assert(name);
assert(suffix);
s = suffix;
for (;;) {
- char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+ char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
r = dns_label_unescape(&n, ln, sizeof(ln));
if (r < 0)
return r;
- k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
if (!saved_n)
saved_n = n;
q = dns_label_unescape(&s, ls, sizeof(ls));
if (q < 0)
return q;
- w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
- if (w < 0)
- return w;
- if (w > 0)
- q = w;
if (r == 0 && q == 0)
return true;
if (r == 0 && saved_n == n)
return false;
- ln[r] = ls[q] = 0;
-
- if (r != q || strcasecmp(ln, ls)) {
+ 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;
}
}
+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;
return 0;
}
-int dns_name_root(const char *name) {
- char label[DNS_LABEL_MAX+1];
- int r;
+bool dns_name_is_root(const char *name) {
assert(name);
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- return r;
+ /* There are exactly two ways to encode the root domain name:
+ * as empty string, or with a single dot. */
- return r == 0 && *name == 0;
+ return STR_IN_SET(name, "", ".");
}
-int dns_name_single_label(const char *name) {
- char label[DNS_LABEL_MAX+1];
+bool dns_name_is_single_label(const char *name) {
int r;
assert(name);
- r = dns_label_unescape(&name, label, sizeof(label));
+ 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;
- if (r == 0)
- return 0;
- r = dns_label_unescape(&name, label, sizeof(label));
+ 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> . <type> . <type2> . <domain> */
+
+ 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 <type> . <type2> . <domain> */
+
+ 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;
- return r == 0 && *name == 0;
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#pragma once
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
#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
-#define DNS_NAME_MAX 255
+
+/* 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 **ret);
+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_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);
-int dns_name_root(const char *name);
-int dns_name_single_label(const char *name);
+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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#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 "util.h"
+#include "unit-name.h"
int drop_in_file(const char *dir, const char *unit, unsigned level,
const char *name, char **_p, char **_q) {
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return log_error_errno(errno, "Failed to read directory %s: %m", path);
if (!de)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "hashmap.h"
#include "macro.h"
#include "set.h"
#include "unit-name.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <unistd.h>
+#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
#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)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
#include <arpa/inet.h>
+#include <endian.h>
+#include <errno.h>
#include <net/if.h>
-#include <sys/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/socket.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter/xt_addrtype.h>
#include "alloc-util.h"
#include "firewall-util.h"
-#include "util.h"
+#include "in-addr-util.h"
+#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+#include <stdint.h>
+
#include "in-addr-util.h"
#ifdef HAVE_LIBIPTC
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <unistd.h>
#include "alloc-util.h"
#include "fileio.h"
#include "fstab-util.h"
#include "generator.h"
+#include "log.h"
+#include "macro.h"
#include "mkdir.h"
-#include "mount-util.h"
#include "path-util.h"
#include "special.h"
#include "string-util.h"
+#include "time-util.h"
#include "unit-name.h"
#include "util.h"
return write_drop_in_format(dir, unit, 50, "device-timeout",
"# Automatically generated by %s\n\n"
- "[Unit]\nJobTimeoutSec=" USEC_FMT,
- program_invocation_short_name,
- u / USEC_PER_SEC);
+ "[Unit]\nJobTimeoutSec=%s",
+ program_invocation_short_name, timeout);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "sd-id128.h"
-/* We only support root disk discovery for x86, x86-64 and ARM for
+/* 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_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_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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <string.h>
+
#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"
return 0;
}
-bool dkr_digest_is_valid(const char *digest) {
- /* 7 chars for prefix, 64 chars for the digest itself */
- if (strlen(digest) != 71)
- return false;
-
- return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef");
-}
-
-bool dkr_ref_is_valid(const char *ref) {
- const char *colon;
-
- if (isempty(ref))
- return false;
-
- colon = strchr(ref, ':');
- if (!colon)
- return filename_is_valid(ref);
-
- return dkr_digest_is_valid(ref);
-}
-
-bool dkr_name_is_valid(const char *name) {
- const char *slash, *p;
-
- if (isempty(name))
- return false;
-
- slash = strchr(name, '/');
- if (!slash)
- return false;
-
- if (!filename_is_valid(slash + 1))
- return false;
-
- p = strndupa(name, slash - name);
- if (!filename_is_valid(p))
- return false;
-
- return true;
-}
-
-bool dkr_id_is_valid(const char *id) {
-
- if (!filename_is_valid(id))
- return false;
-
- if (!in_charset(id, "0123456789abcdef"))
- return false;
-
- return true;
-}
-
int import_assign_pool_quota_and_warn(const char *path) {
int r;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
int tar_strip_suffixes(const char *name, char **ret);
int raw_strip_suffixes(const char *name, char **ret);
-bool dkr_name_is_valid(const char *name);
-bool dkr_id_is_valid(const char *id);
-bool dkr_ref_is_valid(const char *ref);
-bool dkr_digest_is_valid(const char *digest);
-#define dkr_tag_is_valid(tag) filename_is_valid(tag)
-
int import_assign_pool_quota_and_warn(const char *path);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
-#include "alloc-util.h"
#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"
-#include "util.h"
static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
UnitFileInstallInfo *i = userdata;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <unistd.h>
#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 "string-util.h"
#include "strv.h"
#include "unit-name.h"
-#include "util.h"
#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
typedef struct UnitFileList UnitFileList;
typedef struct UnitFileInstallInfo UnitFileInstallInfo;
+#include <stdbool.h>
+
#include "hashmap.h"
+#include "macro.h"
#include "path-lookup.h"
#include "strv.h"
#include "unit-name.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
+#include <syslog.h>
#include <time.h>
+#include <unistd.h>
+
+#include "sd-id128.h"
+#include "sd-journal.h"
#include "alloc-util.h"
#include "fd-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"
static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
size_t fl, nl;
- void *buf;
+ char *buf;
assert(data);
assert(field);
assert(target);
- assert(target_size);
fl = strlen(field);
if (length < fl)
return 0;
nl = length - fl;
- buf = malloc(nl+1);
+ buf = new(char, nl+1);
if (!buf)
return log_oom();
memcpy(buf, (const char*) data + fl, nl);
- ((char*)buf)[nl] = 0;
+ buf[nl] = 0;
free(*target);
*target = buf;
- *target_size = nl;
+
+ if (target_size)
+ *target_size = nl;
return 1;
}
const void *data;
size_t length;
_cleanup_free_ char *cursor = NULL;
- uint64_t realtime;
+ uint64_t realtime = 0;
char ts[FORMAT_TIMESTAMP_MAX + 7];
int r;
return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m");
else {
_cleanup_free_ char *value = NULL;
- size_t size;
- r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
+ r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, NULL);
if (r < 0)
- log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
- else {
- r = safe_atou64(value, &realtime);
- if (r < 0)
- log_debug_errno(r, "Failed to parse realtime timestamp: %m");
- }
+ 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) {
bool system_unit,
bool *ellipsized) {
- _cleanup_journal_close_ sd_journal*j = NULL;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert(mode >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
#include <sys/types.h>
#include "sd-journal.h"
-#include "util.h"
+#include "macro.h"
#include "output-mode.h"
+#include "time-util.h"
+#include "util.h"
int output_journal(
FILE *f,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <linux/fs.h>
-#include <sys/statfs.h>
-
#include "alloc-util.h"
#include "btrfs-util.h"
#include "chattr-util.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 "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[] =
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "time-util.h"
-#include "lockfile-util.h"
+#include <stdbool.h>
+#include <stdint.h>
+
#include "hashmap.h"
+#include "lockfile-util.h"
+#include "macro.h"
+#include "time-util.h"
typedef enum ImageType {
IMAGE_DIRECTORY,
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/loop.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
#include <sys/statvfs.h>
-#include <sys/vfs.h>
+#include <unistd.h>
+
+#include "sd-bus-protocol.h"
+#include "sd-bus.h"
#include "alloc-util.h"
#include "btrfs-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 "signal-util.h"
#include "stat-util.h"
#include "string-util.h"
-#include "util.h"
#define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL)
#define VAR_LIB_MACHINES_FREE_MIN (1024UL*1024UL*750UL)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdint.h>
+
#include "sd-bus.h"
/* Grow the /var/lib/machines directory after each 10MiB written */
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <nss.h>
-#include <netdb.h>
-#include <resolv.h>
-#include <pwd.h>
-#include <grp.h>
-
-
-#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_
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#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"
-#include "util.h"
static pid_t pager_pid = 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
#include "macro.h"
typedef struct LookupPaths {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <limits.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
#include <termios.h>
+#include <unistd.h>
+
+#include "sd-event.h"
#include "alloc-util.h"
#include "fd-util.h"
+#include "log.h"
+#include "macro.h"
#include "ptyfwd.h"
-#include "util.h"
+#include "time-util.h"
struct PTYForward {
sd_event *event;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#include "sd-event.h"
+#include "macro.h"
+
typedef struct PTYForward PTYForward;
typedef enum PTYForwardFlags {
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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);
--- /dev/null
+#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 <http://www.gnu.org/licenses/>.
+***/
+
+#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_;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <seccomp.h>
+#include <stddef.h>
+#include "macro.h"
#include "seccomp-util.h"
#include "string-util.h"
-#include "util.h"
const char* seccomp_arch_to_string(uint32_t c) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include <seccomp.h>
+#include <stdint.h>
const char* seccomp_arch_to_string(uint32_t c);
int seccomp_arch_from_string(const char *n, uint32_t *ret);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "conf-parser.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"
-#include "util.h"
#define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
+#include "sd-id128.h"
+
#include "alloc-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "specifier.h"
#include "string-util.h"
-#include "util.h"
/*
* Generic infrastructure for replacing %x style specifiers in
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdbool.h>
-#include <string.h>
+#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <unistd.h>
#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"
char new_mount[PATH_MAX];
struct stat sb;
- snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
+ xsprintf(new_mount, "%s%s", new_root, i);
mkdir_p_label(new_mount, 0755);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
+#include <stdbool.h>
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdbool.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include "fileio.h"
#include "log.h"
+#include "macro.h"
#include "string-util.h"
#include "sysctl-util.h"
-#include "util.h"
char *sysctl_normalize(char *s) {
char *n;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
reverse_t reverse,
int size,
bool sparse) {
- int i;
+ int i, boring = 0;
for (i = -1; i < size + 1; i++) {
const char* val = lookup(i);
int rev;
- if (val)
+ if (val) {
rev = reverse(val);
- else
+ 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), "");
- printf("%s: %d → %s → %d\n", name, i, val, rev);
assert_se(!(i >= 0 && i < size ?
sparse ? rev != i && rev != -1 : val == NULL || rev != i :
val != NULL || rev != -1));
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macro.h"
#include "uid-range.h"
#include "user-util.h"
-#include "util.h"
static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) {
assert(range);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/time.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <utmpx.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) {
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "time-util.h"
#include "util.h"
#ifdef HAVE_UTMP
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
+#include <syslog.h>
#include <unistd.h>
#include <linux/watchdog.h>
#include "fd-util.h"
#include "log.h"
+#include "time-util.h"
#include "watchdog.h"
static int watchdog_fd = -1;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
+#include "time-util.h"
#include "util.h"
int watchdog_set_timeout(usec_t *usec);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
if (errno != -EAGAIN)
log_warning_errno(errno, "Failed to accept() socket: %m");
} else {
- getpeername_pretty(nfd, &peer);
+ getpeername_pretty(nfd, true, &peer);
log_debug("New connection from %s", strna(peer));
r = add_connection_socket(context, nfd);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
arg_all * OUTPUT_SHOW_ALL |
arg_full * OUTPUT_FULL_WIDTH |
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
+ colors_enabled() * OUTPUT_COLOR |
!arg_quiet * OUTPUT_WARN_CUTOFF;
}
int c,
sd_bus_message **_reply) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
return log_error_errno(r, "Failed to get machine names: %m");
STRV_FOREACH(i, machines) {
- _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
int k;
r = sd_bus_open_system_machine(&container, *i);
const char* path,
char*** ret) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
const char* unit_path,
char*** listening) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
const char *path,
dual_timestamp *next) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
dual_timestamp t;
int r;
const char *path,
usec_t *last) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
}
static int list_unit_files(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ UnitFileList *units = NULL;
UnitFileList *unit;
size_t size = 0;
assert(c <= n_units);
hashmap_free(h);
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
r = acquire_bus(BUS_MANAGER, &bus);
[DEPENDENCY_BEFORE] = "Before\0",
};
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = 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_strv_free_ char **ret = NULL;
_cleanup_free_ char *path = NULL;
int r;
}
static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
- _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
int r;
assert(mi);
}
static int get_default(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *_path = NULL;
const char *path;
int r;
path = _path;
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
r = acquire_bus(BUS_MANAGER, &bus);
for (i = 0; i < n_changes; i++) {
if (changes[i].type == UNIT_FILE_SYMLINK)
- log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
+ log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
else
log_info("Removed symlink %s.", changes[i].path);
}
unit_file_changes_free(changes, n_changes);
r = 0;
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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();
}
static int list_jobs(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
return r;
STRV_FOREACH(name, strv_skip(argv, 1)) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
uint32_t id;
int q;
}
static int need_daemon_reload(sd_bus *bus, const char *unit) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *path;
int b, r;
assert(lp);
if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *unit = NULL;
- char *unit_load_error_name, *unit_load_error_message;
unit = unit_dbus_path_from_name(unit_name);
if (!unit)
return log_oom();
- if (need_daemon_reload(bus, unit_name) > 0)
- warn_unit_file_changed(unit_name);
-
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.systemd1",
- unit,
- "org.freedesktop.systemd1.Unit",
- "LoadError",
- &error,
- &unit_load_error,
- "(ss)");
- if (r < 0)
- return log_error_errno(r, "Failed to get LoadError: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(
- unit_load_error,
- "(ss)",
- &unit_load_error_name,
- &unit_load_error_message);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(unit_load_error_name)) {
- log_error("Unit %s is not loaded: %s", unit_name, unit_load_error_message);
- return 0;
- }
-
r = sd_bus_get_property_string(
bus,
"org.freedesktop.systemd1",
}
static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_free_ char *n = NULL, *state = NULL;
- 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;
+ _cleanup_free_ char *buf = NULL;
+ const char *path, *state;
int r;
assert(name);
- r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- /* We don't use unit_dbus_path_from_name() directly since we
- * don't want to load the unit if it isn't loaded. */
+ /* 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.Manager",
"GetUnit",
- NULL,
+ &error,
&reply,
- "s", n);
+ "s", name);
if (r < 0) {
- if (!quiet)
- puts("unknown");
- return 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));
- r = sd_bus_message_read(reply, "o", &path);
- if (r < 0)
- return bus_log_parse_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";
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "ActiveState",
- NULL,
- &state);
- if (r < 0) {
- if (!quiet)
- puts("unknown");
- return 0;
+ } 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)
sd_bus *bus,
const char *name) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
{ "try-restart", "TryRestartUnit" },
{ "condrestart", "TryRestartUnit" },
{ "reload-or-restart", "ReloadOrRestartUnit" },
+ { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
{ "reload-or-try-restart", "ReloadOrTryRestartUnit" },
{ "condreload", "ReloadOrTryRestartUnit" },
{ "force-reload", "ReloadOrTryRestartUnit" }
sd_bus_error *error,
BusWaitForJobs *w) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *path;
int r;
verb = method_to_verb(method);
- return log_error_errno(r, "Failed to %s %s: %s", verb, name, bus_error_message(error, r));
+ 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);
/* Query the manager only if any of the names are a glob, since
* this is fairly expensive */
if (!strv_isempty(globs)) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
- for (i = 0; i < r; i++)
- if (strv_extend(&mangled, unit_infos[i].id) < 0)
+ 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;
}
STRV_FOREACH(name, names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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 (!arg_no_block) {
int q;
- q = bus_wait_for_jobs(w, arg_quiet);
+ q = bus_wait_for_jobs(w, arg_quiet, arg_scope != UNIT_FILE_SYSTEM ? "--user" : NULL);
if (q < 0)
return q;
static int logind_set_wall_message(void) {
#ifdef HAVE_LOGIND
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
_cleanup_free_ char *m = NULL;
int r;
* through PolicyKit */
static int logind_reboot(enum action a) {
#ifdef HAVE_LOGIND
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *method, *description;
sd_bus *bus;
int r;
static int logind_check_inhibitors(enum action a) {
#ifdef HAVE_LOGIND
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
static int logind_prepare_firmware_setup(void) {
#ifdef HAVE_LOGIND
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
int r;
}
static int set_exit_code(uint8_t code) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
int r;
sd_bus *bus;
char **name;
int r;
+ bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
state = check_one_unit(bus, *name, good_states, arg_quiet);
if (state < 0)
return state;
- if (state == 0)
- r = code;
+ if (state > 0)
+ found = true;
}
- return r;
+ /* 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) {
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
q = sd_bus_call_method(
bus,
usec_t inactive_enter_timestamp;
bool need_daemon_reload;
+ bool transient;
/* Service */
pid_t main_pid;
path = i->source_path ? i->source_path : i->fragment_path;
- if (i->load_error)
+ 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\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;
i->condition_result = b;
else if (streq(name, "AssertResult"))
i->assert_result = b;
+ else if (streq(name, "Transient"))
+ i->transient = b;
break;
}
bool *new_line,
bool *ellipsized) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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,
uint32_t pid,
char **unit) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
bool *new_line,
bool *ellipsized) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ UnitInfo *unit_infos = NULL;
const UnitInfo *u;
unsigned c;
return -EINVAL;
}
- if (show_properties)
- pager_open_if_enabled();
+ pager_open_if_enabled();
if (show_status)
/* Increase max number of open files to 16K if we can, we
}
static int set_property(int argc, char *argv[], void *userdata) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
return bus_log_create_error(r);
STRV_FOREACH(i, strv_skip(argv, 2)) {
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
- if (r < 0)
- return bus_log_create_error(r);
-
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_message_close_container(m);
}
static int daemon_reload(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *method;
sd_bus *bus;
int r;
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
q = sd_bus_call_method(
bus,
}
static int show_environment(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
}
static int switch_root(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int set_environment(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ 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 *m = NULL;
const char *method;
sd_bus *bus;
int r;
}
static int import_environment(int argc, char *argv[], void *userdata) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ 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 *m = NULL;
sd_bus *bus;
int r;
r = 0;
} else {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
unit_file_changes_free(changes, n_changes);
} else {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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 = 0;
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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();
}
} else {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
r = acquire_bus(BUS_MANAGER, &bus);
return r;
STRV_FOREACH(name, names) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *s;
r = sd_bus_call_method(
sd_bus *bus;
int r;
- if (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted()) {
+ if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
if (!arg_quiet)
puts("offline");
return EXIT_FAILURE;
" 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"
- " reload-or-try-restart NAME... Reload one or more units if possible,\n"
- " otherwise restart if active\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"
return version();
case 't': {
- if (isempty(optarg))
- return log_error_errno(r, "--type requires arguments.");
+ if (isempty(optarg)) {
+ log_error("--type requires arguments.");
+ return -EINVAL;
+ }
p = optarg;
for(;;) {
break;
case ARG_STATE: {
- if (isempty(optarg))
- return log_error_errno(r, "--signal requires arguments.");
+ if (isempty(optarg)) {
+ log_error("--signal requires arguments.");
+ return -EINVAL;
+ }
p = optarg;
for(;;) {
static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
- { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_units },
- { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
- { "list-sockets", VERB_ANY, VERB_ANY, 0, list_sockets },
- { "list-timers", VERB_ANY, VERB_ANY, 0, list_timers },
- { "list-jobs", VERB_ANY, VERB_ANY, 0, list_jobs },
- { "list-machines", VERB_ANY, VERB_ANY, 0, list_machines },
- { "clear-jobs", VERB_ANY, 1, 0, daemon_reload },
- { "cancel", VERB_ANY, VERB_ANY, 0, cancel_job },
- { "start", 2, VERB_ANY, 0, start_unit },
- { "stop", 2, VERB_ANY, 0, start_unit },
- { "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */
- { "reload", 2, VERB_ANY, 0, start_unit },
- { "restart", 2, VERB_ANY, 0, start_unit },
- { "try-restart", 2, VERB_ANY, 0, start_unit },
- { "reload-or-restart", 2, VERB_ANY, 0, start_unit },
- { "reload-or-try-restart", 2, VERB_ANY, 0, start_unit },
- { "force-reload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with SysV */
- { "condreload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */
- { "condrestart", 2, VERB_ANY, 0, start_unit }, /* For compatibility with RH */
- { "isolate", 2, 2, 0, start_unit },
- { "kill", 2, VERB_ANY, 0, kill_unit },
- { "is-active", 2, VERB_ANY, 0, check_unit_active },
- { "check", 2, VERB_ANY, 0, check_unit_active },
- { "is-failed", 2, VERB_ANY, 0, check_unit_failed },
- { "show", VERB_ANY, VERB_ANY, 0, show },
- { "cat", 2, VERB_ANY, 0, cat },
- { "status", VERB_ANY, VERB_ANY, 0, show },
- { "help", VERB_ANY, VERB_ANY, 0, show },
- { "daemon-reload", VERB_ANY, 1, 0, daemon_reload },
- { "daemon-reexec", VERB_ANY, 1, 0, daemon_reload },
- { "show-environment", VERB_ANY, 1, 0, show_environment },
- { "set-environment", 2, VERB_ANY, 0, set_environment },
- { "unset-environment", 2, VERB_ANY, 0, set_environment },
- { "import-environment", VERB_ANY, VERB_ANY, 0, import_environment},
- { "halt", VERB_ANY, 1, 0, start_special },
- { "poweroff", VERB_ANY, 1, 0, start_special },
- { "reboot", VERB_ANY, 2, 0, start_special },
- { "kexec", VERB_ANY, 1, 0, start_special },
- { "suspend", VERB_ANY, 1, 0, start_special },
- { "hibernate", VERB_ANY, 1, 0, start_special },
- { "hybrid-sleep", VERB_ANY, 1, 0, start_special },
- { "default", VERB_ANY, 1, 0, start_special },
- { "rescue", VERB_ANY, 1, 0, start_special },
- { "emergency", VERB_ANY, 1, 0, start_special },
- { "exit", VERB_ANY, 2, 0, start_special },
- { "reset-failed", VERB_ANY, VERB_ANY, 0, 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, 0, switch_root },
- { "list-dependencies", VERB_ANY, 2, 0, list_dependencies },
- { "set-default", 2, 2, 0, set_default },
- { "get-default", VERB_ANY, 1, 0, get_default, },
- { "set-property", 3, VERB_ANY, 0, 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, 0, edit },
+ { "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 },
{}
};
static int logind_schedule_shutdown(void) {
#ifdef HAVE_LOGIND
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char date[FORMAT_TIMESTAMP_MAX];
const char *action;
sd_bus *bus;
static int logind_cancel_shutdown(void) {
#ifdef HAVE_LOGIND
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
int r;
if (r <= 0)
goto finish;
- if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
+ if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
log_info("Running in chroot, ignoring request.");
r = 0;
goto finish;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdcommonhfoo
#define foosdcommonhfoo
# ifdef __cplusplus
# define _SD_BEGIN_DECLARATIONS \
extern "C" { \
- struct __useless_struct_to_allow_trailing_semicolon__
+ struct _sd_useless_struct_to_allow_trailing_semicolon_
# else
# define _SD_BEGIN_DECLARATIONS \
- struct __useless_struct_to_allow_trailing_semicolon__
+ struct _sd_useless_struct_to_allow_trailing_semicolon_
# endif
#endif
# ifdef __cplusplus
# define _SD_END_DECLARATIONS \
} \
- struct __useless_struct_to_allow_trailing_semicolon__
+ struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_
# else
# define _SD_END_DECLARATIONS \
- struct __useless_struct_to_allow_trailing_semicolon__
+ 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdbusprotocolhfoo
#define foosdbusprotocolhfoo
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdbusvtablehfoo
#define foosdbusvtablehfoo
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdbushfoo
#define foosdbushfoo
#include <sys/types.h>
#include <sys/uio.h>
-#include "sd-id128.h"
#include "sd-event.h"
+#include "sd-id128.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddaemonhfoo
#define foosddaemonhfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include "_sd-common.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddevicehfoo
#define foosddevicehfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include "_sd-common.h"
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddhcpclienthfoo
#define foosddhcpclienthfoo
#include <netinet/in.h>
#include <sys/types.h>
-#include "sd-event.h"
#include "sd-dhcp-lease.h"
+#include "sd-event.h"
#include "_sd-common.h"
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,
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_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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddhcpleasehfoo
#define foosddhcpleasehfoo
_SD_BEGIN_DECLARATIONS;
typedef struct sd_dhcp_lease sd_dhcp_lease;
-struct sd_dhcp_route;
+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_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, struct sd_dhcp_route **routes);
+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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddhcpserverhfoo
#define foosddhcpserverhfoo
#include <netinet/in.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddhcp6clienthfoo
#define foosddhcp6clienthfoo
#include <net/ethernet.h>
#include <sys/types.h>
-#include "sd-event.h"
#include "sd-dhcp6-lease.h"
+#include "sd-event.h"
#include "_sd-common.h"
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,
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosddhcp6leasehfoo
#define foosddhcp6leasehfoo
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdeventhfoo
#define foosdeventhfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-#include <sys/signalfd.h>
-#include <sys/epoll.h>
#include <inttypes.h>
#include <signal.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
+#include <sys/types.h>
#include "_sd-common.h"
SD_EVENT_PENDING,
SD_EVENT_RUNNING,
SD_EVENT_EXITING,
- SD_EVENT_FINISHED
+ SD_EVENT_FINISHED,
+ SD_EVENT_PREPARING,
};
enum {
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 timeout);
+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 timeout);
+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_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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdhwdbhfoo
#define foosdhwdbhfoo
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdid128hfoo
#define foosdid128hfoo
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdipv4acdfoo
#define foosdipv4acdfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/in.h>
#include <net/ethernet.h>
+#include <netinet/in.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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);
+int sd_ipv4acd_new(sd_ipv4acd **ret);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref);
_SD_END_DECLARATIONS;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdipv4llfoo
#define foosdipv4llfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/in.h>
#include <net/ethernet.h>
+#include <netinet/in.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdjournalhfoo
#define foosdjournalhfoo
***/
#include <inttypes.h>
-#include <sys/types.h>
#include <stdarg.h>
+#include <sys/types.h>
#include <sys/uio.h>
#include <syslog.h>
#include "sd-id128.h"
+
#include "_sd-common.h"
/* Journal APIs. See sd-journal(3) for more information. */
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_get_catalog(sd_journal *j, char **text);
int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
-/* the inverse condition avoids ambiguity of danling 'else' after the macro */
+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 danling 'else' after the macro */
+/* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdlldphfoo
#define foosdlldphfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <net/ethernet.h>
#include <inttypes.h>
+#include <net/ethernet.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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);
-void sd_lldp_free(sd_lldp *lldp);
+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_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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdloginhfoo
#define foosdloginhfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include "_sd-common.h"
/* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdmessageshfoo
#define foosdmessageshfoo
***/
#include "sd-id128.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
#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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdndiscfoo
#define foosdndiscfoo
#include <net/ethernet.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
be16toh((address).s6_addr16[6]), \
be16toh((address).s6_addr16[7])
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref);
+
_SD_END_DECLARATIONS;
#endif
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdnetlinkhfoo
#define foosdnetlinkhfoo
***/
#include <inttypes.h>
-#include <netinet/in.h>
#include <netinet/ether.h>
+#include <netinet/in.h>
#include <linux/rtnetlink.h>
#include <linux/neighbour.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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_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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdnetworkhfoo
#define foosdnetworkhfoo
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include "_sd-common.h"
* representations of IP addresses */
int sd_network_get_ntp(char ***ntp);
-/* Get the search/routing domains for all links. */
-int sd_network_get_domains(char ***domains);
+/* 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:
*/
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 DNS domain names for a given link. */
-int sd_network_link_get_domains(int ifindex, char ***domains);
+/* 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 timezone that was learnt on a specific link. */
int sd_network_link_get_timezone(int ifindex, char **timezone);
-/* Returns whether or not domains that don't match any link should be resolved
- * on this link. 1 for yes, 0 for no and negative value for error */
-int sd_network_link_get_wildcard_domain(int ifindex);
-
/* Monitor object */
typedef struct sd_network_monitor sd_network_monitor;
/* 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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdpathhfoo
#define foosdpathhfoo
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdresolvehfoo
#define foosdresolvehfoo
#include <sys/types.h>
#include "sd-event.h"
+
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
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 = 1ULL,
- SD_RESOLVE_GET_SERVICE = 2ULL,
- SD_RESOLVE_GET_BOTH = 3ULL
+ 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);
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#ifndef foosdutf8hfoo
#define foosdutf8hfoo
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
if (putgrent(&t, group) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 1;
}
errno = 0;
if (putgrent(gr, group) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
errno = 0;
if (putsgent(&t, gshadow) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 1;
}
errno = 0;
if (putsgent(sg, gshadow) != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
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;
}
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;
}
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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int generate_unit_file(SysvStub *s) {
- _cleanup_free_ char *before = NULL, *after = NULL, *wants = NULL, *conflicts = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *unit;
char **p;
unit = strjoina(arg_dest, "/", s->name);
- before = strv_join(s->before, " ");
- after = strv_join(s->after, " ");
- wants = strv_join(s->wants, " ");
- conflicts = strv_join(s->conflicts, " ");
-
- if (!before || !after || !wants || !conflicts)
- return log_oom();
-
/* 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 (s->description)
fprintf(f, "Description=%s\n", s->description);
- if (!isempty(before))
- fprintf(f, "Before=%s\n", before);
- if (!isempty(after))
- fprintf(f, "After=%s\n", after);
- if (!isempty(wants))
- fprintf(f, "Wants=%s\n", wants);
- if (!isempty(conflicts))
- fprintf(f, "Conflicts=%s\n", conflicts);
+ 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"
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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();
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
u = after;
r = calendar_spec_next_usec(c, after, &u);
- printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), 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
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 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <netinet/in.h>
#include <pwd.h>
#include <sys/capability.h>
+#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
cap_free(text);
}
-static int setup_tests(void) {
+static int setup_tests(bool *run_ambient) {
struct passwd *nobody;
+ int r;
nobody = getpwnam("nobody");
if (!nobody) {
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;
}
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();
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
- assert_se(condition_test(condition) != mac_selinux_use());
+ assert_se(condition_test(condition) != mac_selinux_have());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "ima", false, false);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static void test_should_pass(const char *p) {
usec_t t, q;
- char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ 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 */
- *strrchr(buf, ' ') = 0;
+ sp = strrchr(buf, ' ');
+ assert_se(sp);
+ *sp = 0;
assert_se(parse_timestamp(buf, &q) >= 0);
assert_se(q == t);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static void test_dns_label_unescape(void) {
test_dns_label_unescape_one("hallo", "hallo", 6, 5);
- test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC);
+ 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("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;
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, -ENOSPC, -ENOSPC);
+ 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\\", "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, 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, 0, 6);
+ 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);
_cleanup_free_ char *t = NULL;
int r;
- r = dns_label_escape(what, l, &t);
+ r = dns_label_escape_new(what, l, &t);
assert_se(r == ret);
if (r < 0)
}
static void test_dns_label_escape(void) {
- test_dns_label_escape_one("", 0, "", 0);
+ test_dns_label_escape_one("", 0, NULL, -EINVAL);
test_dns_label_escape_one("hallo", 5, "hallo", 5);
- test_dns_label_escape_one("hallo", 6, NULL, -EINVAL);
+ 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(void) {
- test_dns_name_normalize_one("", "", 0);
+ 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", NULL, -EINVAL);
+ 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);
+ test_dns_name_normalize_one(".", ".", 0);
}
static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
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", "xxxx", -EINVAL);
+ 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);
test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
}
-static void test_dns_name_root(void) {
- assert_se(dns_name_root("") == true);
- assert_se(dns_name_root(".") == true);
- assert_se(dns_name_root("xxx") == false);
- assert_se(dns_name_root("xxx.") == false);
- assert_se(dns_name_root("..") == -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_single_label(void) {
- assert_se(dns_name_single_label("") == false);
- assert_se(dns_name_single_label(".") == false);
- assert_se(dns_name_single_label("..") == -EINVAL);
- assert_se(dns_name_single_label("x") == true);
- assert_se(dns_name_single_label("x.") == true);
- assert_se(dns_name_single_label("xx.yy") == false);
+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) {
}
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) {
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_name_normalize();
test_dns_name_equal();
test_dns_name_endswith();
+ test_dns_name_startswith();
test_dns_name_between();
- test_dns_name_root();
- test_dns_name_single_label();
+ 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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-util.h"
#include "manager.h"
+#include "test-helper.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+ _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;
/* prepare the test */
assert_se(set_unit_path(TEST_DIR) >= 0);
r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include "fileio.h"
#include "mkdir.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "test-helper.h"
#include "unit.h"
#include "util.h"
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;
test_exec_umask,
test_exec_runtimedirectory,
test_exec_capabilityboundingset,
+ test_exec_capabilityambientset,
test_exec_oomscoreadjust,
test_exec_ioschedulingclass,
NULL,
assert_se(unsetenv("VAR3") == 0);
r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
#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 */ \
+ )
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
#include "libudev.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
/* add sys path if needed */
if (!startswith(syspath, "/sys")) {
- snprintf(path, sizeof(path), "/sys/%s", syspath);
+ xsprintf(path, "/sys/%s", syspath);
syspath = path;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "test-helper.h"
#include "unit.h"
#include "util.h"
assert_se(m);
r = manager_new(MANAGER_USER, true, &tmp);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
return -EXIT_TEST_SKIP;
}
assert_se(r >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+/*
+ * Tests for RB-Tree
+ */
+
+#undef NDEBUG
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/resource.h>
+
+#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;
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "macro.h"
#include "manager.h"
+#include "test-helper.h"
int main(int argc, char *argv[]) {
Manager *m = NULL;
/* prepare the test */
assert_se(set_unit_path(TEST_DIR) >= 0);
r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
--- /dev/null
+/***
+ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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();
+}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
unsigned i, j;
out = siphash24(in, len, key);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
/* verify the internal state as given in the above paper */
siphash24_init(&state, key);
assert_se(state.v2 == 0x634cb3577b01fd3d);
assert_se(state.v3 == 0xa5224d6f55c7d9c8);
out = siphash24_finalize(&state);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
assert_se(state.v0 == 0xf6bcd53893fecff1);
assert_se(state.v1 == 0x54b9964c7ea0d937);
assert_se(state.v2 == 0x1b38329c099bb55a);
siphash24_compress(&in[i], j - i, &state);
siphash24_compress(&in[j], len - j, &state);
out = siphash24_finalize(&state);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
}
}
return 0;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
r = get_timezones(&zones);
assert_se(r == 0);
- STRV_FOREACH(zone, zones) {
+ 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(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;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
const char *p = argv[1] ?: "/tmp";
char *pattern = strjoina(p, "/systemd-test-XXXXXX");
_cleanup_close_ int fd, fd2;
- _cleanup_free_ char *cmd, *cmd2;
+ _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);
- system(cmd);
+ (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);
- system(cmd2);
+ (void) system(cmd2);
+ assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0);
+ log_debug("link2: %s", ans2);
+ assert_se(endswith(ans2, " (deleted)"));
return 0;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <unistd.h>
#include "alloc-util.h"
+#include "capability-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "hashmap.h"
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, NULL);
+ &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, NULL);
+ &c, u);
log_info("/* test slashes */");
assert_se(r >= 0);
log_info("/* trailing slash */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/RValue/ argv0 r1",
- &c, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
"LValue", 0,
"-@/RValue argv0 r1 ; "
"/goo/goo boo",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
"LValue", 0,
"-@/RValue argv0 r1 ; ; "
"/goo/goo boo",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ; ",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ;",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ';'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \\;",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \\; /x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \\;x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \\073",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \";\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \";\" /x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon\" -1 -2",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon -1 -2\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
log_info("/* invalid character: \\%c */", *ccc);
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, path,
- &c, NULL);
+ &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, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/grep '\\w+\\K'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
/* backslash is invalid */
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/path\\",
- &c, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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, NULL);
+ &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 \
return ((uint64_t) 1ULL << (uint64_t) cap);
}
-static void test_config_parse_bounding_set(void) {
- /* int config_parse_bounding_set(
+static void test_config_parse_capability_set(void) {
+ /* int config_parse_capability_set(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) */
int r;
- uint64_t capability_bounding_set_drop = 0;
+ uint64_t capability_bounding_set = 0;
- r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
"CapabilityBoundingSet", 0, "CAP_NET_RAW",
- &capability_bounding_set_drop, NULL);
+ &capability_bounding_set, NULL);
assert_se(r >= 0);
- assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW));
+ assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
- r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
"CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
- &capability_bounding_set_drop, NULL);
+ &capability_bounding_set, NULL);
assert_se(r >= 0);
- assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
- r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
"CapabilityBoundingSet", 0, "",
- &capability_bounding_set_drop, NULL);
+ &capability_bounding_set, NULL);
assert_se(r >= 0);
- assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL));
+ assert_se(capability_bounding_set == UINT64_C(0));
- r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
"CapabilityBoundingSet", 0, "~",
- &capability_bounding_set_drop, NULL);
+ &capability_bounding_set, NULL);
assert_se(r >= 0);
- assert_se(capability_bounding_set_drop == (uint64_t) 0ULL);
+ assert_se(cap_test_all(capability_bounding_set));
- capability_bounding_set_drop = 0;
- r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ 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_drop, NULL);
+ &capability_bounding_set, NULL);
assert_se(r >= 0);
- assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
}
static void test_config_parse_rlimit(void) {
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_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ 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_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ 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_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ 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_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ 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_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ 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_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ 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_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ 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_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ 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);
r = test_unit_file_get_set();
test_config_parse_exec();
- test_config_parse_bounding_set();
+ test_config_parse_capability_set();
test_config_parse_rlimit();
test_config_parse_pass_environ();
test_load_env_file_1();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <string.h>
#include "alloc-util.h"
+#include "glob-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "manager.h"
assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY));
}
-static void test_u_n_r_i_one(const char *pattern, const char *repl, const char *expected, int ret) {
+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_u_n_r_i(void) {
+static void test_unit_name_replace_instance(void) {
puts("-------------------------------------------------");
- test_u_n_r_i_one("foo@.service", "waldo", "foo@waldo.service", 0);
- test_u_n_r_i_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
- test_u_n_r_i_one("xyz", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("foo.service", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one(".service", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("foo@", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("@bar", "waldo", NULL, -EINVAL);
+ 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_u_n_f_p_one(const char *path, const char *suffix, const char *expected, int ret) {
+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);
}
}
-static void test_u_n_f_p(void) {
+static void test_unit_name_from_path(void) {
puts("-------------------------------------------------");
- test_u_n_f_p_one("/waldo", ".mount", "waldo.mount", 0);
- test_u_n_f_p_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
- test_u_n_f_p_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
- test_u_n_f_p_one("", ".mount", "-.mount", 0);
- test_u_n_f_p_one("/", ".mount", "-.mount", 0);
- test_u_n_f_p_one("///", ".mount", "-.mount", 0);
- test_u_n_f_p_one("/foo/../bar", ".mount", NULL, -EINVAL);
- test_u_n_f_p_one("/foo/./bar", ".mount", NULL, -EINVAL);
+ 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_u_n_f_p_i_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) {
+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);
}
}
-static void test_u_n_f_p_i(void) {
+static void test_unit_name_from_path_instance(void) {
puts("-------------------------------------------------");
- test_u_n_f_p_i_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
- test_u_n_f_p_i_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
- test_u_n_f_p_i_one("waldo", "/", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "///", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "..", ".mount", NULL, -EINVAL);
- test_u_n_f_p_i_one("waldo", "/foo", ".waldi", NULL, -EINVAL);
- test_u_n_f_p_i_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
+ 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_u_n_t_p_one(const char *unit, const char *path, int ret) {
+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_u_n_t_p(void) {
- test_u_n_t_p_one("home.mount", "/home", 0);
- test_u_n_t_p_one("home-lennart.mount", "/home/lennart", 0);
- test_u_n_t_p_one("home-lennart-.mount", NULL, -EINVAL);
- test_u_n_t_p_one("-home-lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("-home--lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("home-..-lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("", NULL, -EINVAL);
- test_u_n_t_p_one("home/foo", NULL, -EINVAL);
+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_u_n_m_one(const char *pattern, const char *expect, int ret) {
+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, UNIT_NAME_NOGLOB, &t) == ret);
+ 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));
+ 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, UNIT_NAME_NOGLOB, &k) == 0);
+ assert_se(unit_name_mangle(t, allow_globs, &k) == 0);
assert_se(streq_ptr(t, k));
}
}
-static void test_u_n_m(void) {
+static void test_unit_name_mangle(void) {
puts("-------------------------------------------------");
- test_u_n_m_one("foo.service", "foo.service", 0);
- test_u_n_m_one("/home", "home.mount", 1);
- test_u_n_m_one("/dev/sda", "dev-sda.device", 1);
- test_u_n_m_one("üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
- test_u_n_m_one("foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
- test_u_n_m_one("_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
- test_u_n_m_one("_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
- test_u_n_m_one("xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
- test_u_n_m_one("", NULL, -EINVAL);
+ 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) {
int main(int argc, char* argv[]) {
int rc = 0;
test_unit_name_is_valid();
- test_u_n_r_i();
- test_u_n_f_p();
- test_u_n_f_p_i();
- test_u_n_m();
- test_u_n_t_p();
+ 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();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
static void test_base64mem(void) {
char *b64;
- b64 = base64mem("", strlen(""));
- assert_se(b64);
+ assert_se(base64mem("", strlen(""), &b64) == 0);
assert_se(streq(b64, ""));
free(b64);
- b64 = base64mem("f", strlen("f"));
- assert_se(b64);
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
assert_se(streq(b64, "Zg=="));
free(b64);
- b64 = base64mem("fo", strlen("fo"));
- assert_se(b64);
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
assert_se(streq(b64, "Zm8="));
free(b64);
- b64 = base64mem("foo", strlen("foo"));
- assert_se(b64);
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
assert_se(streq(b64, "Zm9v"));
free(b64);
- b64 = base64mem("foob", strlen("foob"));
- assert_se(b64);
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
assert_se(streq(b64, "Zm9vYg=="));
free(b64);
- b64 = base64mem("fooba", strlen("fooba"));
- assert_se(b64);
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmE="));
free(b64);
- b64 = base64mem("foobar", strlen("foobar"));
- assert_se(b64);
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmFy"));
free(b64);
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
}
static int set_time(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _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;
}
static int set_timezone(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(args);
}
static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r, b;
assert(args);
}
static int set_ntp(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int b, r;
assert(args);
}
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include "bus-util.h"
#include "clock-util.h"
#include "def.h"
-#include "event-util.h"
#include "fileio-label.h"
#include "fs-util.h"
#include "path-util.h"
}
static int context_read_ntp(Context *c, sd_bus *bus) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _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;
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
assert(c);
int main(int argc, char *argv[]) {
Context context = {};
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "conf-parser.h"
-
#include "timesyncd-manager.h"
const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
if (r < 0)
return -errno;
- touch("/var/lib/systemd/clock");
+ /* 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
***/
#include "sd-event.h"
-#include "sd-resolve.h"
#include "sd-network.h"
+#include "sd-resolve.h"
+
#include "list.h"
#include "ratelimit.h"
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "socket-util.h"
#include "list.h"
+#include "socket-util.h"
typedef struct ServerAddress ServerAddress;
typedef struct ServerName ServerName;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
errno = 0;
de = readdir(d);
if (!de) {
- if (errno != 0 && r == 0)
+ if (errno > 0 && r == 0)
r = -errno;
break;
_cleanup_free_ char *resolved = NULL;
struct stat st;
int r = 0;
+ int q = 0;
CreationMode creation;
assert(i);
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) {
+ 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);
- return 0;
- }
- if (r == -EROFS) {
+ else if (r == -EROFS)
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of read-only file system: %m", i->path);
- return 0;
- }
- if (r == -ENOPROTOOPT) {
+ else if (r == -ENOPROTOOPT)
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because quota support is disabled: %m", i->path);
- return 0;
- }
- if (r < 0)
- return log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
- if (r > 0)
+ 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);
- if (r == 0)
+ 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;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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, *packet = NULL;
+ _cleanup_free_ char *socket_name = NULL, *message = NULL;
bool accept_cached = false, echo = false;
- size_t packet_length = 0;
uint64_t not_after = 0;
unsigned pid = 0;
*wall = _wall;
} else {
- union sockaddr_union sa = {};
- _cleanup_close_ int socket_fd = -1;
+ _cleanup_strv_free_erase_ char **passwords = NULL;
assert(arg_action == ACTION_QUERY ||
arg_action == ACTION_WATCH);
return 0;
}
- if (arg_plymouth) {
- _cleanup_strv_free_erase_ char **passwords = NULL;
-
+ if (arg_plymouth)
r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords);
- if (r >= 0) {
- char **p;
-
- packet_length = 1;
- STRV_FOREACH(p, passwords)
- packet_length += strlen(*p) + 1;
-
- packet = new(char, packet_length);
- if (!packet)
- r = -ENOMEM;
- else {
- char *d = packet + 1;
-
- STRV_FOREACH(p, passwords)
- d = stpcpy(d, *p) + 1;
-
- packet[0] = '+';
- }
- }
-
- } else {
- _cleanup_string_free_erase_ char *password = NULL;
+ else {
+ char *password = NULL;
int tty_fd = -1;
if (arg_console) {
release_terminal();
}
- if (r >= 0) {
- packet_length = 1 + strlen(password) + 1;
- packet = new(char, packet_length);
- if (!packet)
- r = -ENOMEM;
- else {
- packet[0] = '+';
- strcpy(packet + 1, password);
- }
- }
- }
+ if (r >= 0)
+ r = strv_push(&passwords, password);
- if (IN_SET(r, -ETIME, -ENOENT)) {
- /* If the query went away, that's OK */
- r = 0;
- goto finish;
- }
- if (r < 0) {
- log_error_errno(r, "Failed to query password: %m");
- goto finish;
+ if (r < 0)
+ string_free_erase(password);
}
- socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (socket_fd < 0) {
- r = log_error_errno(errno, "socket(): %m");
- goto finish;
- }
+ /* If the query went away, that's OK */
+ if (IN_SET(r, -ETIME, -ENOENT))
+ return 0;
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
+ if (r < 0)
+ return log_error_errno(r, "Failed to query password: %m");
- r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name));
- memory_erase(packet, packet_length);
+ r = send_passwords(socket_name, passwords);
if (r < 0)
- return log_error_errno(errno, "Failed to send: %m");
+ return log_error_errno(r, "Failed to send: %m");
}
return 0;
-
-finish:
- memory_erase(packet, packet_length);
- return r;
}
static int wall_tty_block(void) {
#include "alloc-util.h"
#include "libudev-private.h"
#include "macro.h"
+#include "stdio-util.h"
#include "string-util.h"
#define BUFSIZE 16
if (r < 0 && errno != EEXIST)
return -errno;
- snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
+ xsprintf(buf, "%s/%s", dir, filename);
fd = open(buf,O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR);
if (fd < 0)
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/*
* Default 5 second timeout
*/
-#define DEF_TIMEOUT 5000
+#define DEF_TIMEOUT 5000
-#define SENSE_BUFF_LEN 32
+#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
+#define SCSI_INQ_BUFF_LEN 254
/*
* SCSI INQUIRY vendor and model (really product) lengths.
*/
-#define VENDOR_LENGTH 8
-#define MODEL_LENGTH 16
+#define VENDOR_LENGTH 8
+#define MODEL_LENGTH 16
-#define INQUIRY_CMD 0x12
-#define INQUIRY_CMDLEN 6
+#define INQUIRY_CMD 0x12
+#define INQUIRY_CMDLEN 6
/*
* INQUIRY VPD page 0x83 identifier descriptor related values. Reference the
/*
* 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_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
+#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 5
-#define SCSI_ID_NAA_IEEE_REG_EXTENDED 6
+#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
+#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;
+ u_char id_type;
+ u_char naa_type;
+ u_char code_set;
};
/*
* used a 1 bit right and masked version of these. So now CHECK_CONDITION
* and friends (in <scsi/scsi.h>) are deprecated.
*/
-#define SCSI_CHECK_CONDITION 0x2
-#define SCSI_CONDITION_MET 0x4
-#define SCSI_BUSY 0x8
-#define SCSI_IMMEDIATE 0x10
+#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
+#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
* 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 },
+ { 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
* 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 },
+ { 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";
* 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 */
+#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 */
+#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,
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);
+ dev_scsi->kernel, sb_len, s - sb_len);
return -1;
}
if ((code == 0x0) || (code == 0x1)) {
* Possible?
*/
log_debug("%s: sense result too" " small %d bytes",
- dev_scsi->kernel, s);
+ dev_scsi->kernel, s);
return -1;
}
asc = sense_buffer[12];
ascq = sense_buffer[3];
} else {
log_debug("%s: invalid sense code 0x%x",
- dev_scsi->kernel, code);
+ 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);
+ 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);
+ dev_scsi->kernel, sb_len, 4 - sb_len);
return -1;
}
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]);
+ 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);
+ dev_scsi->kernel, sense_class, code);
}
}
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);
+ 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
}
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);
+ 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);
error:
if (retval < 0)
log_debug("%s: Unable to get INQUIRY vpd %d page 0x%x.",
- dev_scsi->kernel, evpd, page);
+ dev_scsi->kernel, evpd, page);
return retval;
}
return 1;
}
if (buffer[3] > len) {
- log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]);
+ log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]);
return 1;
}
*/
if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
log_debug("%s: expected length %d, got length %d",
- dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
+ dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
return -1;
}
return ind;
if (max_len < len) {
log_debug("%s: length %d too short - need %d",
- dev_scsi->kernel, max_len, len);
+ dev_scsi->kernel, max_len, len);
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);
+ dev_scsi->kernel, max_len, len);
return 1;
}
/*
errno = 0;
pl = blkid_probe_get_partitions(pr);
if (!pl)
- return errno ? -errno : -ENOMEM;
+ return errno > 0 ? -errno : -ENOMEM;
nvals = blkid_partlist_numof_partitions(pl);
for (i = 0; i < nvals; i++) {
#include <linux/input.h>
#include "fd-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
#include "util.h"
if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0)
return;
- snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo));
- snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo));
+ 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);
if (!v)
v = "";
- snprintf(text, sizeof(text), "%s", v);
+ xsprintf(text, "%s", v);
log_debug("%s raw kernel attribute: %s", attr, text);
memzero(bitmask, bitmask_size);
if (test) {
/* printf pattern with the right unsigned long number of hex chars */
- snprintf(text, sizeof(text), " bit %%4u: %%0%zulX\n", 2 * sizeof(unsigned long));
+ 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 */
/* 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)
+ 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)
+ if (has_mt_coordinates && (is_direct || has_touch))
is_touchscreen = true;
if (has_rel_coordinates && has_mouse_button)
*
* Type of names:
* b<number> -- BCMA bus core number
- * ccw<name> -- CCW bus group name
+ * c<bus_id> -- CCW bus group name, without leading zeros [s390]
* o<index>[d<dev_port>] -- on-board device index number
* s<slot>[f<function>][d<dev_port>] -- hotplug slot index number
* x<MAC> -- MAC address
#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,
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)
err = -ENOENT;
goto out;
}
- snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci));
+ xsprintf(slots, "%s/slots", udev_device_get_syspath(pci));
dir = opendir(slots);
if (!dir) {
err = -errno;
continue;
if (i < 1)
continue;
- snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name);
+ 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)))
return -EINVAL;
/* suppress the common core == 0 */
if (core > 0)
- snprintf(names->bcma_core, sizeof(names->bcma_core), "b%u", core);
+ xsprintf(names->bcma_core, "b%u", core);
names->type = NET_BCMA;
return 0;
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), "ccw%s", bus_id);
+ 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;
/* skip commonly misused 00:00:00 (Xerox) prefix */
if (memcmp(names->mac, "\0\0\0", 3) == 0)
return -EINVAL;
- snprintf(str, sizeof(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]);
+ 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;
}
if (err >= 0 && names.mac_valid) {
char str[IFNAMSIZ];
- snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
+ 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);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
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");
#include <unistd.h>
#include "alloc-util.h"
-#include "event-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "netlink-util.h"
.pid = pid,
.accept_failure = accept_failure,
};
- _cleanup_event_unref_ sd_event *e = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
int r, ret;
r = sd_event_new(&e);
/* 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);
+ 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,
#include "fs-util.h"
#include "selinux-util.h"
#include "smack-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
return;
/* always add /dev/{block,char}/$major:$minor */
- snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
+ 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)));
+ 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 */
link_update(dev, udev_list_entry_get_name(list_entry), false);
/* remove /dev/{block,char}/$major:$minor */
- snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
+ 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)));
+ major(udev_device_get_devnum(dev)),
+ minor(udev_device_get_devnum(dev)));
unlink(filename);
}
#include <sys/inotify.h>
#include <unistd.h>
+#include "stdio-util.h"
#include "udev.h"
static int inotify_fd = -1;
return;
}
- snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+ xsprintf(filename, "/run/udev/watch/%d", wd);
mkdir_parents(filename, 0755);
unlink(filename);
r = symlink(udev_device_get_id_filename(dev), filename);
log_debug("removing watch on '%s'", udev_device_get_devnode(dev));
inotify_rm_watch(inotify_fd, wd);
- snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+ xsprintf(filename, "/run/udev/watch/%d", wd);
unlink(filename);
udev_device_set_watch_handle(dev, -1);
if (inotify_fd < 0 || wd < 0)
return NULL;
- snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+ xsprintf(filename, "/run/udev/watch/%d", wd);
len = readlink(filename, device, sizeof(device));
if (len <= 0 || (size_t)len == sizeof(device))
return NULL;
}
if (test) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
int r;
r = sd_hwdb_new(&hwdb);
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/*
* Copyright (C) 2007-2012 Kay Sievers <kay@vrfy.org>
*
#include "cgroup-util.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
-#include "event-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
switch (pid) {
case 0: {
struct udev_device *dev = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = 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 };
int main(int argc, char *argv[]) {
_cleanup_free_ char *cgroup = NULL;
- int r, fd_ctrl, fd_uevent;
+ int fd_ctrl = -1, fd_uevent = -1;
+ int r;
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
} Context;
static usec_t get_startup_time(Context *c) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
usec_t t = 0;
int r;
{ '1', SPECIAL_RESCUE_TARGET },
};
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
unsigned i;
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <unistd.h>
#include "fileio.h"
+#include "fileio-label.h"
#include "log.h"
+#include "selinux-util.h"
#include "string-util.h"
#include "util.h"
umask(0022);
+ mac_selinux_init(NULL);
+
if (streq(argv[1], "start")) {
int r = 0;
} else if (streq(argv[1], "stop")) {
int r;
- r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+ 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;
return EXIT_FAILURE;
}
+ mac_selinux_finish();
+
return EXIT_SUCCESS;
}
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#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"
continue;
/* skip non-allocated ttys */
- snprintf(vcname, sizeof(vcname), "/dev/vcs%i", i);
+ xsprintf(vcname, "/dev/vcs%i", i);
if (access(vcname, F_OK) < 0)
continue;
- snprintf(vcname, sizeof(vcname), "/dev/tty%i", i);
+ xsprintf(vcname, "/dev/tty%i", i);
vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC);
if (vcfd < 0)
continue;
# 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 %e
+kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %e
/basic.conf
/systemd.conf
+/systemd-remote.conf
# Access to certain kernel and userspace facilities
g kmem - - -
-g lock - - -
g tty @TTY_GID@ - -
g utmp - - -
+++ /dev/null
-# 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.
-
-u systemd-journal-gateway - "systemd Journal Gateway"
-u systemd-journal-remote - "systemd Journal Remote"
-u systemd-journal-upload - "systemd Journal Upload"
--- /dev/null
+# 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
m4_ifdef(`ENABLE_TIMESYNCD',
u systemd-timesync - "systemd Time Synchronization"
)m4_dnl
+m4_ifdef(`ENABLE_COREDUMP',
+u systemd-coredump - "systemd Core Dumper"
+)m4_dnl
$ 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 default kernel path and initramfs are used by default)
+(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
mount ${LOOPDEV}p1 $TESTDIR/root
[[ -e $TESTDIR/root/testok ]] && ret=0
[[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
- [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR
+ cp -a $TESTDIR/root/var/log/journal $TESTDIR
umount $TESTDIR/root
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
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
}
[[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
mount /dev/mapper/varcrypt $TESTDIR/root/var
- [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR
+ cp -a $TESTDIR/root/var/log/journal $TESTDIR
umount $TESTDIR/root/var
umount $TESTDIR/root
cryptsetup luksClose /dev/mapper/varcrypt
cat >>$initdir/etc/fstab <<EOF
/dev/mapper/varcrypt /var ext3 defaults 0 1
EOF
- )
- setup_nspawn_root
+ ) || return 1
ddebug "umount $TESTDIR/root/var"
umount $TESTDIR/root/var
# installed job.
systemctl start --no-block hello-after-sleep.target
-# sleep is now running, hello/start is waiting. Verify that:
+
systemctl list-jobs > /root/list-jobs.txt
-grep 'sleep\.service.*running' /root/list-jobs.txt || exit 1
+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.
systemctl start unstoppable.service || exit 1
touch /testok
-exit 0
cp test-jobs.sh $initdir/
setup_testsuite
- )
+ ) || return 1
setup_nspawn_root
ddebug "umount $TESTDIR/root"
--- /dev/null
+../TEST-01-BASIC/Makefile
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+#!/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 <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-journal.sh
+Type=oneshot
+EOF
+
+ cat >$initdir/etc/systemd/system/forever-print-hola.service <<EOF
+[Unit]
+Description=ForeverPrintHola service
+
+[Service]
+Type=simple
+ExecStart=/bin/sh -x -c 'while :; do printf "Hola\n" || touch /i-lose-my-logs; sleep 1; done'
+EOF
+
+ cp test-journal.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+ setup_nspawn_root
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+test_cleanup() {
+ umount $TESTDIR/root 2>/dev/null
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+ return 0
+}
+
+do_test "$@"
--- /dev/null
+../TEST-01-BASIC/Makefile
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+#!/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 <<EOF
+[Manager]
+DefaultLimitNOFILE=10000:16384
+EOF
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-rlimits.sh
+Type=oneshot
+EOF
+
+ cp test-rlimits.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+ setup_nspawn_root
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+test_cleanup() {
+ umount $TESTDIR/root 2>/dev/null
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+ return 0
+}
+
+do_test "$@"
--- /dev/null
+all:
+ @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
--- /dev/null
+template(`systemd_test_base_template', `
+ gen_require(`
+ attribute systemd_test_domain_type;
+ ')
+
+ type $1_t, systemd_test_domain_type;
+ domain_type($1_t)
+')
--- /dev/null
+policy_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 };
--- /dev/null
+#!/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
--- /dev/null
+#!/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 <<EOF >$initdir/etc/systemd/system/testsuite.service
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-selinux-checks.sh
+Type=oneshot
+EOF
+
+ cat <<EOF >$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 <<EOF >$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 "$@"
--- /dev/null
+../TEST-01-BASIC/Makefile
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+#!/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 <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-segfault.sh
+Type=oneshot
+EOF
+
+ cp test-segfault.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+ setup_nspawn_root
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+test_cleanup() {
+ umount $TESTDIR/root 2>/dev/null
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+ return 0
+}
+
+do_test "$@"
--- /dev/null
+#!/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 <martin.pitt@ubuntu.com>
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+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))
import tempfile
import shutil
from glob import glob
+import collections
try:
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):
for service in glob(self.out_dir + '/*.service'):
if os.path.islink(service):
continue
- cp = RawConfigParser()
+ 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)
s = self.run_generator()[1]['foo.service']
self.assertEqual(set(s.options('Unit')),
set(['Documentation', 'SourcePath', 'Description', 'After']))
- self.assertEqual(s.get('Unit', 'After'), 'nss-lookup.target rpcbind.target')
+ self.assertEqual(s.get('Unit', 'After').split(), ['nss-lookup.target', 'rpcbind.target'])
def test_lsb_deps(self):
'''LSB header dependencies to other services'''
--- /dev/null
+[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
--- /dev/null
+[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
ROOTLIBDIR=/usr/lib/systemd
fi
-BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe"
-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"
+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
&& 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" ] || INITRD=/boot/initramfs-${KERNEL_VER}.img
+ [ "$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 \
"
- QEMU_OPTIONS="-machine accel=kvm:tcg \
--smp $QEMU_SMP \
+ QEMU_OPTIONS="-smp $QEMU_SMP \
-net none \
-m 512M \
-nographic \
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 --boot --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
+ ../../systemd-nspawn --register=no --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
}
setup_basic_environment() {
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
- # softlink mtab
- ln -fs /proc/self/mounts $initdir/etc/mtab
+}
+
+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 <<EOF >$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 <<EOF
+#!/bin/bash
+
+exec valgrind --leak-check=full --log-file=/valgrind.out $ROOTLIBDIR/systemd "\$@"
+EOF
+ chmod 0755 $_valgrind_wrapper
+}
+
+install_fsck() {
+ dracut_install /sbin/fsck*
+ dracut_install -o /bin/fsck*
}
install_dmevent() {
instmods dm_crypt =crypto
type -P dmeventd >/dev/null && dracut_install dmeventd
inst_libdir_file "libdevmapper-event.so*"
- inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
+ 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() {
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=300
+ 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" <<EOF
-,290M
+,390M
,
EOF
}
strip_binaries() {
+ if [[ "$STRIP_BINARIES" = "no" ]]; then
+ ddebug "Don't strip binaries"
+ return 0
+ fi
ddebug "Strip binaries"
find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | xargs strip --strip-unneeded | ddebug
}
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/
}
}
check_nspawn() {
- [[ -d /sys/fs/cgroup/systemd ]]
+ [[ -d /run/systemd/system ]]
}
desc => "big major number test",
devpath => "/devices/virtual/misc/misc-fake1",
exp_name => "node",
- exp_majorminor => "4095:1",
+ exp_majorminor => "511:1",
rules => <<EOF
KERNEL=="misc-fake1", SYMLINK+="node"
EOF
desc => "big major and big minor number test",
devpath => "/devices/virtual/misc/misc-fake89999",
exp_name => "node",
- exp_majorminor => "4095:89999",
+ exp_majorminor => "511:89999",
rules => <<EOF
KERNEL=="misc-fake89999", SYMLINK+="node"
EOF
d /run/lock/subsys 0755 root root -
-# /run/lock/lockdev is used to serialize access to tty devices via
-# LCK..xxx style lock files, For more information see:
-# http://lists.freedesktop.org/archives/systemd-devel/2011-March/001823.html
-# On modern systems a BSD file lock is a better choice if
-# serialization is needed on those devices.
-
-d /run/lock/lockdev 0775 root lock -
-
# /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the
# kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and
# 'quotacheck.mode=force'
# See tmpfiles.d(5) for details
-z /var/log/journal/remote 2755 root systemd-journal-remote - -
-z /run/log/journal/remote 2755 root systemd-journal-remote - -
+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 - -
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 -
b = tree.SubElement(para, 'citerefentry')
c = tree.SubElement(b, 'refentrytitle')
c.text = manpage
+ c.attrib['target'] = varname
d = tree.SubElement(b, 'manvolnum')
d.text = manvolume
entry.tail = '\n\n'
/systemd-binfmt.service
/systemd-bootchart.service
/systemd-bus-proxyd.service
+/systemd-coredump@.service
/systemd-firstboot.service
/systemd-fsck-root.service
/systemd-fsck@.service
Documentation=man:systemd.special(7)
Requires=sysinit.target
Wants=sockets.target timers.target paths.target slices.target
-After=sysinit.target sockets.target paths.target slices.target
+After=sysinit.target sockets.target paths.target slices.target tmp.mount
# We support /var, /tmp, /var/tmp, being on NFS, but we don't pull in
-# remote-fs.target by default, hence explicitly pull /var in here.
-RequiresMountsFor=/var /tmp /var/tmp
+# remote-fs.target by default, hence pull them in explicitly here. Note that we
+# require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as
+# we support that unit being masked, and this should not be considered an error.
+RequiresMountsFor=/var /var/tmp
+Wants=tmp.mount
[Service]
Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
ExecStart=-@SULOGIN@
ExecStopPost=-@SYSTEMCTL@ poweroff
Type=idle
DefaultDependencies=no
Before=sysinit.target
ConditionPathExists=/proc/sys/fs/mqueue
+ConditionCapability=CAP_SYS_ADMIN
[Mount]
What=mqueue
[Service]
Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
ExecStartPre=-/bin/plymouth --wait quit
ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\ntry again to boot into default mode.'
ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default"
DefaultDependencies=no
Before=sysinit.target systemd-tmpfiles-setup-dev.service
ConditionCapability=CAP_SYS_MODULE
-ConditionPathExists=/lib/modules/%v/modules.devname
+ConditionFileNotEmpty=/lib/modules/%v/modules.devname
[Service]
Type=oneshot
[Service]
Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
ExecStartPre=-/bin/plymouth quit
-ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.'
+ExecStartPre=-/bin/echo -e 'Welcome to rescue mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.'
ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default"
Type=idle
StandardInput=tty-force
Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
DefaultDependencies=no
ConditionPathExists=/sys/fs/fuse/connections
+ConditionCapability=CAP_SYS_ADMIN
After=systemd-modules-load.service
Before=sysinit.target
--- /dev/null
+# 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.
+
+[Unit]
+Description=Process Core Dump Socket
+Documentation=man:systemd-coredump(8)
+DefaultDependencies=no
+
+[Socket]
+ListenSequentialPacket=/run/systemd/coredump
+SocketMode=0600
+Accept=yes
+MaxConnections=16
--- /dev/null
+# 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.
+
+[Unit]
+Description=Process Core Dump
+Documentation=man:systemd-coredump(8)
+DefaultDependencies=no
+RequiresMountsFor=/var/lib/systemd/coredump
+Conflicts=shutdown.target
+After=systemd-remount-fs.service systemd-journald.socket
+Requires=systemd-journald.socket
+Before=shutdown.target
+
+[Service]
+ExecStart=-@rootlibexecdir@/systemd-coredump
+Nice=9
+OOMScoreAdjust=500
+PrivateNetwork=yes
+ProtectSystem=full
+RuntimeMaxSec=5min
[Unit]
Description=Journal Gateway Service
+Documentation=man:systemd-journal-gatewayd(8)
Requires=systemd-journal-gatewayd.socket
[Service]
[Unit]
Description=Journal Gateway Service Socket
+Documentation=man:systemd-journal-gatewayd(8)
[Socket]
ListenStream=19531
[Unit]
Description=Journal Remote Sink Service
+Documentation=man:systemd-journal-remote(8) man:journal-remote.conf(5)
Requires=systemd-journal-remote.socket
[Service]
[Unit]
Description=Journal Remote Upload Service
+Documentation=man:systemd-journal-upload(8)
After=network.target
[Service]
ExecStart=@rootlibexecdir@/systemd-journal-upload \
--save-state
User=systemd-journal-upload
+SupplementaryGroups=systemd-journal
PrivateTmp=yes
PrivateDevices=yes
WatchdogSec=3min
Slice=user-%i.slice
KillMode=mixed
Delegate=yes
+TasksMax=infinity