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 FATAL("Malformed IPv4 address.");
44 if (a1
> 255 || a2
> 255 || a3
> 255 || a4
> 255)
45 FATAL("Malformed IPv4 address.");
55 /* Parse IPv6 address into a buffer. */
57 static void parse_addr6(char* str
, u8
* ret
) {
64 if (seg
== 8) FATAL("Malformed IPv6 address (too many segments).");
66 if (sscanf((char*)str
, "%x", &val
) != 1 ||
67 val
> 65535) FATAL("Malformed IPv6 address (bad octet value).");
69 ret
[seg
* 2] = val
>> 8;
70 ret
[seg
* 2 + 1] = val
;
74 while (isxdigit(*str
)) str
++;
79 if (seg
!= 8) FATAL("Malformed IPv6 address (don't abbreviate).");
84 int main(int argc
, char** argv
) {
89 static struct p0f_api_query q
;
90 static struct p0f_api_response r
;
92 static struct sockaddr_un sun
;
98 ERRORF("Usage: p0f-client /path/to/socket host_ip\n");
102 q
.magic
= P0F_QUERY_MAGIC
;
104 if (strchr(argv
[2], ':')) {
106 parse_addr6(argv
[2], q
.addr
);
107 q
.addr_type
= P0F_ADDR_IPV6
;
111 parse_addr4(argv
[2], q
.addr
);
112 q
.addr_type
= P0F_ADDR_IPV4
;
116 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
118 if (sock
< 0) PFATAL("Call to socket() failed.");
120 sun
.sun_family
= AF_UNIX
;
122 if (strlen(argv
[1]) >= sizeof(sun
.sun_path
))
123 FATAL("API socket filename is too long for sockaddr_un (blame Unix).");
125 strcpy(sun
.sun_path
, argv
[1]);
127 if (connect(sock
, (struct sockaddr
*)&sun
, sizeof(sun
)))
128 PFATAL("Can't connect to API socket.");
130 if (write(sock
, &q
, sizeof(struct p0f_api_query
)) !=
131 sizeof(struct p0f_api_query
)) FATAL("Short write to API socket.");
133 if (read(sock
, &r
, sizeof(struct p0f_api_response
)) !=
134 sizeof(struct p0f_api_response
)) FATAL("Short read from API socket.");
138 if (r
.magic
!= P0F_RESP_MAGIC
)
139 FATAL("Bad response magic (0x%08x).\n", r
.magic
);
141 if (r
.status
== P0F_STATUS_BADQUERY
)
142 FATAL("P0f did not understand the query.\n");
144 if (r
.status
== P0F_STATUS_NOMATCH
) {
145 SAYF("No matching host in p0f cache. That's all we know.\n");
151 strftime((char*)tmp
, 128, "%Y/%m/%d %H:%M:%S", t
);
153 SAYF("First seen = %s\n", tmp
);
157 strftime((char*)tmp
, 128, "%Y/%m/%d %H:%M:%S", t
);
159 // SAYF("Last update = %s\n", tmp);
161 // SAYF("Total flows = %u\n", r.total_conn);
164 SAYF("Detected OS = ???\n");
166 SAYF("Detected OS = %s %s%s%s\n", r
.os_name
, r
.os_flavor
,
167 (r
.os_match_q
& P0F_MATCH_GENERIC
) ? " [generic]" : "",
168 (r
.os_match_q
& P0F_MATCH_FUZZY
) ? " [fuzzy]" : "");
170 // if (!r.http_name[0])
171 // SAYF("HTTP software = ???\n");
173 // SAYF("HTTP software = %s %s (ID %s)\n", r.http_name, r.http_flavor,
174 // (r.bad_sw == 2) ? "is fake" : (r.bad_sw ? "OS mismatch" : "seems legit"));
176 // if (!r.link_type[0])
177 // SAYF("Network link = ???\n");
179 // SAYF("Network link = %s\n", r.link_type);
181 // if (!r.language[0])
182 // SAYF("Language = ???\n");
184 // SAYF("Language = %s\n", r.language);
187 // if (r.distance == -1)
188 // SAYF("Distance = ???\n");
190 // SAYF("Distance = %u\n", r.distance);
194 // t = localtime(&ut);
195 // strftime((char*)tmp, 128, "%Y/%m/%d %H:%M:%S", t);
196 // SAYF("IP sharing = %s\n", tmp);
201 // t = localtime(&ut);
202 // strftime((char*)tmp, 128, "%Y/%m/%d %H:%M:%S", t);
203 // SAYF("Sys change = %s\n", tmp);
206 // if (r.uptime_min) {
207 // SAYF("Uptime = %u days %u hrs %u min (modulo %u days)\n",
208 // r.uptime_min / 60 / 24, (r.uptime_min / 60) % 24, r.uptime_min % 60,