36
36
static const char *radius_secret = "testing123";
37
37
static VALUE_PAIR *filter_vps = NULL;
38
static int debug_flag = 0;
40
#define DEBUG if (debug_flag) printf
39
#define DEBUG if (fr_debug_flag) printf
42
static const char *packet_codes[] = {
48
"Accounting-Response",
64
"Resource-Free-Request",
65
"Resource-Free-Response",
66
"Resource-Query-Request",
67
"Resource-Query-Response",
68
"Alternate-Resource-Reclaim-Request",
70
"NAS-Reboot-Response",
93
"IP-Address-Allocate",
41
static int minimal = 0;
42
static int do_sort = 0;
43
struct timeval start_pcap = {0, 0};
44
static rbtree_t *filter_tree = NULL;
45
typedef int (*rbcmp)(const void *, const void *);
97
47
static int filter_packet(RADIUS_PACKET *packet)
118
70
if (fail == 0 && pass != 0) {
72
* Cache authentication requests, as the replies
73
* may not match the RADIUS filter.
75
if ((packet->code == PW_AUTHENTICATION_REQUEST) ||
76
(packet->code == PW_ACCOUNTING_REQUEST)) {
77
rbtree_deletebydata(filter_tree, packet);
79
if (!rbtree_insert(filter_tree, packet)) {
81
fprintf(stderr, "radsniff: Out of memory\n");
85
return 0; /* matched */
89
* Don't create erroneous matches.
91
if ((packet->code == PW_AUTHENTICATION_REQUEST) ||
92
(packet->code == PW_ACCOUNTING_REQUEST)) {
93
rbtree_deletebydata(filter_tree, packet);
98
* Else see if a previous Access-Request
99
* matched. If so, also print out the
100
* matching accept, reject, or challenge.
102
if ((packet->code == PW_AUTHENTICATION_ACK) ||
103
(packet->code == PW_AUTHENTICATION_REJECT) ||
104
(packet->code == PW_ACCESS_CHALLENGE) ||
105
(packet->code == PW_ACCOUNTING_RESPONSE)) {
106
RADIUS_PACKET *reply;
109
* This swaps the various fields.
111
reply = rad_alloc_reply(packet);
112
if (!reply) goto oom;
115
if (rbtree_finddata(filter_tree, reply)) {
129
static void sort(RADIUS_PACKET *packet)
132
VALUE_PAIR *vp, *tmp;
133
VALUE_PAIR *array[1024]; /* way more than necessary */
136
for (vp = packet->vps; vp != NULL; vp = vp->next) {
140
if (size == 0) return;
142
for (i = 0; i < size - 1; i++) {
143
for (j = 0; j < size - 1 - i; j++) {
144
if (array[j + 1]->attribute < array[j]->attribute) {
146
array[j] = array[j + 1];
153
* And put them back again.
155
vp = packet->vps = array[0];
156
for (i = 1; i < size; i++) {
164
static void tv_sub(struct timeval *end, struct timeval *start,
165
struct timeval *elapsed)
167
elapsed->tv_sec = end->tv_sec - start->tv_sec;
168
if (elapsed->tv_sec > 0) {
170
elapsed->tv_usec = USEC;
172
elapsed->tv_usec = 0;
174
elapsed->tv_usec += end->tv_usec;
175
elapsed->tv_usec -= start->tv_usec;
177
if (elapsed->tv_usec >= USEC) {
178
elapsed->tv_usec -= USEC;
125
183
static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *data)
127
185
/* Just a counter of how many packets we've had */
164
223
packet->data_len = header->len - size_ethernet - size_ip - size_udp;
166
225
if (!rad_packet_ok(packet, 0)) {
167
librad_perror("Packet");
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]);
175
239
if (rad_decode(packet, NULL, radius_secret) != 0) {
177
librad_perror("decode");
180
245
if (filter_vps && filter_packet(packet)) {
182
247
DEBUG("Packet number %d doesn't match\n", count++);
250
printf("%s Id %d\t", fr_packet_codes[packet->code], packet->id);
186
252
/* Print the RADIUS packet */
187
printf("Packet number %d has just been sniffed\n", count++);
188
printf("\tFrom: %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
189
printf("\tTo: %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
190
printf("\tType: %s\n", packet_codes[packet->code]);
191
if (packet->vps != NULL) {
253
printf("%s:%d -> ", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
254
printf("%s:%d", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
255
if (fr_debug_flag) printf("\t(%d packets)", count++);
257
if (!start_pcap.tv_sec) {
258
start_pcap = header->ts;
261
tv_sub(&header->ts, &start_pcap, &elapsed);
263
printf("\t+%u.%03u", (unsigned int) elapsed.tv_sec,
264
(unsigned int) elapsed.tv_usec / 1000);
265
if (!minimal) printf("\n");
266
if (!minimal && packet->vps) {
267
if (do_sort) sort(packet);
192
269
vp_printlist(stdout, packet->vps);
193
270
pairfree(&packet->vps);
276
* If we're doing filtering, Access-Requests are cached
277
* in the filter tree.
280
((packet->code != PW_AUTHENTICATION_REQUEST) &&
281
(packet->code != PW_ACCOUNTING_REQUEST))) {
199
286
static void NEVER_RETURNS usage(int status)
206
293
fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813 or 1814)\n");
207
294
fprintf(output, "\t-h\t\tPrint this help message.\n");
208
295
fprintf(output, "\t-i interface\tInterface to capture.\n");
296
fprintf(output, "\t-I filename\tRead packets from filename.\n");
297
fprintf(output, "\t-m\t\tPrint packet headers only, not contents.\n");
209
298
fprintf(output, "\t-p port\tList for packets on port.\n");
210
299
fprintf(output, "\t-r filter\tRADIUS attribute filter.\n");
211
300
fprintf(output, "\t-s secret\tRADIUS secret.\n");
212
fprintf(output, "\t-X\t\tPrint out debugging information.\n");
301
fprintf(output, "\t-S\t\tSort attributes in the packet. Used to compare server results.\n");
302
fprintf(output, "\t-x\t\tPrint out debugging information.\n");
282
383
if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
283
librad_perror("radsniff");
384
fr_perror("radsniff");
287
388
if (radius_filter) {
288
389
parsecode = userparse(radius_filter, &filter_vps);
289
390
if (parsecode == T_OP_INVALID) {
290
fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\": %s\n", optarg, librad_errstr);
391
fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\": %s\n", radius_filter, fr_strerror());
293
394
if (!filter_vps) {
294
fprintf(stderr, "radsniff: Empty RADIUS filter \"%s\"\n", optarg);
395
fprintf(stderr, "radsniff: Empty RADIUS filter \"%s\"\n", radius_filter);
399
filter_tree = rbtree_create((rbcmp) fr_packet_cmp,
402
fprintf(stderr, "radsniff: Failed creating filter tree\n");
300
408
pcap_lookupnet(dev, &netp, &maskp, errbuf);
302
410
/* Print device to the user */
303
printf("Device: [%s]\n", dev);
304
if (packet_count > 0) {
305
printf("Num of packets: [%d]\n", packet_count);
307
printf("PCAP filter: [%s]\n", pcap_filter);
308
if (filter_vps != NULL) {
309
printf("RADIUS filter:\n");
310
vp_printlist(stdout, filter_vps);
312
printf("RADIUS secret: [%s]\n", radius_secret);
412
if (dev) printf("Device: [%s]\n", dev);
413
if (packet_count > 0) {
414
printf("Num of packets: [%d]\n",
417
printf("PCAP filter: [%s]\n", pcap_filter);
419
printf("RADIUS filter:\n");
420
vp_printlist(stdout, filter_vps);
422
printf("RADIUS secret: [%s]\n", radius_secret);
314
425
/* Open the device so we can spy */
315
descr = pcap_open_live(dev, SNAPLEN, 1, 0, errbuf);
427
descr = pcap_open_offline(filename, errbuf);
429
descr = pcap_open_live(dev, SNAPLEN, 1, 0, errbuf);
316
431
if (descr == NULL)
318
433
printf("radsniff: pcap_open_live failed (%s)\n", errbuf);