6 #include <sys/socket.h>
10 #include <netinet/in.h>
13 #include <sys/types.h>
19 enum class P0fMagic
: uint32_t {
25 enum class P0fStatus
: uint32_t {
31 enum class P0fAddr
: uint8_t {
37 constexpr size_t P0F_STR_MAX
= 31;
39 constexpr auto P0F_MATCH_FUZZY
= 1;
40 constexpr auto P0F_MATCH_GENERIC
= 2;
42 struct p0f_api_query
{
44 P0fMagic
const magic
{P0fMagic::QUERY
};
45 P0fAddr addr_type
{P0fAddr::UNKNOWN
};
48 } __attribute__((packed
));
50 struct p0f_api_response
{
52 P0fMagic
const magic
{P0fMagic::UNKNOWN
};
53 P0fStatus status
{P0fStatus::BADQUERY
};
55 uint32_t first_seen
; // First seen (unix time)
56 uint32_t last_seen
; // Last seen (unix time)
57 uint32_t total_conn
; // Total connections seen
59 uint32_t uptime_min
; // Last uptime (minutes)
60 uint32_t up_mod_days
; // Uptime modulo (days)
62 uint32_t last_nat
; // NAT / LB last detected (unix time)
63 uint32_t last_chg
; // OS chg last detected (unix time)
65 int16_t distance
; // System distance
67 uint8_t bad_sw
; // Host is lying about U-A / Server
68 uint8_t os_match_q
; // Match quality
70 char os_name
[P0F_STR_MAX
+ 1]; // Name of detected OS
71 char os_flavor
[P0F_STR_MAX
+ 1]; // Flavor of detected OS
72 char http_name
[P0F_STR_MAX
+ 1]; // Name of detected HTTP app
73 char http_flavor
[P0F_STR_MAX
+ 1]; // Flavor of detected HTTP app
74 char link_type
[P0F_STR_MAX
+ 1]; // Link type
75 char language
[P0F_STR_MAX
+ 1]; // Language
77 } __attribute__((packed
));
79 int main(int argc
, char const* argv
[])
81 static_assert(sizeof(p0f_api_query
) == 21, "p0f_api_query wrong size");
82 static_assert(sizeof(p0f_api_response
) == 232, "p0f_api_response wrong size");
84 auto fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
85 PCHECK(fd
>= 0) << "socket() failed";
88 addr
.sun_family
= AF_UNIX
;
90 constexpr char socket_path
[]{"/run/p0f.sock"};
91 static_assert(sizeof(socket_path
) < sizeof(addr
.sun_path
));
92 strcpy(addr
.sun_path
, socket_path
);
94 PCHECK(connect(fd
, reinterpret_cast<struct sockaddr
*>(&addr
), sizeof(addr
))
96 << "p0f api connect() failed";
98 for (auto i
= 1; i
< argc
; ++i
) {
99 if (IP4::is_address(argv
[i
])) {
101 p0f_api_query query_msg
;
103 if (inet_pton(AF_INET
, argv
[i
], reinterpret_cast<void*>(&query_msg
.addr
))
105 query_msg
.addr_type
= P0fAddr::IPV4
;
107 PCHECK(write(fd
, reinterpret_cast<void const*>(&query_msg
),
109 == sizeof(query_msg
))
110 << "p0f api write() failed";
112 p0f_api_response response_msg
;
114 PCHECK(read(fd
, reinterpret_cast<void*>(&response_msg
),
115 sizeof(response_msg
))
116 == sizeof(response_msg
))
117 << "p0f api read() failed";
119 CHECK(response_msg
.magic
== P0fMagic::RESP
);
121 switch (response_msg
.status
) {
122 case P0fStatus::BADQUERY
:
123 LOG(ERROR
) << "bad query";
126 std::cout
<< "os_match_q == "
127 << static_cast<int>(response_msg
.os_match_q
) << "\n";
128 std::cout
<< "os_name == " << response_msg
.os_name
<< "\n";
129 std::cout
<< "os_flavor == " << response_msg
.os_flavor
<< "\n";
131 case P0fStatus::NOMATCH
:
132 LOG(ERROR
) << "no match";
139 PCHECK(close(fd
) == 0) << "p0f api close failed";