<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Carvilsi [Char]</title>
    <description>The latest articles on DEV Community by Carvilsi [Char] (@carvilsi).</description>
    <link>https://dev.to/carvilsi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F840145%2F7f7f7c17-f034-4ad5-95ba-f5933e1dff95.jpeg</url>
      <title>DEV Community: Carvilsi [Char]</title>
      <link>https://dev.to/carvilsi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/carvilsi"/>
    <language>en</language>
    <item>
      <title>CanaryUsb</title>
      <dc:creator>Carvilsi [Char]</dc:creator>
      <pubDate>Sat, 09 Sep 2023 16:48:52 +0000</pubDate>
      <link>https://dev.to/carvilsi/canaryusb-55dc</link>
      <guid>https://dev.to/carvilsi/canaryusb-55dc</guid>
      <description>&lt;h2&gt;
  
  
  Introducing Canary Tokens
&lt;/h2&gt;

&lt;p&gt;Some time ago I found &lt;a href="https://canary.tools"&gt;Thinkst Canary&lt;/a&gt; and I fall in love with it. &lt;/p&gt;

&lt;p&gt;It's already well know but, the idea behind &lt;strong&gt;Canary Tokens&lt;/strong&gt; is to have a notification if you have security breach. The notification is via email, and you have different types of tokens, these will trigger a notification under certain situation, for example a &lt;strong&gt;URL token&lt;/strong&gt; will be triggered when a URL is visited.&lt;/p&gt;

&lt;p&gt;One of my favorites is the QR code token, it's meant for physical things; e.g. You can stick the QR code inside of your prototype case, and if someone scans it, at least you know that someone is snooping around.&lt;/p&gt;

&lt;p&gt;Just want to mention, that when you create a new Canary Token, apart of email, where you want to receive the notification, you need to provide a &lt;em&gt;reminder note&lt;/em&gt; to describe the token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F488wih5y7dq8gjmi33eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F488wih5y7dq8gjmi33eg.png" alt="QR code token creation" width="800" height="369"&gt;&lt;/a&gt;    &lt;/p&gt;

&lt;p&gt;You can check the different types of Canary tokens that &lt;a href="https://canarytokens.org/generate#"&gt;Thinkst Canary&lt;/a&gt; have, and they explain all the things better than me.&lt;/p&gt;

&lt;h2&gt;
  
  
  CanaryUsb
&lt;/h2&gt;

&lt;p&gt;So now that we now about CanaryTokens; Lets see what CanaryUsb is.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is it?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/carvilsi/canaryusb"&gt;CanaryUsb&lt;/a&gt; monitors the USB activity on a Linux system, and will call a CanaryToken when a not known USB is connected.&lt;/p&gt;

&lt;p&gt;Here we are thinking about &lt;strong&gt;removable media threats&lt;/strong&gt; like &lt;strong&gt;BadUSB&lt;/strong&gt; or physical attacks to &lt;strong&gt;extract data&lt;/strong&gt; e.g. on remote servers or on unattended laptops.&lt;/p&gt;

&lt;p&gt;The code is in &lt;strong&gt;c&lt;/strong&gt; and right now, and unless someone borrow me a Mac, &lt;strong&gt;canaryusb&lt;/strong&gt; only works on Linux (is not even an idea to support Windows).&lt;/p&gt;

&lt;h3&gt;
  
  
  The DNS Canary token
&lt;/h3&gt;

&lt;p&gt;CanaryUsb uses a CanaryToken of type &lt;strong&gt;DNS token&lt;/strong&gt; that &lt;em&gt;alerts when a hostname is requested&lt;/em&gt;. As it's described at the &lt;a href="https://docs.canarytokens.org/guide/dns-token.html#encoding-additional-information-in-your-token"&gt;DNS token Documentation&lt;/a&gt; one of the features is that the token can carry a small extra data.&lt;br&gt;
This is used by canaryusb to send the &lt;em&gt;fingerprint&lt;/em&gt; of the connected usb; so the notification via mail will include this info.&lt;/p&gt;
&lt;h3&gt;
  
  
  A USB fingerprint
&lt;/h3&gt;

&lt;p&gt;Since the total number of bytes that could be included among the DNS token is &lt;strong&gt;~125 bytes&lt;/strong&gt;, we need to restrict the amount of data that we take from from USB attributes.&lt;br&gt;
We choose the next format for the usb fingerprint:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;vendor&amp;gt;:&amp;lt;product&amp;gt;-&amp;lt;product_name&amp;gt;-&amp;lt;serial&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;e.g. for a USB with the next attributes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vendor&lt;/strong&gt;: 18d1&lt;br&gt;
&lt;strong&gt;product&lt;/strong&gt;: 4ee8&lt;br&gt;
&lt;strong&gt;product name&lt;/strong&gt;: OnePlus Nord&lt;br&gt;
&lt;strong&gt;serial&lt;/strong&gt;: d3115c34&lt;/p&gt;

&lt;p&gt;The USB fingerprint will be: &lt;strong&gt;18d1:4ee8-OnePlus_Nord-d3115c34&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The struct that holds the &lt;em&gt;usb fingerprint&lt;/em&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;syspath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;UsbAttrs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;em&gt;syspath&lt;/em&gt; variable is there just for debugging pourposes and it's not used to define the &lt;em&gt;usb fingerptint&lt;/em&gt;.&lt;br&gt;
We initialize this struct as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;UsbAttrs&lt;/span&gt; &lt;span class="n"&gt;usbattr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"no-path"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we fill the gaps in case of a missing attribute.&lt;br&gt;
It's not guaranteed that the 4 attributes which with we want to build the &lt;em&gt;usb fingerprint&lt;/em&gt; will be present.&lt;/p&gt;
&lt;h3&gt;
  
  
  Monitoring the USB devices
&lt;/h3&gt;

&lt;p&gt;The USB attributes, to build the &lt;em&gt;usb fingerprint&lt;/em&gt;, are retrieved with &lt;strong&gt;libsystemd&lt;/strong&gt;, specifically usage of &lt;a href="https://man.archlinux.org/man/sd-device.3.en"&gt;sd-device&lt;/a&gt; and monitoring the USB devices activity.&lt;/p&gt;

&lt;p&gt;The monitor code is quite brief; failure handling and finishing actions are omitted for brevity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;monitor_usb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sd_device_monitor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;sd_device_monitor_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;sd_device_monitor_filter_add_match_subsystem_devtype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SUBSYSTEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEVICE_TYPE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;sd_device_monitor_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usb_monitor_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;sd_event&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_device_monitor_get_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sd_event_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="cm"&gt;/*
         * Deal with errors and exit actions
         * like stooping monitor and un-references
         */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the event is triggered the handler function, &lt;strong&gt;usb_monitor_handler&lt;/strong&gt;, takes care of the rest; retrieve the USB attributes to build the the &lt;em&gt;usb fingerprint&lt;/em&gt;, build the &lt;em&gt;DNS Canary Token&lt;/em&gt; and perform the DNS call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the DNS Canary Token
&lt;/h3&gt;

&lt;p&gt;We need to convert the &lt;em&gt;usb fingerprint&lt;/em&gt; into &lt;strong&gt;base32&lt;/strong&gt; removing the padding '=' characters adding a dot after every 63-bytes and prepare the hostname call for DNS token, from the &lt;a href="https://docs.canarytokens.org/guide/dns-token.html#encoding-additional-information-in-your-token"&gt;Documentation&lt;/a&gt; is something like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;base32-string&amp;gt;.&amp;lt;base32-string&amp;gt;.G&amp;lt;2-random-digits&amp;gt;.&amp;lt;dns-token&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also we'll strip the &lt;em&gt;usb fingerprint&lt;/em&gt; if the length exceeds the maximum data to encode; 63 bytes for each &lt;em&gt;base32-string&lt;/em&gt; block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling the Canary
&lt;/h3&gt;

&lt;p&gt;Once we have the DNS Canary Token, we just need to call it, using &lt;em&gt;getaddrinfo&lt;/em&gt; (netdb.h):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;call_the_canary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;canary_dns_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;canaryrsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;addrinfo&lt;/span&gt; &lt;span class="n"&gt;hints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hints&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;canaryrsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getaddrinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canary_dns_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CANARY_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;canaryrsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameter &lt;em&gt;canary_dns_token&lt;/em&gt; it's the value that we get on previous step, and for &lt;em&gt;CANARY_PORT&lt;/em&gt; we use 80.&lt;br&gt;
We do not care about the response, variable &lt;em&gt;res&lt;/em&gt; of &lt;em&gt;getaddrinfo&lt;/em&gt; but the return integer of it, a nonzero means an error.&lt;/p&gt;

&lt;p&gt;Here you can see the notification that I received from the above example of &lt;em&gt;usb fingerprint&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwhgqbvtcxf9qz61zt8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwhgqbvtcxf9qz61zt8x.png" alt="Image description" width="608" height="835"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Some other things
&lt;/h3&gt;

&lt;p&gt;In order to avoid notifications from your own devices, &lt;em&gt;canaryusb&lt;/em&gt; supports a &lt;em&gt;usb trusted list&lt;/em&gt;, so only the devices that are not at this list will send a notification.&lt;br&gt;
To make the life easer &lt;em&gt;canaryusb&lt;/em&gt; could read values for the &lt;em&gt;CanaryToken&lt;/em&gt; and the &lt;em&gt;usb fingerprint trusted list&lt;/em&gt; from a config file. The format of the config file is &lt;strong&gt;toml&lt;/strong&gt; and I found very useful &lt;a href="https://github.com/cktan/tomlc99"&gt;tomlc99&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>c</category>
      <category>security</category>
      <category>usb</category>
      <category>linux</category>
    </item>
    <item>
      <title>Linux; monitor USB devices; libudev replacement with sd-device</title>
      <dc:creator>Carvilsi [Char]</dc:creator>
      <pubDate>Sat, 09 Sep 2023 11:09:42 +0000</pubDate>
      <link>https://dev.to/carvilsi/linux-monitor-usb-devices-libudev-replacement-with-sd-device-3n4d</link>
      <guid>https://dev.to/carvilsi/linux-monitor-usb-devices-libudev-replacement-with-sd-device-3n4d</guid>
      <description>&lt;h2&gt;
  
  
  Some context
&lt;/h2&gt;

&lt;p&gt;Recently I was writing a post related with a c &lt;a href="https://github.com/carvilsi/canaryusb"&gt;project&lt;/a&gt; to monitor and send notifications when a unknown &lt;strong&gt;USB device&lt;/strong&gt; is connected to a Linux system and just notice that the library that I was using, &lt;a href="https://man.archlinux.org/man/libudev.3.en"&gt;libudev&lt;/a&gt; even still supported but should not be used in new projects. The &lt;a href="https://github.com/carvilsi/canaryusb"&gt;project&lt;/a&gt; is quite new, so I started to update it in order to use the equivalent replacement with a more modern API; &lt;a href="https://man.archlinux.org/man/sd-device.3.en"&gt;sd-device&lt;/a&gt; that is part of &lt;strong&gt;libsystemd&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sd-device.h is part of libsystemd(3) and provides an API to introspect and enumerate devices on the local system. It provides a programmatic interface to the database of devices and their properties mananaged by systemd-udevd.service(8). This API is a replacement for libudev(3) and libudev.h.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The case is that the replacement took me more effort than I expected, almost all the concepts still the same, but there are some changes. &lt;/p&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/carvilsi/systemd-usb-monitor-example"&gt;code&lt;/a&gt; is just a simple example that reads some values of a new connected USB to a Linux system.&lt;br&gt;
It's written in &lt;strong&gt;C&lt;/strong&gt; and uses two components from &lt;em&gt;libsystemd&lt;/em&gt; &lt;a href="https://man.archlinux.org/man/sd-device.3.en"&gt;sd-device&lt;/a&gt; and &lt;a href="https://man.archlinux.org/man/sd-event.3.en"&gt;sd-event&lt;/a&gt; that we include with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;systemd/sd-event.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;systemd/sd-device.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then at the &lt;em&gt;main&lt;/em&gt; block we have the part for monitor the device and deal with the events. Despite failure handling and related stop actions, these are the basic steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;create a new monitor device&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_device_monitor_new(sd_device_monitor **ret);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;add a filter that will match by &lt;em&gt;subsystem&lt;/em&gt; and &lt;em&gt;device type&lt;/em&gt;, for our purpose will use "usb" and "usb_device" respectively. With the second value for device type we restrict the amount of triggers for the monitor, e.g. if we do not specify (NULL) we'll be catching also the "usb_interface" related with the device.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;start the monitor, passing as parameter a handler function, to react when the filter will be triggered. We'll take a look to this handler later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;get the event for this device monitor&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sd_event *sd_device_monitor_get_event(sd_device_monitor *m);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;start the event loop. Run the event in loop mode, &lt;em&gt;sd_event_run()&lt;/em&gt;, waiting for a &lt;em&gt;sd_event_exit()&lt;/em&gt; or a &lt;strong&gt;SIGTERM&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_event_loop(sd_event *e);&lt;/code&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice that both, &lt;em&gt;sd-event&lt;/em&gt; and &lt;em&gt;sd-device&lt;/em&gt; return a negative errno-style error code.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;main&lt;/em&gt; function is something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;sd_device_monitor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// create a new monitor device&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_device_monitor_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// check for errors, sd-device functions returns negative values on errors&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// we would like to monitor USB activity&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_device_monitor_filter_add_match_subsystem_devtype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"usb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"usb_device"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// start monitoring and attach a handler function to it&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_device_monitor_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;monitor_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// get the event related with device monitor&lt;/span&gt;
        &lt;span class="n"&gt;sd_event&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_device_monitor_get_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// starts the event loop&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sd_event_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;finish:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error: %m&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// stop and unref monitor and event&lt;/span&gt;
        &lt;span class="n"&gt;sd_device_monitor_stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sd_device_monitor_unref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sddm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sd_event_unref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;About the &lt;strong&gt;monitor handler function&lt;/strong&gt;, with this signature:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;typedef int (*sd_device_monitor_handler_t)(sd_device_monitor *m, sd_device *device, void *userdata);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It's main purpose is to print values of the connected USB device, and has a condition in order to only print the values when the action from the device is &lt;em&gt;SD_DEVICE_ADD&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The list for different actions are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;sd_device_action_t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_ADD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_REMOVE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_CHANGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_MOVE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_ONLINE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_OFFLINE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_BIND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;SD_DEVICE_UNBIND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;_SD_DEVICE_ACTION_MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;_SD_DEVICE_ACTION_INVALID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;EINVAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;_SD_ENUM_FORCE_S64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEVICE_ACTION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;sd_device_action_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to retrieve the action inside the monitor handler we use:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_device_get_action(sd_device *device, sd_device_action_t *ret);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And to retrieve e.g. the &lt;em&gt;idVendor&lt;/em&gt; value of the device we use, passing "idVendor" as &lt;em&gt;sysattr&lt;/em&gt; parameter:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;id_vendor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;sd_device_get_sysattr_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"idVendor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id_vendor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"idVendor: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_vendor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole example is available at &lt;a href="https://github.com/carvilsi/systemd-usb-monitor-example"&gt;GitHub&lt;/a&gt; in case that you want to take a look or run it on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;I tried the code on a Arch Linux and on a Ubuntu lunar (23.04) and for this one I needed to install &lt;em&gt;libsystemd-dev&lt;/em&gt;; seems that Arc Linux has the package already installed.&lt;/p&gt;

&lt;p&gt;If you want to install the package on Ubuntu lunar:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install libsystemd-dev&lt;/code&gt; &lt;/p&gt;

</description>
      <category>c</category>
      <category>linux</category>
      <category>usb</category>
      <category>monitoring</category>
    </item>
  </channel>
</rss>
