~ubuntu-branches/ubuntu/oneiric/cdpr/oneiric

« back to all changes in this revision

Viewing changes to cdpr.c

  • Committer: Bazaar Package Importer
  • Author(s): Lukas Fittl
  • Date: 2006-09-28 12:59:22 UTC
  • Revision ID: james.westby@ubuntu.com-20060928125922-ifqnugsv5unc4iiz
Tags: upstream-2.2.1
ImportĀ upstreamĀ versionĀ 2.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* cdpr - Cisco Discovery Protocol Reporter
 
3
* Copyright (c) 2002-2006 MonkeyMental.com
 
4
*
 
5
* This program will show you which Cisco device your machine is
 
6
* connected to based on CDP packets received.
 
7
*
 
8
* This program is free software; you can redistribute it and/or
 
9
* modify it under the terms of the GNU General Public License
 
10
* as published by the Free Software Foundation; either version 2
 
11
* of the License, or (at your option) any later version.
 
12
*
 
13
* This program is distributed in the hope that it will be useful,
 
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
* GNU General Public License for more details.
 
17
*
 
18
* You should have received a copy of the GNU General Public License
 
19
* along with this program; if not, write to the Free Software
 
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
21
*
 
22
* Version History:
 
23
*
 
24
* 1.0.0 LO      02-06-30        Initial Release
 
25
* 1.0.1 LO      02-07-01        ifdef/endif DLT types to deal with older bpf.h headers
 
26
* 1.0.2 LO      02-07-02        New filter to better identify CDP packets
 
27
* 1.0.3 LO      02-07-03        loop on pcap_next until a valid packet is received.
 
28
*                                               (patch provided Martin Buck <martin.buck@ascom.ch>)
 
29
* 1.0.4 LO      02-07-10        Added 1ms timeout to pcap_open_live to fix *BSD
 
30
* 1.0.5 LO      02-07-14        Copy packet data to local struct to resolve Bus Errors
 
31
*                                               on Sun machines.
 
32
* 1.0.6 LO      02-07-15        More alignment fixes.
 
33
* 1.0.7 LO      02-10-29        Port to Win32, autodetection and list generation of
 
34
*                                               PCAP capable devices.
 
35
* 1.0.8 LO      03-02-13        Port to arm processor (Zaurus) using a filter specific
 
36
*                                               to arm processors to work around pcap bug
 
37
* 1.1.0 LO      03-04-25        Add central server reporting code
 
38
* 1.1.1 LO      03-04-26        Fix compile errors for Win32 on server code
 
39
* 1.1.2 LO      03-04-27        Add config file support
 
40
* 1.1.3 LO      03-04-28        Add location/description flag for extended info on server
 
41
*                                               Split server code and conf file code into seperate source files
 
42
*                                               Cleanup old server/config file code. Remove cond. compile for CDPRS
 
43
*                                               Create cdpr.h for ext. functions and common defines.
 
44
*                                               Add DNS support to the config file so you can specify a hostname
 
45
* 1.1.4 LO      03-06-20        Added -n flag to override hostname sent to server. Added error
 
46
*                                               checking to the socket code.
 
47
* 1.1.5 LO      03-06-23        Fix bug where hostname would not be transmitted w/o location set
 
48
* 2.0.0 LO      03-06-25        Release - Major revision change due to server reporting code
 
49
* 2.0.1 LO      03-07-01        Add sys/types.h to the includes in conffile.c for BSD support
 
50
* 2.0.2 LO      03-08-03        Enable timeouts so that cdpr won't wait forever looking for a packet
 
51
* 2.0.3 LO      03-08-04        Better cleanup after aborting due to timeout. 
 
52
* 2.0.4 LO      03-08-05        Timeout code that actually timesout. Set device to nonblocking
 
53
*                                               mode and loop until packet or timeout. Before, pcap_next would
 
54
*                                               block so the signal handler couldn't acutally exit.
 
55
* 2.0.5 LO      03-10-22        Went back to pcap_next() to get the packet, add a default timeout
 
56
*                                               of 5 minutes. Got rid of pktcap.c and timeout.c as they are no
 
57
*                                               longer needed.
 
58
* 2.1.0 LO      03-11-08        Release - Got timeout code working on WIN32 port
 
59
* 2.2.0 LO      04-04-14        Added the ability specify the port to send the cdpr updates to.
 
60
* 2.2.1 LO      06-07-28        Fixed segfault when not providing port to a command line selected server (-s)
 
61
*/
 
62
 
 
63
/*#include "pcap.h" */
 
64
#include <stdio.h>
 
65
#include <stdlib.h>
 
66
#include <string.h>
 
67
#include <time.h>
 
68
#ifdef WIN32
 
69
#include "xgetopt.h"
 
70
#include "time.h"
 
71
#else
 
72
#include <unistd.h>
 
73
#endif
 
74
#ifdef SOLARIS
 
75
#include "u_ints.h"
 
76
#endif
 
77
#include "cdpr.h"
 
78
#include "cdp.h"
 
79
 
 
80
void
 
81
dump_ip (const u_char *ip)
 
82
{
 
83
        char switch_ip[100];
 
84
        if(cdprs>=1)
 
85
        {
 
86
                sprintf (switch_ip, "switch_ip=%d.%d.%d.%d",
 
87
                        (int) ip[0], (int) ip[1], (int) ip[2], (int) ip[3]);
 
88
                cdprs_action(CDPRS_DATA, switch_ip, 0);
 
89
        }
 
90
        printf ("%d.%d.%d.%d",
 
91
                (int) ip[0], (int) ip[1], (int) ip[2], (int) ip[3]);
 
92
}
 
93
 
 
94
void
 
95
dump_hex (const u_char *p, int len)
 
96
{
 
97
        while (len--)
 
98
        {
 
99
                printf ("%02X ", *p++);
 
100
        }
 
101
}
 
102
 
 
103
void
 
104
dump_ascii (const u_char *p, int len)
 
105
{
 
106
        while (len--)
 
107
        {
 
108
                printf ("%c", (*p < ' ' || *p > '~') ? '.' : *p);
 
109
                ++p;
 
110
        }
 
111
}
 
112
 
 
113
void
 
114
dump_data (const u_char *p, int len)
 
115
{
 
116
        int i;
 
117
 
 
118
        for (i = 0; i < len; i += 16, p += 16)
 
119
        {
 
120
                printf ("%p:  ", p);
 
121
                dump_hex (p, 16);
 
122
                printf (" ");
 
123
                dump_ascii (p, 16);
 
124
                printf ("\n");
 
125
        }
 
126
}
 
127
char *
 
128
get_cdp_type (int type)
 
129
{
 
130
    int i;
 
131
 
 
132
    for (i = 0; type_vals[i].type != 0; ++i)
 
133
    {
 
134
        if (type == type_vals[i].type)
 
135
        {
 
136
                return type_vals[i].val;
 
137
        }
 
138
    }
 
139
    return "Unknown type";
 
140
}
 
141
 
 
142
void
 
143
print_cdp_address (u_char *v, int verbose)
 
144
{
 
145
        u_int32_t i;
 
146
        u_int32_t number;
 
147
 
 
148
        memcpy (&number, v, sizeof (number));
 
149
        number = ntohl (number);
 
150
 
 
151
        if (verbose > 0)
 
152
        {
 
153
                printf ("  number: %d\n", number);
 
154
        }
 
155
 
 
156
        v += sizeof (u_int32_t);
 
157
        for (i = 0; i < number; ++i)
 
158
        {
 
159
                u_char protocol      = *v;
 
160
                u_char protocol_len  = *(v+1);
 
161
                u_char *protocol_val = v+2;
 
162
/*              int    address_len   = ntohs(*((u_int16_t *)(v+2+protocol_len)));*/
 
163
                u_int16_t address_len;
 
164
                u_char *address_val  = v+2+protocol_len+2;
 
165
 
 
166
                memcpy (&address_len, (v+2+protocol_len), sizeof(address_len));
 
167
                address_len = ntohs(address_len);
 
168
 
 
169
                
 
170
                if (verbose > 0)
 
171
                {
 
172
                        printf ("  protocol: %02x\n", protocol);
 
173
                        printf ("  protocol len: %02x\n", protocol_len);
 
174
                        printf ("  protocol val: ");
 
175
                        dump_hex (protocol_val, protocol_len);
 
176
                        printf ("\n");
 
177
                
 
178
                        printf ("  address len: %02x\n", address_len);
 
179
                        printf ("  address val: ");
 
180
                }
 
181
                else
 
182
                {
 
183
                        printf ("  value:  ");
 
184
                }
 
185
                if (protocol_len == 1 && *protocol_val == 0xCC && address_len == 4)
 
186
                        dump_ip (address_val);
 
187
                else
 
188
                        dump_hex (address_val, address_len);
 
189
                printf ("\n");
 
190
 
 
191
                v += (2+protocol_len+2+address_len);
 
192
        }
 
193
}
 
194
 
 
195
void
 
196
print_cdp_capabilities (u_char *v)
 
197
{
 
198
        u_int32_t cap;
 
199
 
 
200
        memcpy (&cap, v, sizeof (cap));
 
201
        cap = ntohl (cap);
 
202
 
 
203
        printf ("  value:  %08x\n", cap);
 
204
        if (cap & 0x01) printf ("          Performs level 3 routing for at least one network layer protocol.\n");
 
205
        if (cap & 0x02) printf ("          Performs level 2 transparent bridging.\n");
 
206
        if (cap & 0x04) printf ("          Performs level 2 source-route bridging.\n");
 
207
        if (cap & 0x08) printf ("          Performs level 2 switching.\n");
 
208
        if (cap & 0x10) printf ("          Sends and receives packets for at least one network layer protocol.\n");
 
209
        if (cap & 0x20) printf ("          The bridge or switch does not forward IGMP Report packets on nonrouter ports.\n");
 
210
        if (cap & 0x40) printf ("          Provides level 1 functionality.\n");
 
211
}
 
212
 
 
213
void
 
214
print_cdp_packet (const u_char *p, unsigned int plen, int verbose)
 
215
{
 
216
        CDP_HDR *h;
 
217
        CDP_DATA *d;
 
218
 
 
219
        h = (CDP_HDR *) p;
 
220
 
 
221
 
 
222
        // dump_data (p, 128);
 
223
 
 
224
        if (verbose > 1 )
 
225
        {
 
226
                printf ("\ncdp packet:\n");
 
227
                printf ("  version:      %02x\n", h->version);
 
228
                printf ("  time to live: %02x\n", h->time_to_live);
 
229
                printf ("  checksum:     %04x\n", ntohs (h->checksum));
 
230
        }
 
231
 
 
232
        d = (CDP_DATA *) (p + sizeof (CDP_HDR));
 
233
        plen -= sizeof (CDP_HDR);
 
234
 
 
235
        while (plen > sizeof (CDP_DATA))
 
236
        {
 
237
                int type;
 
238
                int length;
 
239
                u_char *v;  /* variable data */
 
240
                int vlen;   /* length of variable data */
 
241
                CDP_DATA data;
 
242
 
 
243
                memcpy (&data, d, sizeof (CDP_DATA));
 
244
                type = ntohs (data.type);
 
245
                length = ntohs (data.length);
 
246
                v = (u_char *) d + sizeof (CDP_DATA);
 
247
                vlen = length - sizeof (CDP_DATA);
 
248
        
 
249
                if(verbose > 0 )
 
250
                {
 
251
            printf ("\ncdp type/len/val:\n");
 
252
                        printf ("  type:   %04x - %s\n", type, get_cdp_type (type));
 
253
                        printf ("  length: %04x\n", length);
 
254
                }
 
255
                switch (type)
 
256
                {
 
257
                case TYPE_DEVICE_ID:
 
258
                        printf ("%s\n", get_cdp_type (type));
 
259
                        printf ("  value:  %.*s\n", vlen, v);
 
260
                        break;
 
261
 
 
262
                case TYPE_ADDRESS:
 
263
                        printf ("%s\n", get_cdp_type (type));
 
264
                        print_cdp_address (v, verbose);
 
265
                        break;
 
266
 
 
267
                case TYPE_PORT_ID:
 
268
                        printf ("%s\n", get_cdp_type (type));
 
269
                        printf ("  value:  %.*s\n", vlen, v);
 
270
                        if(cdprs >= 1)
 
271
                        {
 
272
                                char port[1024];
 
273
                                char *portval;
 
274
                                int portlen;
 
275
                                portval = urlencode(v, strlen(v), &portlen);
 
276
                                sprintf(port, "&port=%.*s", portlen, portval);
 
277
                                free(portval);
 
278
                                cdprs_action(CDPRS_DATA, port, verbose);
 
279
                        }
 
280
                        break;
 
281
 
 
282
                case TYPE_CAPABILITIES:
 
283
                        if(verbose > 0)
 
284
                        {
 
285
                                printf ("%s\n", get_cdp_type (type));
 
286
                                print_cdp_capabilities (v);
 
287
                        }
 
288
                        break;
 
289
 
 
290
                case TYPE_IOS_VERSION:
 
291
                        if(verbose > 0)
 
292
                        {
 
293
                                printf ("%s\n", get_cdp_type (type));
 
294
                                printf ("  value:  %.*s\n", vlen, v);
 
295
                        }
 
296
                        break;
 
297
 
 
298
                case TYPE_PLATFORM:
 
299
                        if(verbose > 0)
 
300
                        {
 
301
                                printf ("%s\n", get_cdp_type (type));
 
302
                                printf ("  value:  %.*s\n", vlen, v);
 
303
                        }
 
304
                        break;
 
305
 
 
306
                case TYPE_IP_PREFIX:
 
307
                        if(verbose > 0)
 
308
                        {
 
309
                                printf ("%s\n", get_cdp_type (type));
 
310
                                printf ("  value:  ");
 
311
                                dump_hex (v, vlen);
 
312
                                printf ("\n");
 
313
                        }
 
314
                        break;
 
315
 
 
316
                case TYPE_VTP_MGMT_DOMAIN:
 
317
                        if(verbose > 0)
 
318
                        {
 
319
                                printf ("%s\n", get_cdp_type (type));
 
320
                                printf ("  value:  %.*s\n", vlen, v);
 
321
                        }
 
322
                        break;
 
323
 
 
324
                case TYPE_NATIVE_VLAN:
 
325
                        if(verbose > 0)
 
326
                        {
 
327
                                printf ("%s\n", get_cdp_type (type));
 
328
                                printf ("  value:  ");
 
329
                                dump_hex (v, vlen);
 
330
                                printf ("\n");
 
331
                        }
 
332
                        break;
 
333
                
 
334
                case TYPE_DUPLEX:
 
335
                        if(verbose > 0)
 
336
                        {
 
337
                                printf ("%s\n", get_cdp_type (type));
 
338
                                printf ("  value:  ");
 
339
                                dump_hex (v, vlen);
 
340
                                printf ("\n");
 
341
                        }
 
342
                        break;
 
343
 
 
344
                default:
 
345
                        if(verbose > 1)
 
346
                        {
 
347
                                printf ("%s\n", get_cdp_type (type));
 
348
                                printf ("  value:  ");
 
349
                                dump_hex (v, vlen);
 
350
                                printf ("\n");
 
351
                        }
 
352
                }
 
353
 
 
354
            plen -= length;
 
355
            d = (CDP_DATA *) ((u_char *) d + length);
 
356
        }
 
357
}
 
358
 
 
359
 
 
360
int
 
361
print_dlt(pcap_t *handle)
 
362
{
 
363
        int type;
 
364
 
 
365
        /* Print the DLL Type*/
 
366
        switch(type = pcap_datalink(handle))
 
367
        {
 
368
#ifdef DLT_NULL
 
369
                case DLT_NULL:
 
370
                        printf("Data Link Type: BSD Loopback encapsulation.\n");
 
371
                        break;
 
372
#endif
 
373
#ifdef DLT_EN10MB
 
374
                case DLT_EN10MB:
 
375
                        printf("Data Link Type: Ethernet (10MB, 100MB, 1000MB and up).\n");
 
376
                        break;
 
377
#endif
 
378
#ifdef DLT_IEEE802
 
379
                case DLT_IEEE802:
 
380
                        printf("Data Link Type: IEEE 802.5 Token Ring.\n");
 
381
                        break;
 
382
#endif
 
383
#ifdef DLT_ARCNET
 
384
                case DLT_ARCNET:
 
385
                        printf("Data Link Type: ARCNET.\n");
 
386
                        break;
 
387
#endif
 
388
#ifdef DLT_PPP
 
389
                case DLT_PPP:
 
390
                        printf("Data Link Type: PPP (Point-to-Point Protocol).\n");
 
391
                        break;
 
392
#endif
 
393
#ifdef DLT_FDDI
 
394
                case DLT_FDDI:
 
395
                        printf("Data Link Type: FDDI.\n");
 
396
                        break;
 
397
#endif
 
398
#ifdef DLT_ATM_RFC1483
 
399
                case DLT_ATM_RFC1483:
 
400
                        printf("Data Link Type: RFC 1483 LLC/SNAP-encapsulated ATM.\n");
 
401
                        break;
 
402
#endif
 
403
#ifdef DLT_RAW
 
404
                case DLT_RAW:
 
405
                        printf("Data Link Type: raw IP.\n");
 
406
                        break;
 
407
#endif
 
408
#ifdef DLT_PPP_SERIAL
 
409
                case DLT_PPP_SERIAL:
 
410
                        printf("Data Link Type: PPP in HDLC-like framing.\n");
 
411
                        break;
 
412
#endif
 
413
#ifdef DLT_PPP_ETHER
 
414
                case DLT_PPP_ETHER:
 
415
                        printf("Data Link Type: PPPoE.\n");
 
416
                        break;
 
417
#endif
 
418
#ifdef DLT_C_HDLC
 
419
                case DLT_C_HDLC:
 
420
                        printf("Data Link Type: Cisco PPP with HDLC framing.\n");
 
421
                        break;
 
422
#endif
 
423
#ifdef DLT_IEEE802_11
 
424
                case DLT_IEEE802_11:
 
425
                        printf("Data Link Type: IEEE 802.11 wireless LAN.\n");
 
426
                        break;
 
427
#endif
 
428
#ifdef DLT_LOOP
 
429
                case DLT_LOOP:
 
430
                        printf("Data Link Type: OpenBSD loopback encapsulation.\n");
 
431
                        break;
 
432
#endif
 
433
#ifdef DLT_LTALK
 
434
                case DLT_LTALK:
 
435
                        printf("Data Link Type: Apple LocalTalk.\n");
 
436
                        break;
 
437
#endif
 
438
                default:
 
439
                        printf("%d is an unknown Data Link Transport\n", type);
 
440
        }
 
441
 
 
442
        return 0;
 
443
}
 
444
 
 
445
int
 
446
usage(void)
 
447
{
 
448
        puts("d: Specify device to use (eth0, hme0, etc.)");
 
449
        puts("h: Print this usage");
 
450
        puts("t: time in seconds to abort waiting for a packet (should be > 60)");
 
451
        puts("v[vv]: Set verbose mode");
 
452
        puts("\n** Options dealing with server updates: **");
 
453
        puts(" u: Send cdpr information to a cdpr server\n    requires config file as arg");
 
454
        puts(" l: Location/description of this port for use with -u or -s and -p");
 
455
        puts(" n: Override the hostname reported to the server for use with -u or -s and -p");
 
456
        puts(" s: Server to send information to specify port with a : after Server/IP\n     Example: 192.168.1.20:88 (default: 80) requires -p (overridden by -u)");
 
457
        puts(" p: Path of server script to send data to requires -s (overridden by -u)");
 
458
 
 
459
        exit(0);
 
460
}
 
461
 
 
462
int
 
463
main(int argc, char *argv[])
 
464
{
 
465
        pcap_t *handle;
 
466
        char *dev = NULL;
 
467
        char *conf = NULL;
 
468
        char *loc = NULL;
 
469
        char *name = NULL;
 
470
        char *svr = NULL;
 
471
        char *path = NULL;
 
472
        char errbuf[PCAP_ERRBUF_SIZE];
 
473
        struct bpf_program filter;
 
474
        /*
 
475
        ** Filter Expression: 01:00:0c:cc:cc:cc Multicast Mac Address
 
476
        ** This filter doesn't work on the arm, so use all multicast
 
477
        ** ether[20:2] = 0x2000: CDP signature in LLC
 
478
        */
 
479
#ifdef ZAURUS
 
480
        char filter_app[] = "ether multicast and ether[20:2] = 0x2000";
 
481
#else
 
482
        char filter_app[] = "ether host 01:00:0c:cc:cc:cc and ether[20:2] = 0x2000";
 
483
#endif
 
484
        bpf_u_int32 mask;
 
485
        bpf_u_int32 net;
 
486
        struct pcap_pkthdr header;
 
487
        const u_char *packet;
 
488
        char version[] = "2.2.1";
 
489
 
 
490
        int c;
 
491
        int verbose=0;
 
492
        int locdetail=0;
 
493
        int nameoverride=0;
 
494
        int cdprs_config=0;
 
495
        int cdprs_cmdline=0;
 
496
        unsigned int seconds=300;
 
497
        time_t start_time=0;
 
498
 
 
499
        /* Zero out some global variables */
 
500
        timeout=1;
 
501
        cdprs=0;
 
502
        memset (errbuf, 0, sizeof (errbuf));
 
503
 
 
504
        /* Print out header */
 
505
        printf("cdpr - Cisco Discovery Protocol Reporter\nVersion %s\n", version);
 
506
        printf("Copyright (c) 2002-2006 - MonkeyMental.com\n\n");
 
507
 
 
508
        /* Check command-line options */
 
509
        while((c = getopt(argc, argv, "d:t:vhu:l:n:s:p:")) !=EOF)
 
510
                switch(c)
 
511
                {
 
512
                        case 'd':
 
513
                                dev = optarg;
 
514
                                break;
 
515
                        case 'v':
 
516
                                verbose++;
 
517
                                break;
 
518
                        case 't':
 
519
                                seconds = atoi(optarg);
 
520
                                printf("Timeout enabled for %u seconds\n", seconds);
 
521
                                break;
 
522
                        case 'u':
 
523
                                conf = optarg;
 
524
                                cdprs = 1;
 
525
                                cdprs_config=1;
 
526
                                if(cdprs_cmdline)
 
527
                                {
 
528
                                        puts("Overriding command line server arguments with config file\n");
 
529
                                        cdprs_cmdline = 0;
 
530
                                }
 
531
                                cdprs_action(CDPRS_INIT, conf, 0);
 
532
                                break;
 
533
                        case 'l':
 
534
                                loc = optarg;
 
535
                                locdetail = 1;
 
536
                                break;
 
537
                        case 'n':
 
538
                                name = optarg;
 
539
                                nameoverride = 1;
 
540
                                break;
 
541
                        case 's':
 
542
                                svr = optarg;
 
543
                                if(cdprs_config)
 
544
                                {
 
545
                                        puts("Config file overrides cmd line");
 
546
                                }
 
547
                                else
 
548
                                {
 
549
                                        if(cdprs != 1) cdprs = 1;
 
550
                                        cdprs_cmdline++;
 
551
                                }
 
552
                                break;
 
553
                        case 'p':
 
554
                                path = optarg;
 
555
                                if(cdprs_config)
 
556
                                {
 
557
                                        puts("Config file overrides cmd line");
 
558
                                }
 
559
                                else
 
560
                                {
 
561
                                        if(cdprs != 1) cdprs = 1;
 
562
                                        cdprs_cmdline++;
 
563
                                }
 
564
                                break;
 
565
                        case 'h':
 
566
                        case '?':
 
567
                                usage();
 
568
                                break;
 
569
                }
 
570
 
 
571
        /*
 
572
        ** If we are using command line server paths, validate and buld
 
573
        ** build data structure using functions that are normally used
 
574
        ** when parsing the config file
 
575
        */
 
576
        if(cdprs && (cdprs_cmdline == 2))
 
577
        {
 
578
                cdprs_action(CDPRS_INIT, "", 0);
 
579
                do_something_with(svr, path);
 
580
        }
 
581
        else if(cdprs && (cdprs_cmdline != 0))
 
582
        {
 
583
                puts("Error only -s or -p was specified but not both");
 
584
                exit(2);
 
585
        }
 
586
 
 
587
        /* Get a pcap capable device */
 
588
        if(dev == NULL)
 
589
        {
 
590
                int i = 0;
 
591
                int inum;
 
592
                pcap_if_t *d;
 
593
                pcap_if_t *alldevs;
 
594
 
 
595
                /* The user didn't provide a packet source: Retrieve the device list */
 
596
                if (pcap_findalldevs(&alldevs, errbuf) == -1)
 
597
                {
 
598
                        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
 
599
                        exit(1);
 
600
                }
 
601
                
 
602
                /* Print the list */
 
603
                for(d=alldevs; d; d=d->next)
 
604
                {
 
605
                        printf("%d. %s", ++i, d->name);
 
606
                        if (d->description)
 
607
                                printf(" (%s)\n", d->description);
 
608
                        else
 
609
                                printf(" (No description available)\n");
 
610
                }
 
611
                
 
612
                if(i==0)
 
613
                {
 
614
                        printf("\nNo interfaces found! Make sure pcap is installed.\n");
 
615
                        return -1;
 
616
                }
 
617
                
 
618
                printf("Enter the interface number (1-%d):",i);
 
619
                scanf("%d", &inum);
 
620
                
 
621
                if(inum < 1 || inum > i)
 
622
                {
 
623
                        printf("\nInterface number out of range.\n");
 
624
                        /* Free the device list */
 
625
                        pcap_freealldevs(alldevs);
 
626
                        return -1;
 
627
                }
 
628
                
 
629
                /* Jump to the selected adapter */
 
630
                for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++)
 
631
                {
 
632
                        ;
 
633
                }
 
634
                
 
635
                dev = d->name;
 
636
        }
 
637
 
 
638
        printf("Using Device: %s\n", dev);
 
639
 
 
640
        /* Get the network number and netmask */
 
641
        pcap_lookupnet(dev, &net, &mask, errbuf);
 
642
 
 
643
        /* Open the pcap device */
 
644
        if((handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf)) == NULL)
 
645
        {
 
646
                printf("Error opening device (%s)\n", errbuf);
 
647
                exit(1);
 
648
        }
 
649
        else if (strlen(errbuf))
 
650
        {
 
651
                printf("Warning opening device (%s)\n", errbuf);
 
652
        }
 
653
 
 
654
        /* Compile the pcap filter */
 
655
        pcap_compile(handle, &filter, filter_app, 0, net);
 
656
 
 
657
        /* Activate the pcap filter */
 
658
        pcap_setfilter(handle, &filter);
 
659
        pcap_freecode(&filter);
 
660
 
 
661
        /* Set non-blocking mode */
 
662
        if(pcap_setnonblock(handle, 1, errbuf))
 
663
        {
 
664
                pcap_perror(handle, NULL);
 
665
        }
 
666
 
 
667
        /* Get the next packet that comes in, we only need one */
 
668
        printf("Waiting for CDP advertisement:\n");
 
669
        printf("(default config is to transmit CDP packets every 60 seconds)\n");
 
670
 
 
671
        /* Get current time to check for timeout */
 
672
        start_time = time(NULL);
 
673
        do
 
674
        {
 
675
                packet = pcap_next(handle, &header);
 
676
#ifdef WIN32
 
677
                Sleep(10000);
 
678
#else
 
679
                usleep(10000);
 
680
#endif
 
681
        } while ((!packet) && ( timeout=((start_time+seconds) > (unsigned int)time(NULL))) );
 
682
 
 
683
        /*
 
684
        ** timeout expired. clean up and exit
 
685
        */
 
686
        if(timeout == 0)
 
687
        {
 
688
                puts("Aborting due to timeout");
 
689
                pcap_close(handle);
 
690
                return(2);
 
691
        }
 
692
 
 
693
        /* Print its length */
 
694
        if(verbose > 0)
 
695
        {
 
696
                printf("Received a CDP packet, header length: %d\n", header.len);
 
697
        }
 
698
 
 
699
        // print cdp packet, 22 bytes into packet
 
700
        print_cdp_packet (packet+22, header.len-22, verbose);
 
701
 
 
702
        if (verbose > 1)
 
703
        {
 
704
                print_dlt(handle);
 
705
        }
 
706
        
 
707
        pcap_close(handle);
 
708
        if(cdprs >=1)
 
709
        {
 
710
                if(locdetail >=1)
 
711
                {
 
712
                        set_location(loc);
 
713
                }
 
714
                if(nameoverride >= 1)
 
715
                {
 
716
                        get_hostname(nameoverride, name);
 
717
                }
 
718
                else
 
719
                {
 
720
                        get_hostname(0, NULL);
 
721
                }
 
722
 
 
723
                cdprs_action(CDPRS_SEND, "", verbose);
 
724
        }
 
725
        return(0);
 
726
}