42
42
static int do_sort = 0;
43
43
struct timeval start_pcap = {0, 0};
44
44
static rbtree_t *filter_tree = NULL;
45
static pcap_dumper_t *pcap_dumper = NULL;
45
47
typedef int (*rbcmp)(const void *, const void *);
47
49
static int filter_packet(RADIUS_PACKET *packet)
163
165
#define USEC 1000000
164
static void tv_sub(struct timeval *end, struct timeval *start,
166
static void tv_sub(const struct timeval *end, const struct timeval *start,
165
167
struct timeval *elapsed)
167
169
elapsed->tv_sec = end->tv_sec - start->tv_sec;
200
202
args = args; /* -Wunused */
202
204
/* Define our packet's attributes */
203
ethernet = (const struct ethernet_header*)(data);
204
ip = (const struct ip_header*)(data + size_ethernet);
205
udp = (const struct udp_header*)(data + size_ethernet + size_ip);
206
payload = (const uint8_t *)(data + size_ethernet + size_ip + size_udp);
206
if ((data[0] == 2) && (data[1] == 0) &&
207
(data[2] == 0) && (data[3] == 0)) {
208
ip = (const struct ip_header*) (data + 4);
211
ethernet = (const struct ethernet_header*)(data);
212
ip = (const struct ip_header*)(data + size_ethernet);
214
udp = (const struct udp_header*)(((const uint8_t *) ip) + size_ip);
215
payload = (const uint8_t *)(((const uint8_t *) udp) + size_udp);
208
217
packet = malloc(sizeof(*packet));
220
229
packet->dst_port = ntohs(udp->udp_dport);
222
231
packet->data = payload;
223
packet->data_len = header->len - size_ethernet - size_ip - size_udp;
232
packet->data_len = header->len - (payload - data);
225
234
if (!rad_packet_ok(packet, 0)) {
235
printf("Packet: %s\n", fr_strerror());
228
fprintf(stderr, "\tFrom: %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
229
fprintf(stderr, "\tTo: %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
230
fprintf(stderr, "\tType: %s\n", fr_packet_codes[packet->code]);
237
printf("\tFrom: %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
238
printf("\tTo: %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
239
printf("\tType: %s\n", fr_packet_codes[packet->code]);
247
256
DEBUG("Packet number %d doesn't match\n", count++);
261
pcap_dump((void *) pcap_dumper, header, data);
250
265
printf("%s Id %d\t", fr_packet_codes[packet->code], packet->id);
252
267
/* Print the RADIUS packet */
290
306
fprintf(output, "options:\n");
291
307
fprintf(output, "\t-c count\tNumber of packets to capture.\n");
292
308
fprintf(output, "\t-d directory\tDirectory where the dictionaries are found\n");
293
fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813 or 1814)\n");
309
fprintf(output, "\t-F\t\tFilter PCAP file from stdin to stdout.\n");
310
fprintf(output, "\t\t\tOutput file will contain RADIUS packets.\n");
311
fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813)\n");
294
312
fprintf(output, "\t-h\t\tPrint this help message.\n");
295
313
fprintf(output, "\t-i interface\tInterface to capture.\n");
296
314
fprintf(output, "\t-I filename\tRead packets from filename.\n");
297
315
fprintf(output, "\t-m\t\tPrint packet headers only, not contents.\n");
298
fprintf(output, "\t-p port\tList for packets on port.\n");
316
fprintf(output, "\t-p port\t\tListen for packets on port.\n");
299
317
fprintf(output, "\t-r filter\tRADIUS attribute filter.\n");
300
318
fprintf(output, "\t-s secret\tRADIUS secret.\n");
301
fprintf(output, "\t-S\t\tSort attributes in the packet. Used to compare server results.\n");
319
fprintf(output, "\t-S\t\tSort attributes in the packet.\n");
320
fprintf(output, "\t\t\tUsed to compare server results.\n");
302
321
fprintf(output, "\t-x\t\tPrint out debugging information.\n");
315
334
char *pcap_filter = NULL;
316
335
char *radius_filter = NULL;
317
336
char *filename = NULL;
337
char *dump_file = NULL;
318
338
int packet_count = -1; /* how many packets to sniff */
320
340
FR_TOKEN parsecode;
321
341
const char *radius_dir = RADIUS_DIR;
343
int filter_stdin = 0;
324
345
/* Default device */
325
346
dev = pcap_lookupdev(errbuf);
327
348
/* Get options */
328
while ((opt = getopt(argc, argv, "c:d:f:hi:I:mp:r:s:SxX")) != EOF) {
349
while ((opt = getopt(argc, argv, "c:d:Ff:hi:I:mp:r:s:Sw:xX")) != EOF) {
405
* Cross-check command-line arguments.
407
if (filter_stdin && (filename || dump_file)) usage(1);
377
409
if (!pcap_filter) {
378
410
pcap_filter = buffer;
379
snprintf(buffer, sizeof(buffer), "udp port %d or %d or %d",
380
port, port + 1, port + 2);
383
if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
384
fr_perror("radsniff");
411
snprintf(buffer, sizeof(buffer), "udp port %d or %d",
416
* There are many times where we don't need the dictionaries.
418
if (fr_debug_flag || radius_filter) {
419
if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
420
fr_perror("radsniff");
388
425
if (radius_filter) {
389
426
parsecode = userparse(radius_filter, &filter_vps);
425
462
/* Open the device so we can spy */
427
464
descr = pcap_open_offline(filename, errbuf);
466
} else if (filter_stdin) {
467
descr = pcap_fopen_offline(stdin, errbuf);
470
fprintf(stderr, "radsniff: No filename or device was specified.\n");
429
descr = pcap_open_live(dev, SNAPLEN, 1, 0, errbuf);
474
descr = pcap_open_live(dev, 65536, 1, 0, errbuf);
431
476
if (descr == NULL)
433
printf("radsniff: pcap_open_live failed (%s)\n", errbuf);
478
fprintf(stderr, "radsniff: pcap_open_live failed (%s)\n", errbuf);
483
pcap_dumper = pcap_dump_open(descr, dump_file);
485
fprintf(stderr, "radsniff: Failed opening output file (%s)\n", pcap_geterr(descr));
488
} else if (filter_stdin) {
489
pcap_dumper = pcap_dump_fopen(descr, stdout);
491
fprintf(stderr, "radsniff: Failed opening stdout: %s\n", pcap_geterr(descr));
437
497
/* Apply the rules */
438
498
if( pcap_compile(descr, &fp, pcap_filter, 0, netp) == -1)
440
printf("radsniff: pcap_compile failed\n");
500
fprintf(stderr, "radsniff: pcap_compile failed\n");
443
503
if (pcap_setfilter(descr, &fp) == -1)
445
printf("radsniff: pcap_setfilter failed\n");
505
fprintf(stderr, "radsniff: pcap_setfilter failed\n");