~ubuntu-branches/ubuntu/edgy/hwinfo/edgy

« back to all changes in this revision

Viewing changes to src/hd/pppoe.c

  • Committer: Bazaar Package Importer
  • Author(s): James Vega
  • Date: 2006-09-28 20:56:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060928205606-bgxl69hts04xbx51
Tags: 13.4-1
* New upstream version.
* Switch from dbs to quilt
  - Revamp debian/rules
  - Add quilt and remove dbs from Build-Depends in debian/control
* Remove reference to hwscan(8) from manpage. (closes: #388245)
* Re-wrote manpage from scratch.  Drop docbook-to-man from Build-Depends.
* Remove NEWS.Debian since it is no longer applicable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 *  License: GPL
 
4
 *
 
5
 *  Much inspired by rp-pppoe from Roaring Penguin Software Inc.
 
6
 *  which itself is inspired by earlier code from Luke Stras.
 
7
 */
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <stdint.h>
 
12
#include <unistd.h>
 
13
#include <sys/types.h>
 
14
#include <sys/ioctl.h>
 
15
#include <sys/socket.h>
 
16
#include <fcntl.h>
 
17
#include <errno.h>
 
18
#include <string.h>
 
19
#include <linux/if.h>
 
20
#include <net/ethernet.h>
 
21
#include <net/if_arp.h>
 
22
#include <netinet/in.h>
 
23
#include <netpacket/packet.h>
 
24
 
 
25
#include "hd.h"
 
26
#include "hd_int.h"
 
27
#include "pppoe.h"
 
28
 
 
29
static hd_data_t *hd_data;
 
30
 
 
31
/**
 
32
 * @defgroup PPPOEint PPPoE devices (DSL)
 
33
 * @ingroup libhdDEVint
 
34
 * @brief PPPoE devices scan functions
 
35
 *
 
36
 * @{
 
37
 */
 
38
 
 
39
/* Ethernet Frame Types */
 
40
#define ETH_PPPOE_DISCOVERY     0x8863
 
41
#define ETH_PPPOE_SESSION       0x8864
 
42
 
 
43
/* PPPoE Codes */
 
44
#define CODE_PADI               0x09
 
45
#define CODE_PADO               0x07
 
46
#define CODE_PADR               0x19
 
47
#define CODE_PADS               0x65
 
48
#define CODE_PADT               0xA7
 
49
 
 
50
/* PPPoE Tags */
 
51
#define TAG_END_OF_LIST         0x0000
 
52
#define TAG_SERVICE_NAME        0x0101
 
53
#define TAG_AC_NAME             0x0102
 
54
#define TAG_HOST_UNIQ           0x0103
 
55
#define TAG_AC_COOKIE           0x0104
 
56
#define TAG_VENDOR_SPECIFIC     0x0105
 
57
#define TAG_RELAY_SESSION_ID    0x0110
 
58
#define TAG_SERVICE_NAME_ERROR  0x0201
 
59
#define TAG_AC_SYSTEM_ERROR     0x0202
 
60
#define TAG_GENERIC_ERROR       0x0203
 
61
 
 
62
/* Number of Attempts */
 
63
#define MAX_ATTEMPTS            2
 
64
 
 
65
/* Timeout for PADO Packets */
 
66
#define PADO_TIMEOUT            3
 
67
 
 
68
/* A PPPoE Packet, including Ethernet headers */
 
69
typedef struct PPPoEPacketStruct {
 
70
    struct ethhdr ethHdr;       /* Ethernet header */
 
71
    unsigned int ver:4;         /* PPPoE Version (must be 1) */
 
72
    unsigned int type:4;        /* PPPoE Type (must be 1) */
 
73
    unsigned int code:8;        /* PPPoE code */
 
74
    unsigned int session:16;    /* PPPoE session */
 
75
    unsigned int length:16;     /* Payload length */
 
76
    unsigned char payload[ETH_DATA_LEN];        /* A bit of room to spare */
 
77
} PPPoEPacket;
 
78
 
 
79
/* Header size of a PPPoE Packet */
 
80
#define PPPOE_OVERHEAD 6        /* type, code, session, length */
 
81
#define HDR_SIZE (sizeof (struct ethhdr) + PPPOE_OVERHEAD)
 
82
#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD)
 
83
 
 
84
/* PPPoE Tag */
 
85
typedef struct PPPoETagStruct {
 
86
    unsigned int type:16;       /* tag type */
 
87
    unsigned int length:16;     /* Length of payload */
 
88
    unsigned char payload[ETH_DATA_LEN];        /* A LOT of room to spare */
 
89
} PPPoETag;
 
90
 
 
91
/* Header size of a PPPoE Tag */
 
92
#define TAG_HDR_SIZE 4
 
93
 
 
94
/* Function passed to parse_packet */
 
95
typedef void parse_func (uint16_t type, uint16_t len,
 
96
                         unsigned char* data, void* extra);
 
97
 
 
98
/* Keep track of the state of a connection */
 
99
typedef struct PPPoEConnectionStruct {
 
100
    char* ifname;               /* Interface name */
 
101
    int fd;                     /* Raw socket for discovery frames */
 
102
    int received_pado;          /* Where we are in discovery */
 
103
    unsigned char my_mac[ETH_ALEN];     /* My MAC address */
 
104
    unsigned char peer_mac[ETH_ALEN];   /* Peer's MAC address */
 
105
    hd_t *hd;
 
106
} PPPoEConnection;
 
107
 
 
108
/* Structure used to determine acceptable PADO packet */
 
109
typedef struct PacketCriteriaStruct {
 
110
    PPPoEConnection* conn;
 
111
    int acname_ok;
 
112
    int servicename_ok;
 
113
    int error;
 
114
} PacketCriteria;
 
115
 
 
116
/* True if Ethernet address is broadcast or multicast */
 
117
#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)
 
118
 
 
119
 
 
120
static int
 
121
check_room (PPPoEConnection* conn, unsigned char* cursor, unsigned char* start,
 
122
            uint16_t len)
 
123
{
 
124
    if (cursor - start + len > MAX_PPPOE_PAYLOAD) {
 
125
        ADD2LOG ("%s: Would create too-long packet\n", conn->ifname);
 
126
        return 0;
 
127
    }
 
128
    return 1;
 
129
}
 
130
 
 
131
 
 
132
static int
 
133
parse_packet (PPPoEConnection* conn, PPPoEPacket* packet, parse_func* func,
 
134
              void* extra)
 
135
{
 
136
    uint16_t len = ntohs (packet->length);
 
137
    unsigned char* curTag;
 
138
    uint16_t tagType, tagLen;
 
139
 
 
140
    if (packet->ver != 1) {
 
141
        ADD2LOG ("%s: Invalid PPPoE version (%d)\n", conn->ifname,
 
142
                 (int) packet->ver);
 
143
        return 0;
 
144
    }
 
145
 
 
146
    if (packet->type != 1) {
 
147
        ADD2LOG ("%s: Invalid PPPoE type (%d)\n", conn->ifname,
 
148
                 (int) packet->type);
 
149
        return 0;
 
150
    }
 
151
 
 
152
    /* Do some sanity checks on packet. */
 
153
    if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
 
154
        ADD2LOG ("%s: Invalid PPPoE packet length (%u)\n", conn->ifname, len);
 
155
        return 0;
 
156
    }
 
157
 
 
158
    /* Step through the tags. */
 
159
    curTag = packet->payload;
 
160
    while (curTag - packet->payload < len) {
 
161
        /* Alignment is not guaranteed, so do this by hand. */
 
162
        tagType = (((uint16_t) curTag[0]) << 8) + (uint16_t) curTag[1];
 
163
        tagLen = (((uint16_t) curTag[2]) << 8) + (uint16_t) curTag[3];
 
164
        if (tagType == TAG_END_OF_LIST)
 
165
            break;
 
166
        if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
 
167
            ADD2LOG ("%s: Invalid PPPoE tag length (%u)\n", conn->ifname,
 
168
                     tagLen);
 
169
            return 0;
 
170
        }
 
171
        func (tagType, tagLen, curTag + TAG_HDR_SIZE, extra);
 
172
        curTag = curTag + TAG_HDR_SIZE + tagLen;
 
173
    }
 
174
 
 
175
    return 1;
 
176
}
 
177
 
 
178
 
 
179
static int
 
180
open_interfaces (int n, PPPoEConnection* conns)
 
181
{
 
182
    int ret = 0, i;
 
183
 
 
184
    for (i = 0; i < n; i++)
 
185
    {
 
186
        PPPoEConnection* conn = &conns[i];
 
187
 
 
188
        conn->fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_PPPOE_DISCOVERY));
 
189
        if (conn->fd < 0) {
 
190
            ADD2LOG ("%s: socket failed: %m\n", conn->ifname);
 
191
            continue;
 
192
        }
 
193
 
 
194
        int one = 1;
 
195
        if (setsockopt (conn->fd, SOL_SOCKET, SO_BROADCAST, &one,
 
196
                        sizeof (one)) < 0) {
 
197
            ADD2LOG ("%s: setsockopt failed: %m\n", conn->ifname);
 
198
            goto error;
 
199
        }
 
200
 
 
201
        /* Fill in hardware address */
 
202
        struct ifreq ifr;
 
203
        struct sockaddr_ll sa;
 
204
        memset (&sa, 0, sizeof (sa));
 
205
        strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
 
206
        if (ioctl (conn->fd, SIOCGIFHWADDR, &ifr) < 0) {
 
207
            ADD2LOG ("%s: ioctl (SIOCGIFHWADDR) failed: %m\n", conn->ifname);
 
208
            goto error;
 
209
        }
 
210
 
 
211
        memcpy (conn->my_mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
 
212
        if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
 
213
            ADD2LOG ("%s: Interface is not ethernet\n", conn->ifname);
 
214
            goto error;
 
215
        }
 
216
 
 
217
        if (NOT_UNICAST (conn->my_mac)) {
 
218
            ADD2LOG ("%s: Interface has broadcast/multicast MAC address?\n",
 
219
                    conn->ifname);
 
220
            goto error;
 
221
        }
 
222
 
 
223
        /* Sanity check on MTU */
 
224
        strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
 
225
        if (ioctl (conn->fd, SIOCGIFMTU, &ifr) < 0) {
 
226
            ADD2LOG ("%s: ioctl (SIOCGIFMTU) failed: %m\n", conn->ifname);
 
227
            goto error;
 
228
        }
 
229
        if (ifr.ifr_mtu < ETH_DATA_LEN) {
 
230
            ADD2LOG ("%s: Interface has to low MTU\n", conn->ifname);
 
231
            goto error;
 
232
        }
 
233
 
 
234
        /* Get interface index */
 
235
        sa.sll_family = AF_PACKET;
 
236
        sa.sll_protocol = htons (ETH_PPPOE_DISCOVERY);
 
237
        strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
 
238
        if (ioctl (conn->fd, SIOCGIFINDEX, &ifr) < 0) {
 
239
            ADD2LOG ("%s: ioctl (SIOCFIGINDEX) failed: Could not get interface "
 
240
                     "index\n", conn->ifname);
 
241
            goto error;
 
242
        }
 
243
        sa.sll_ifindex = ifr.ifr_ifindex;
 
244
 
 
245
        /* We're only interested in packets on specified interface */
 
246
        if (bind (conn->fd, (struct sockaddr*) &sa, sizeof (sa)) < 0) {
 
247
            ADD2LOG ("%s: bind failed: %m\n", conn->ifname);
 
248
            goto error;
 
249
        }
 
250
 
 
251
        ret = 1;
 
252
        continue;
 
253
 
 
254
error:
 
255
 
 
256
        close (conn->fd);
 
257
        conn->fd = -1;
 
258
 
 
259
    }
 
260
 
 
261
    return ret;
 
262
}
 
263
 
 
264
 
 
265
static void
 
266
close_intefaces (int n, PPPoEConnection* conns)
 
267
{
 
268
    int i;
 
269
 
 
270
    for (i = 0; i < n; i++)
 
271
    {
 
272
        PPPoEConnection* conn = &conns[i];
 
273
 
 
274
        if (conn->fd != -1) {
 
275
            close (conn->fd);
 
276
            conn->fd = -1;
 
277
        }
 
278
    }
 
279
}
 
280
 
 
281
 
 
282
static int
 
283
send_packet (int fd, PPPoEPacket* pkt, size_t size)
 
284
{
 
285
    if (send (fd, pkt, size, 0) < 0) {
 
286
        ADD2LOG ("send failed: %m\n");
 
287
        return 0;
 
288
    }
 
289
 
 
290
    return 1;
 
291
}
 
292
 
 
293
 
 
294
static int
 
295
receive_packet (int fd, PPPoEPacket* pkt, size_t* size)
 
296
{
 
297
    int r = recv (fd, pkt, sizeof (PPPoEPacket), 0);
 
298
    if (r < 0) {
 
299
        ADD2LOG ("recv failed: %m\n");
 
300
        return 0;
 
301
    }
 
302
 
 
303
    *size = r;
 
304
    return 1;
 
305
}
 
306
 
 
307
 
 
308
static void
 
309
parse_hostuniq (uint16_t type, uint16_t len, unsigned char* data, void* extra)
 
310
{
 
311
    if (type == TAG_HOST_UNIQ && len == sizeof (pid_t)) {
 
312
        pid_t tmp;
 
313
        memcpy (&tmp, data, len);
 
314
        if (tmp == getpid ()) {
 
315
            int* val = (int*) extra;
 
316
            *val = 1;
 
317
        }
 
318
    }
 
319
}
 
320
 
 
321
 
 
322
static int
 
323
packet_for_me (PPPoEConnection* conn, PPPoEPacket* packet)
 
324
{
 
325
    /* If packet is not directed to our MAC address, forget it. */
 
326
    if (memcmp (packet->ethHdr.h_dest, conn->my_mac, ETH_ALEN))
 
327
        return 0;
 
328
 
 
329
    /* Check for HostUniq tag. */
 
330
    int for_me = 0;
 
331
    parse_packet (conn, packet, parse_hostuniq, &for_me);
 
332
    return for_me;
 
333
}
 
334
 
 
335
 
 
336
static void
 
337
parse_pado_tags (uint16_t type, uint16_t len, unsigned char* data, void* extra)
 
338
{
 
339
    PacketCriteria* pc = (PacketCriteria*) extra;
 
340
    PPPoEConnection *conn = pc->conn;
 
341
 
 
342
    switch (type) {
 
343
        case TAG_AC_NAME:
 
344
            pc->acname_ok = 1;
 
345
            ADD2LOG ("%s: Service-Name is: %.*s\n", conn->ifname, (int) len,
 
346
                     data);
 
347
            break;
 
348
        case TAG_SERVICE_NAME:
 
349
            pc->servicename_ok = len == 0;
 
350
            break;
 
351
        case TAG_SERVICE_NAME_ERROR:
 
352
            ADD2LOG ("%s: Service-Name-Error: %.*s\n", conn->ifname, (int) len,
 
353
                     data);
 
354
            pc->error = 1;
 
355
            break;
 
356
        case TAG_AC_SYSTEM_ERROR:
 
357
            ADD2LOG ("%s: System-Error: %.*s\n", conn->ifname, (int) len, data);
 
358
            pc->error = 1;
 
359
            break;
 
360
        case TAG_GENERIC_ERROR:
 
361
            ADD2LOG ("%s: Generic-Error: %.*s\n", conn->ifname, (int) len, data);
 
362
            pc->error = 1;
 
363
            break;
 
364
    }
 
365
}
 
366
 
 
367
 
 
368
static int
 
369
send_padi (int n, PPPoEConnection* conns)
 
370
{
 
371
    int ret = 0, i;
 
372
 
 
373
    for (i = 0; i < n; i++)
 
374
    {
 
375
        PPPoEConnection* conn = &conns[i];
 
376
 
 
377
        if (conn->fd == -1 || conn->received_pado)
 
378
            continue;
 
379
 
 
380
        PPPoEPacket packet;
 
381
        unsigned char* cursor = packet.payload;
 
382
        PPPoETag* svc = (PPPoETag*) (&packet.payload);
 
383
        uint16_t namelen = 0;
 
384
        uint16_t plen;
 
385
 
 
386
        namelen = 0;
 
387
        plen = TAG_HDR_SIZE + namelen;
 
388
        if (!check_room (conn, cursor, packet.payload, TAG_HDR_SIZE))
 
389
            continue;
 
390
 
 
391
        /* Set destination to Ethernet broadcast address */
 
392
        memset (packet.ethHdr.h_dest, 0xFF, ETH_ALEN);
 
393
        memcpy (packet.ethHdr.h_source, conn->my_mac, ETH_ALEN);
 
394
 
 
395
        packet.ethHdr.h_proto = htons (ETH_PPPOE_DISCOVERY);
 
396
        packet.ver = 1;
 
397
        packet.type = 1;
 
398
        packet.code = CODE_PADI;
 
399
        packet.session = 0;
 
400
 
 
401
        svc->type = TAG_SERVICE_NAME;
 
402
        svc->length = htons (0);
 
403
        if (!check_room (conn, cursor, packet.payload, namelen + TAG_HDR_SIZE))
 
404
            continue;
 
405
 
 
406
        cursor += namelen + TAG_HDR_SIZE;
 
407
 
 
408
        PPPoETag hostUniq;
 
409
        pid_t pid = getpid ();
 
410
        hostUniq.type = htons (TAG_HOST_UNIQ);
 
411
        hostUniq.length = htons (sizeof (pid));
 
412
        memcpy (hostUniq.payload, &pid, sizeof (pid));
 
413
        if (!check_room (conn, cursor, packet.payload, sizeof (pid) + TAG_HDR_SIZE))
 
414
            continue;
 
415
        memcpy (cursor, &hostUniq, sizeof (pid) + TAG_HDR_SIZE);
 
416
        cursor += sizeof (pid) + TAG_HDR_SIZE;
 
417
        plen += sizeof (pid) + TAG_HDR_SIZE;
 
418
 
 
419
        packet.length = htons (plen);
 
420
 
 
421
        ADD2LOG ("%s: Sending PADI packet\n", conn->ifname);
 
422
 
 
423
        if (send_packet (conn->fd, &packet, (int) (plen + HDR_SIZE)))
 
424
            ret = 1;
 
425
    }
 
426
 
 
427
    return ret;
 
428
}
 
429
 
 
430
 
 
431
static int
 
432
wait_for_pado (int n, PPPoEConnection* conns)
 
433
{
 
434
    int r, i, all;
 
435
    size_t len;
 
436
    fd_set readable;
 
437
    PPPoEPacket packet;
 
438
    PacketCriteria pc;
 
439
 
 
440
    struct timeval tv;
 
441
    tv.tv_sec = PADO_TIMEOUT;
 
442
    tv.tv_usec = 0;
 
443
 
 
444
    while (1)
 
445
    {
 
446
        FD_ZERO (&readable);
 
447
        for (i = 0; i < n; i++)
 
448
            if (conns[i].fd != -1)
 
449
                FD_SET (conns[i].fd, &readable);
 
450
 
 
451
        do {
 
452
            r = select (FD_SETSIZE, &readable, NULL, NULL, &tv);
 
453
        } while (r == -1 && errno == EINTR);
 
454
 
 
455
        if (r < 0) {
 
456
            ADD2LOG ("select: %m\n");
 
457
            return 0;
 
458
        }
 
459
 
 
460
        if (r == 0) {
 
461
            ADD2LOG ("Timeout waiting for PADO packets\n");
 
462
            return 0;
 
463
        }
 
464
 
 
465
        for (i = 0; i < n; i++)
 
466
        {
 
467
            PPPoEConnection* conn = &conns[i];
 
468
 
 
469
            if (conn->fd == -1 || !FD_ISSET (conn->fd, &readable))
 
470
                continue;
 
471
 
 
472
            pc.conn = conn;
 
473
            pc.acname_ok = 0;
 
474
            pc.servicename_ok = 0;
 
475
            pc.error = 0;
 
476
 
 
477
            /* Get the packet */
 
478
            if (!receive_packet (conn->fd, &packet, &len))
 
479
                continue;
 
480
 
 
481
            /* Check length */
 
482
            if (ntohs (packet.length) + HDR_SIZE > len) {
 
483
                ADD2LOG ("%s: Bogus PPPoE length field (%u)\n", conn->ifname,
 
484
                        (unsigned int) ntohs (packet.length));
 
485
                continue;
 
486
            }
 
487
 
 
488
            /* If it's not for us, loop again */
 
489
            if (!packet_for_me (conn, &packet))
 
490
                continue;
 
491
 
 
492
            if (packet.code != CODE_PADO)
 
493
                continue;
 
494
 
 
495
            if (NOT_UNICAST (packet.ethHdr.h_source)) {
 
496
                ADD2LOG ("%s: Ignoring PADO packet from non-unicast MAC "
 
497
                         "address\n", conn->ifname);
 
498
                continue;
 
499
            }
 
500
 
 
501
            parse_packet (conn, &packet, parse_pado_tags, &pc);
 
502
 
 
503
            if (!pc.acname_ok) {
 
504
                ADD2LOG ("%s: Wrong or missing AC-Name tag\n", conn->ifname);
 
505
                continue;
 
506
            }
 
507
 
 
508
            if (!pc.servicename_ok) {
 
509
                ADD2LOG ("%s: Wrong or missing Service-Name tag\n",
 
510
                         conn->ifname);
 
511
                continue;
 
512
            }
 
513
 
 
514
            if (pc.error) {
 
515
                ADD2LOG ("%s: Ignoring PADO packet with some Error tag\n",
 
516
                         conn->ifname);
 
517
                continue;
 
518
            }
 
519
 
 
520
            memcpy (conn->peer_mac, packet.ethHdr.h_source, ETH_ALEN);
 
521
            ADD2LOG ("%s: Received correct PADO packet\n", conn->ifname);
 
522
            conn->received_pado = 1;
 
523
        }
 
524
 
 
525
        all = 1;
 
526
        for (i = 0; i < n; i++)
 
527
            if (conns[i].fd != -1 && !conns[i].received_pado)
 
528
                all = 0;
 
529
        if (all)
 
530
            return 1;
 
531
    }
 
532
}
 
533
 
 
534
 
 
535
static void
 
536
discovery (int n, PPPoEConnection* conns)
 
537
{
 
538
    int a;
 
539
 
 
540
    if (open_interfaces (n, conns))
 
541
    {
 
542
        for (a = 0; a < MAX_ATTEMPTS; a++)
 
543
        {
 
544
            ADD2LOG ("Attempt number %d\n", a + 1);
 
545
 
 
546
            if (!send_padi (n, conns))
 
547
                break;
 
548
 
 
549
            if (wait_for_pado (n, conns))
 
550
                break;
 
551
        }
 
552
    }
 
553
 
 
554
    close_intefaces (n, conns);
 
555
}
 
556
 
 
557
 
 
558
void hd_scan_pppoe(hd_data_t *hd_data2)
 
559
{
 
560
  hd_t *hd;
 
561
  int cnt, interfaces;
 
562
  PPPoEConnection *conn;
 
563
 
 
564
  hd_data = hd_data2;
 
565
 
 
566
  if(!hd_probe_feature(hd_data, pr_pppoe)) return;
 
567
 
 
568
  hd_data->module = mod_pppoe;
 
569
 
 
570
  PROGRESS(1, 0, "looking for pppoe");
 
571
 
 
572
  for(interfaces = 0, hd = hd_data->hd; hd; hd = hd->next) {
 
573
    if(
 
574
      hd->base_class.id == bc_network_interface &&
 
575
      hd->sub_class.id == sc_nif_ethernet &&
 
576
      hd->unix_dev_name
 
577
    ) {
 
578
      interfaces++;
 
579
    }
 
580
  }
 
581
 
 
582
  if(!interfaces) return;
 
583
 
 
584
  conn = new_mem(interfaces * sizeof *conn);
 
585
 
 
586
  for(cnt = 0, hd = hd_data->hd; hd && cnt < interfaces; hd = hd->next) {
 
587
    if(
 
588
      hd->base_class.id == bc_network_interface &&
 
589
      hd->sub_class.id == sc_nif_ethernet &&
 
590
      hd->unix_dev_name
 
591
    ) {
 
592
      conn[cnt].hd = hd;
 
593
      conn[cnt].fd = -1;
 
594
      conn[cnt].ifname = hd->unix_dev_name;
 
595
      cnt++;
 
596
    }
 
597
  }
 
598
 
 
599
  PROGRESS(2, 0, "discovery");
 
600
 
 
601
  discovery(interfaces, conn);
 
602
 
 
603
  for(cnt = 0; cnt < interfaces; cnt++) {
 
604
    conn[cnt].hd->is.pppoe = 0;
 
605
 
 
606
    if(conn[cnt].received_pado) {
 
607
      conn[cnt].hd->is.pppoe = 1;
 
608
      ADD2LOG(
 
609
        "pppoe %s: my mac %02x:%02x:%02x:%02x:%02x:%02x, "
 
610
        "peer mac %02x:%02x:%02x:%02x:%02x:%02x\n",
 
611
        conn[cnt].ifname,
 
612
        conn[cnt].my_mac[0], conn[cnt].my_mac[1], conn[cnt].my_mac[2],
 
613
        conn[cnt].my_mac[3], conn[cnt].my_mac[4], conn[cnt].my_mac[5],
 
614
        conn[cnt].peer_mac[0], conn[cnt].peer_mac[1], conn[cnt].peer_mac[2],
 
615
        conn[cnt].peer_mac[3], conn[cnt].peer_mac[4], conn[cnt].peer_mac[5]
 
616
      );
 
617
    }
 
618
  }
 
619
}
 
620
 
 
621
/** @} */
 
622