2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 * Copyright (C) 2020 embedd.ch
16 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
17 * Copyright (C) 2020 John Crispin <john@phrozen.org>
20 #include <netinet/udp.h>
21 #include <arpa/inet.h>
24 #include <pcap/pcap.h>
26 #include <libubox/blobmsg_json.h>
32 static int pkt_offset
;
36 uint8_t ip_vhl
; /* version << 4 | header length >> 2 */
37 uint8_t ip_tos
; /* type of service */
38 uint16_t ip_len
; /* total length */
39 uint16_t ip_id
; /* identification */
40 uint16_t ip_off
; /* fragment offset field */
41 #define IP_RF 0x8000 /* reserved fragment flag */
42 #define IP_DF 0x4000 /* dont fragment flag */
43 #define IP_MF 0x2000 /* more fragments flag */
44 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
45 uint8_t ip_ttl
; /* time to live */
46 uint8_t ip_p
; /* protocol */
47 uint16_t ip_sum
; /* checksum */
48 struct in_addr ip_src
, ip_dst
; /* source and dest address */
50 #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
51 #define IP_V(ip) (((ip)->ip_vhl) >> 4)
54 uint16_t uh_sport
; /* source port */
55 uint16_t uh_dport
; /* destination port */
56 uint16_t uh_ulen
; /* udp length */
57 uint16_t uh_sum
; /* udp checksum */
62 decode_sta(struct blob_attr
*data
)
66 if (!parse_apmsg_sta(&msg
, data
))
69 fprintf(stderr
, "\t\tSta "MAC_ADDR_FMT
" signal=%d connected=%d timeout=%d\n",
70 MAC_ADDR_DATA(msg
.addr
), msg
.signal
, msg
.connected
, msg
.timeout
);
74 decode_node(struct blob_attr
*data
)
76 struct apmsg_node msg
;
77 struct blob_attr
*cur
;
80 if (!parse_apmsg_node(&msg
, data
))
83 fprintf(stderr
, "\tNode %s, freq=%d, n_assoc=%d, noise=%d load=%d max_assoc=%d\n",
84 msg
.name
, msg
.freq
, msg
.n_assoc
, msg
.noise
, msg
.load
, msg
.max_assoc
);
86 fprintf(stderr
, "\t\tRRM:");
87 blobmsg_for_each_attr(cur
, msg
.rrm_nr
, rem
) {
88 if (!blobmsg_check_attr(cur
, false))
90 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
92 fprintf(stderr
, " %s", blobmsg_get_string(cur
));
94 fprintf(stderr
, "\n");
97 if (msg
.script_data
) {
98 char *data
= blobmsg_format_json(msg
.script_data
, true);
99 fprintf(stderr
, "\t\tScript data: %s\n", data
);
103 blob_for_each_attr(cur
, msg
.stations
, rem
)
108 decode_packet(struct blob_attr
*data
)
111 struct blob_attr
*cur
;
114 if (!parse_apmsg(&msg
, data
)) {
115 fprintf(stderr
, "missing fields\n");
119 fprintf(stderr
, "id=%08x, seq=%d\n", msg
.id
, msg
.seq
);
121 blob_for_each_attr(cur
, msg
.nodes
, rem
)
126 recv_packet(unsigned char *user
, const struct pcap_pkthdr
*hdr
,
127 const unsigned char *packet
)
129 char addr
[INET_ADDRSTRLEN
];
130 struct ip_header
*ip
;
131 struct udp_header
*uh
;
132 struct blob_attr
*data
;
133 int len
= hdr
->caplen
;
137 packet
+= pkt_offset
;
138 ip
= (void *) packet
;
140 hdrlen
= IP_HL(ip
) * 4;
141 if (hdrlen
< 20 || hdrlen
>= len
)
147 inet_ntop(AF_INET
, &ip
->ip_src
, addr
, sizeof(addr
));
149 hdrlen
= sizeof(*uh
);
153 uh
= (void *) packet
;
157 if (uh
->uh_dport
!= htons(APMGR_PORT
))
160 data
= (void *) packet
;
162 fprintf(stderr
, "[%s]: len=%d ", addr
, len
);
164 if (len
!= blob_pad_len(data
)) {
165 fprintf(stderr
, "invalid data\n");
172 int main(int argc
, char **argv
)
174 static char errbuf
[PCAP_ERRBUF_SIZE
];
175 struct bpf_program fp
;
178 fprintf(stderr
, "Usage: %s <interface>\n", argv
[0]);
182 pcap
= pcap_open_live(argv
[1], APMGR_BUFLEN
, 1, 1000, errbuf
);
184 fprintf(stderr
, "Failed to open interface %s: %s\n", argv
[1], errbuf
);
188 pcap_compile(pcap
, &fp
, "port "APMGR_PORT_STR
, 1, PCAP_NETMASK_UNKNOWN
);
189 pcap_setfilter(pcap
, &fp
);
191 switch (pcap_datalink(pcap
)) {
199 fprintf(stderr
, "Invalid link type\n");
203 pcap_loop(pcap
, 0, recv_packet
, NULL
);