2 p0f-client - simple API client
3 ------------------------------
5 Can be used to query p0f API sockets.
7 Copyright (C) 2012 by Michal Zalewski <lcamtuf@coredump.cx>
9 Distributed under the terms and conditions of GNU LGPL.
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <sys/types.h>
26 #include <sys/socket.h>
30 #include "../config.h"
31 #include "../alloc-inl.h"
35 /* Parse IPv4 address into a buffer. */
37 static void parse_addr4(char* str
, u8
* ret
) {
41 if (sscanf(str
, "%u.%u.%u.%u", &a1
, &a2
, &a3
, &a4
) != 4) {
42 SAYF("Malformed IPv4 address.");
46 if (a1
> 255 || a2
> 255 || a3
> 255 || a4
> 255) {
47 SAYF("Malformed IPv4 address.");
59 /* Parse IPv6 address into a buffer. */
61 static void parse_addr6(char* str
, u8
* ret
) {
63 int8_t r
= inet_pton(AF_INET6
, str
, &ip
);
65 SAYF("parse_addr6: error while converting IPv6 address to binary format: %s", strerror(errno
));
68 SAYF("parse_addr6: passed invalid IPv6 address");
76 int main(int argc
, char** argv
) {
81 static struct p0f_api_query q
;
82 static struct p0f_api_response r
;
84 static struct sockaddr_un sun
;
90 ERRORF("Usage: p0f-client /path/to/socket host_ip\n");
94 q
.magic
= P0F_QUERY_MAGIC
;
96 if (strchr(argv
[2], ':')) {
98 parse_addr6(argv
[2], q
.addr
);
99 q
.addr_type
= P0F_ADDR_IPV6
;
103 parse_addr4(argv
[2], q
.addr
);
104 q
.addr_type
= P0F_ADDR_IPV4
;
108 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
111 SAYF("Call to socket() failed.");
115 sun
.sun_family
= AF_UNIX
;
117 if (strlen(argv
[1]) >= sizeof(sun
.sun_path
)) {
118 SAYF("API socket filename is too long for sockaddr_un (blame Unix).");
122 strcpy(sun
.sun_path
, argv
[1]);
124 if (connect(sock
, (struct sockaddr
*)&sun
, sizeof(sun
))) {
125 SAYF("Can't connect to API socket.");
129 if (write(sock
, &q
, sizeof(struct p0f_api_query
)) !=
130 sizeof(struct p0f_api_query
)) {
131 SAYF("Short write to API socket.");
135 if (read(sock
, &r
, sizeof(struct p0f_api_response
)) !=
136 sizeof(struct p0f_api_response
)) {
137 SAYF("Short read from API socket.");
142 if (r
.magic
!= P0F_RESP_MAGIC
) {
143 SAYF("Bad response magic (0x%08x).\n", r
.magic
);
147 if (r
.status
== P0F_STATUS_BADQUERY
) {
148 SAYF("P0f did not understand the query.\n");
152 if (r
.status
== P0F_STATUS_NOMATCH
) {
153 SAYF("No matching host in p0f cache. That's all we know.\n");
159 strftime((char*)tmp
, 128, "%Y/%m/%d %H:%M:%S", t
);
161 // SAYF("First seen = %s\n", tmp);
165 strftime((char*)tmp
, 128, "%Y/%m/%d %H:%M:%S", t
);
167 // SAYF("Last update = %s\n", tmp);
169 // SAYF("Total flows = %u\n", r.total_conn);
172 SAYF("Genre and OS details not recognized.");
174 SAYF("%s %s%s%s", r
.os_name
, r
.os_flavor
,
175 (r
.os_match_q
& P0F_MATCH_GENERIC
) ? " [generic]" : "",
176 (r
.os_match_q
& P0F_MATCH_FUZZY
) ? " [fuzzy]" : "");
178 // if (!r.http_name[0])
179 // SAYF("HTTP software = ???\n");
181 // SAYF("HTTP software = %s %s (ID %s)\n", r.http_name, r.http_flavor,
182 // (r.bad_sw == 2) ? "is fake" : (r.bad_sw ? "OS mismatch" : "seems legit"));
184 // if (!r.link_type[0])
185 // SAYF("Network link = ???\n");
187 // SAYF("Network link = %s\n", r.link_type);
189 // if (!r.language[0])
190 // SAYF("Language = ???\n");
192 // SAYF("Language = %s\n", r.language);
195 // if (r.distance == -1)
196 // SAYF("Distance = ???\n");
198 // SAYF("Distance = %u\n", r.distance);
202 // t = localtime(&ut);
203 // strftime((char*)tmp, 128, "%Y/%m/%d %H:%M:%S", t);
204 // SAYF("IP sharing = %s\n", tmp);
209 // t = localtime(&ut);
210 // strftime((char*)tmp, 128, "%Y/%m/%d %H:%M:%S", t);
211 // SAYF("Sys change = %s\n", tmp);
214 // if (r.uptime_min) {
215 // SAYF("Uptime = %u days %u hrs %u min (modulo %u days)\n",
216 // r.uptime_min / 60 / 24, (r.uptime_min / 60) % 24, r.uptime_min % 60,