1/*
2 * pppoe, a PPP-over-Ethernet redirector
3 * Copyright (C) 1999 Luke Stras <stras@ecf.toronto.edu>
4 *
5 *    This program is free software; you can redistribute it and/or modify
6 *    it under the terms of the GNU General Public License as published by
7 *    the Free Software Foundation; either version 2 of the License, or
8 *    (at your option) any later version.
9 *
10 *    This program is distributed in the hope that it will be useful,
11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *    GNU General Public License for more details.
14 *
15 *    You should have received a copy of the GNU General Public License
16 *    along with this program; if not, write to the Free Software
17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Revision History
20 * 1999/09/22 stras Initial version
21 * 1999/09/24 stras Changed header files for greater portability
22 * 1999/10/02 stras Added more logging, bug fixes
23 * 1999/10/02 mr    Port to bpf/OpenBSD; starvation fixed; efficiency fixes
24 * 1999/10/18 stras added BUGGY_AC code, partial forwarding
25 */
26
27#include <sys/types.h>
28/* foxconn wklin added start, 07/26/2007 */
29#include <sys/stat.h>
30/* foxconn wklin added end, 07/26/2007 */
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <sys/time.h> /* wklin added, 01/10/2007 */
34/* Foxconn modified start Winster Chan 11/25/2005 */
35/* #include <net/if.h> */
36#include "pppoe.h"
37/* Foxconn modified end Winster Chan 11/25/2005 */
38#include <sys/sysinfo.h> /*added by EricHuang, 01/11/2007*/
39
40#ifdef __linux__
41#include <net/if_arp.h>
42#endif /* __linux__ */
43#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6
44#include <linux/if_ether>
45#else
46#include <netinet/if_ether.h>
47#endif
48
49#include <assert.h>
50#ifdef __linux__
51#include <getopt.h>
52#endif
53#include <signal.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <unistd.h>
58
59/* #include <sys/time.h> */
60#include <time.h>
61#include <sys/ioctl.h>
62#include <sys/wait.h>
63
64
65#ifdef USE_BPF
66#ifndef ETH_ALEN
67#define ETH_ALEN 6
68#endif /* ETH_ALEN */
69/* set this to desired size - you may not get this */
70int bpf_buf_size = 65536;
71#include <net/bpf.h>
72#include <fcntl.h>
73#include <nlist.h>
74#include <kvm.h>
75unsigned char local_ether[ETH_ALEN]; /* need to this filter packets */
76#endif /* USE_BPF */
77
78#include <errno.h>
79#ifdef __linux__
80extern int errno;
81#endif
82
83/* used as the size for a packet buffer */
84/* should be > 2 * size of max packet size */
85#define PACKETBUF (4096 + 30)
86/* Foxconn added start Winster Chan 11/25/2005 */
87#define TAGBUF 128
88/* Foxconn added end Winster Chan 11/25/2005 */
89
90/* Foxconn added start, Winster Chan, 06/26/2006 */
91static int poxfd = -1;
92static int pppfd = -1;
93unsigned short sessId = 0;
94char dstMac[ETH_ALEN];
95/* Foxconn added start, Winster Chan, 06/26/2006 */
96
97char *service_name = NULL; /* foxconn wklin added, 03/27/2007 */
98
99#define VERSION_MAJOR 0
100#define VERSION_MINOR 3
101
102/* references: RFC 2516 */
103/* ETHER_TYPE fields for PPPoE */
104
105#define ETH_P_PPPOE_DISC 0x8863 /* discovery stage */
106#define ETH_P_PPPOE_SESS 0x8864 /* session stage */
107
108/* ethernet broadcast address */
109#define MAC_BCAST_ADDR "\xff\xff\xff\xff\xff\xff"
110
111/* PPPoE packet; includes Ethernet headers and such */
112struct pppoe_packet {
113#ifdef __linux__
114    struct ethhdr ethhdr; /* ethernet header */
115#else
116    struct ether_header ethhdr; /* ethernet header */
117#endif
118    unsigned int ver:4; /* pppoe version */
119    unsigned int type:4; /* pppoe type */
120    unsigned int code:8; /* pppoe code CODE_* */
121    unsigned int session:16; /* session id */
122    unsigned short length; /* payload length */
123    /* payload follows */
124};
125
126/* maximum payload length */
127#define MAX_PAYLOAD (1484 - sizeof(struct pppoe_packet))
128
129/* PPPoE codes */
130#define CODE_SESS 0x00 /* PPPoE session */
131#define CODE_PADI 0x09 /* PPPoE Active Discovery Initiation */
132#define CODE_PADO 0x07 /* PPPoE Active Discovery Offer */
133#define CODE_PADR 0x19 /* PPPoE Active Discovery Request */
134#define CODE_PADS 0x65 /* PPPoE Active Discovery Session-confirmation */
135#define CODE_PADT 0xa7 /* PPPoE Active Discovery Terminate */
136
137/* also need */
138#define STATE_RUN (-1)
139
140/* PPPoE tag; the payload is a sequence of these */
141struct pppoe_tag {
142    unsigned short type; /* tag type TAG_* */
143    unsigned short length; /* tag length */
144    /* payload follows */
145} __attribute__ ((packed)); /*added by EricHuang, 07/23/2007*/
146
147/* Foxconn added start Winster Chan 11/25/2005 */
148#define TAG_STRUCT_SIZE  sizeof(struct pppoe_tag)
149#define PPP_PPPOE_SESSION   "/tmp/ppp/pppoe_session"
150#define PPP_PPPOE2_SESSION   "/tmp/ppp/pppoe2_session"
151/*#define PPP_PPPOE_IFNAME    "/tmp/ppp/pppoe_ifname"*/
152/* Foxconn added end Winster Chan 11/25/2005 */
153
154/* PPPoE tag types */
155#define TAG_END_OF_LIST        0x0000
156#define TAG_SERVICE_NAME       0x0101
157#define TAG_AC_NAME            0x0102
158#define TAG_HOST_UNIQ          0x0103
159#define TAG_AC_COOKIE          0x0104
160#define TAG_VENDOR_SPECIFIC    0x0105
161#define TAG_RELAY_SESSION_ID   0x0110
162#define TAG_SERVICE_NAME_ERROR 0x0201
163#define TAG_AC_SYSTEM_ERROR    0x0202
164#define TAG_GENERIC_ERROR      0x0203
165
166/* globals */
167int opt_verbose = 0;   /* logging */
168int opt_fwd = 0;       /* forward invalid packets */
169int opt_fwd_search = 0; /* search for next packet when forwarding */
170#ifdef MULTIPLE_PPPOE
171#define log_file stderr
172#else
173FILE *log_file = NULL;
174#endif
175FILE *error_file = NULL;
176#ifdef MULTIPLE_PPPOE
177int ppp_ifunit = 0; /* foxconn wklin added, 08/16/2007 */
178#endif
179pid_t sess_listen = 0, pppd_listen = 0; /* child processes */
180int disc_sock = 0, sess_sock = 0; /* PPPoE sockets */
181char src_addr[ETH_ALEN]; /* source hardware address */
182char dst_addr[ETH_ALEN]; /* destination hardware address */
183char *if_name = NULL; /* interface to use */
184int session = 0; /* identifier for our session */
185int clean_child = 0; /* flag set when SIGCHLD received */
186/* Foxconn added start Winster Chan 11/25/2005 */
187char pado_tags[TAGBUF]; /* TAGs of PADO */
188int pado_tag_size = 0;
189typedef struct {
190    unsigned short  usPadLen;   /* Tag length in type of unsigned short */
191    int             nPadLen;    /* Tag length in type of integer */
192    char            *pPadStart; /* Start point of tag payload */
193} sPadxTag, *pPadxTag;
194/* Foxconn added end Winster Chan 11/25/2005 */
195#ifdef NEW_WANDETECT
196int bWanDetect = 0;/* Foxconn added by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
197#endif
198
199/* Winster Chan debugtest */
200#define DEBUG_PRINT_PACKET  0
201#define DEBUG_SEND_PACKET   0
202#define BUFRING             5 /* 40 */ /* foxconn wklin modified, 08/13/2007 */
203#define DEBUG_PRINT         0
204#define PPPOE_DEBUG_FILE    "/tmp/ppp/pppoeDbg"
205FILE *fp0;
206pid_t main_pid, sess_pid, pppd_pid;
207
208
209typedef struct {
210    /* unsigned char *pBufAddr; */
211    unsigned char packetBuf[PACKETBUF];
212} sPktBuf, *pPktBuf;
213
214void
215print_hex(unsigned char *buf, int len)
216{
217    int i;
218
219    if (opt_verbose == 0)
220      return;
221
222    for (i = 0; i < len; i++)
223      fprintf(log_file, "%02x ", (unsigned char)*(buf+i));
224
225    fprintf(log_file, "\n");
226}
227
228void
229print_packet(struct pppoe_packet *p)
230{
231    int i;
232    struct pppoe_tag *t = (struct pppoe_tag*)(p + 1);
233    struct pppoe_tag tag; /* needed to avoid alignment problems */
234    char *buf;
235    time_t tm;
236
237    if (opt_verbose == 0)
238	return;
239
240    time(&tm);
241
242    fprintf(log_file, "Ethernet header:\n");
243    fprintf(log_file, "h_dest: ");
244#ifdef __linux__
245    for (i = 0; i < 6; i++)
246	fprintf(log_file, "%02x:", (unsigned)p->ethhdr.h_dest[i]);
247#else
248    for (i = 0; i < 6; i++)
249	fprintf(log_file, "%02x:", (unsigned)p->ethhdr.ether_dhost[i]);
250#endif
251    fprintf(log_file, "\nh_source: ");
252#ifdef __linux__
253    for (i = 0; i < 6; i++)
254	fprintf(log_file, "%02x:", (unsigned)p->ethhdr.h_source[i]);
255#else
256    for (i = 0; i < 6; i++)
257	fprintf(log_file, "%02x:", (unsigned)p->ethhdr.ether_shost[i]);
258#endif
259
260#ifdef __linux__
261    fprintf(log_file, "\nh_proto: 0x%04x ",
262	    (unsigned)ntohs(p->ethhdr.h_proto));
263#else
264    fprintf(log_file, "\nh_proto: 0x%04x ",
265	    (unsigned)ntohs(p->ethhdr.ether_type));
266#endif
267
268#ifdef __linux__
269    switch((unsigned)ntohs(p->ethhdr.h_proto))
270#else
271    switch((unsigned)ntohs(p->ethhdr.ether_type))
272#endif
273    {
274        case ETH_P_PPPOE_DISC:
275            fprintf(log_file, "(PPPOE Discovery)\n");
276            break;
277        case ETH_P_PPPOE_SESS:
278            fprintf(log_file, "(PPPOE Session)\n");
279            break;
280        default:
281            fprintf(log_file, "(Unknown)\n");
282    }
283
284    fprintf(log_file, "PPPoE header: \nver: 0x%01x type: 0x%01x code: 0x%02x "
285	   "session: 0x%04x length: 0x%04x ", (unsigned)p->ver,
286	   (unsigned)p->type, (unsigned)p->code, (unsigned)p->session,
287	   (unsigned)ntohs(p->length));
288
289    switch(p->code)
290    {
291        case CODE_PADI:
292            fprintf(log_file, "(PADI)\n");
293            break;
294        case CODE_PADO:
295            fprintf(log_file, "(PADO)\n");
296            break;
297        case CODE_PADR:
298            fprintf(log_file, "(PADR)\n");
299            break;
300        case CODE_PADS:
301            fprintf(log_file, "(PADS)\n");
302            break;
303        case CODE_PADT:
304            fprintf(log_file, "(PADT)\n");
305            break;
306        default:
307            fprintf(log_file, "(Unknown)\n");
308    }
309
310#ifdef __linux__
311    if (ntohs(p->ethhdr.h_proto) != ETH_P_PPPOE_DISC)
312#else
313    if (ntohs(p->ethhdr.ether_type) != ETH_P_PPPOE_DISC)
314#endif
315    {
316        print_hex((unsigned char *)(p+1), ntohs(p->length));
317        return;
318    }
319
320
321    while (t < (struct pppoe_tag *)((char *)(p+1) + ntohs(p->length)))
322    {
323        /* no guarantee in PPPoE spec that t is aligned at all... */
324        memcpy(&tag,t,sizeof(tag));
325        fprintf(log_file, "PPPoE tag:\ntype: %04x length: %04x ",
326            ntohs(tag.type), ntohs(tag.length));
327        switch(ntohs(tag.type))
328        {
329            case TAG_END_OF_LIST:
330                fprintf(log_file, "(End of list)\n");
331                break;
332            case TAG_SERVICE_NAME:
333                fprintf(log_file, "(Service name)\n");
334                break;
335            case TAG_AC_NAME:
336                fprintf(log_file, "(AC Name)\n");
337                break;
338            case TAG_HOST_UNIQ:
339                fprintf(log_file, "(Host Uniq)\n");
340                break;
341            case TAG_AC_COOKIE:
342                fprintf(log_file, "(AC Cookie)\n");
343                break;
344            case TAG_VENDOR_SPECIFIC:
345                fprintf(log_file, "(Vendor Specific)\n");
346                break;
347            case TAG_RELAY_SESSION_ID:
348                fprintf(log_file, "(Relay Session ID)\n");
349                break;
350            case TAG_SERVICE_NAME_ERROR:
351                fprintf(log_file, "(Service Name Error)\n");
352                break;
353            case TAG_AC_SYSTEM_ERROR:
354                fprintf(log_file, "(AC System Error)\n");
355                break;
356            case TAG_GENERIC_ERROR:
357                fprintf(log_file, "(Generic Error)\n");
358                break;
359            default:
360                fprintf(log_file, "(Unknown)\n");
361        }
362        if (ntohs(tag.length) > 0) {
363            switch (ntohs(tag.type))
364            {
365                case TAG_SERVICE_NAME:
366                case TAG_AC_NAME:
367                case TAG_SERVICE_NAME_ERROR:
368                case TAG_AC_SYSTEM_ERROR:
369                case TAG_GENERIC_ERROR: /* ascii data */
370                    buf = malloc(ntohs(tag.length) + 1);
371                    memset(buf, 0, ntohs(tag.length)+1);
372                    strncpy(buf, (char *)(t+1), ntohs(tag.length));
373                    buf[ntohs(tag.length)] = '\0';
374                    fprintf(log_file, "data (UTF-8): %s\n", buf);
375                    free(buf);
376                    break;
377
378                case TAG_HOST_UNIQ:
379                case TAG_AC_COOKIE:
380                case TAG_RELAY_SESSION_ID:
381                    fprintf(log_file, "data (bin): ");
382                    for (i = 0; i < ntohs(tag.length); i++)
383                        fprintf(log_file, "%02x", (unsigned)*((char *)(t+1) + i));
384                    fprintf(log_file, "\n");
385                    break;
386
387                default:
388                    fprintf(log_file, "unrecognized data\n");
389            }
390            t = (struct pppoe_tag *)((char *)(t+1)+ntohs(tag.length));
391	}
392    }
393}
394
395/* Foxconn added start, Winster Chan, 06/26/2006 */
396#ifndef MULTIPLE_PPPOE
397/**************************************************************************
398** Function:    addr_itox()
399** Description: Convert the <int> address value getting from file to
400**                  <unsigned char> address type.
401** Parameters:  (unsigned char *) daddr -- destination address value
402**              (int *) saddr -- source address value
403**              (int) convlen -- convert length
404** Return:      none.
405**************************************************************************/
406static void addr_itox(unsigned char *daddr, int *saddr, int convlen)
407{
408    int i;
409
410    for (i = 0; i < convlen; i++)
411        daddr[i] = (unsigned char)saddr[i];
412}
413#endif
414/**************************************************************************
415** Function:    pptp_pppox_open()
416** Description: Open socket to kernel pppox driver, and open ppp device
417** Parameters:  (int *) poxfd -- pointer of file descriptor for pppox
418**              (int *) pppfd -- pointer of file descriptor for ppp device
419** Return:      none.
420**************************************************************************/
421void pptp_pppox_open(int *poxfd, int *pppfd)
422{
423#ifdef MULTIPLE_PPPOE
424    /* Open socket to pppox kernel module */
425
426    *poxfd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE);
427    if (*poxfd >= 0)
428    {
429        /* Open ppp device */
430        *pppfd = open("/dev/ppp", O_RDWR);
431	    if (*pppfd < 0)
432	    { /* on error */
433	        fprintf(stderr, "pppoe: error opening pppfd.\n");
434	        close(*poxfd);
435	    }
436	    else
437	        return;
438    }
439    else
440    {
441	    fprintf(stderr, "pppoe: error opening poxfd.\n");
442    }
443    *poxfd = -1;
444    *pppfd = -1;
445#else
446    /* Open socket to pppox kernel module */
447    *poxfd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE);
448    if (*poxfd >= 0) {
449        /* Open ppp device */
450        *pppfd = open("/dev/ppp", O_RDWR);
451    }
452    else {
453        *poxfd = -1;
454        *pppfd = -1;
455    }
456#endif
457}
458
459/**************************************************************************
460** Function:    pptp_pppox_get_info()
461** Description: Get the essential information for connecting pptp kernel
462**                  module. Such as Source IP, Destination IP, Remote MAC
463**                  address, Device name, call_id, and peer_call_id, etc.
464** Parameters:  none.
465** Return:      (struct sockaddr_pppox)sp_info -- structure of information.
466**************************************************************************/
467struct sockaddr_pppox pptp_pppox_get_info(void)
468{
469    struct sockaddr_pppox sp_info;
470    char devName[16];
471    strcpy(devName, if_name);
472    memset(&sp_info, 0, sizeof(struct sockaddr_pppox));
473    sp_info.sa_family = AF_PPPOX;
474    sp_info.sa_protocol = PX_PROTO_OE;
475    sp_info.sa_addr.pppoe.sid = sessId;   /* PPPoE session ID */
476    memcpy(sp_info.sa_addr.pppoe.remote, dstMac, ETH_ALEN); /* Remote MAC address */
477    memcpy(sp_info.sa_addr.pppoe.dev, devName, strlen(devName));
478
479    return sp_info;
480}
481
482/**************************************************************************
483** Function:    pptp_pppox_connect()
484** Description: Actually connect to pppox kernel module with the structure
485**                  got by pptp_pppox_get_info().
486** Parameters:  (int *) poxfd -- pointer of file descriptor for pppox
487**              (int *) pppfd -- pointer of file descriptor for ppp device
488** Return:      (int)err -- Fail = -1
489**                          Success = 0.
490**************************************************************************/
491/* foxconn wklin modified start, 07/31/2007 */
492int  pptp_pppox_connect(int *poxfd, int *pppfd)
493{
494    struct sockaddr_pppox lsp;
495    int err = -1;
496    int chindex;
497	int flags;
498
499    memset(&lsp, 0, sizeof(struct sockaddr_pppox));
500    lsp = pptp_pppox_get_info();
501
502    if (*poxfd >= 0) {
503        /* Connect pptp kernel connection */
504        err = connect(*poxfd, (struct sockaddr*)&lsp,
505            sizeof(struct sockaddr_pppox));
506        if (err == 0) {
507            /* Get PPP channel */
508            if (ioctl(*poxfd, PPPIOCGCHAN, &chindex) == -1) {
509                fprintf(stderr, "Couldn't get channel number");
510                return -1;
511            }
512
513            if (*pppfd >= 0) {
514                /* Attach to PPP channel */
515                if ((err = ioctl(*pppfd, PPPIOCATTCHAN, &chindex)) < 0) {
516                    fprintf(stderr, "Couldn't attach to channel");
517                    return -1;
518                }
519#ifdef MULTIPLE_PPPOE
520                if (ioctl(*pppfd, PPPIOCCONNECT, &ppp_ifunit) < 0) {
521                    fprintf(stderr, "Couldn't attach to PPP unit %d.\n", ppp_ifunit);
522                    return -1;
523                }
524#endif
525                flags = fcntl(*pppfd, F_GETFL);
526                if (flags == -1 || fcntl(*pppfd, F_SETFL, flags | O_NONBLOCK) == -1) {
527                    fprintf(stderr, "Couldn't set /dev/ppp (channel) to nonblock");
528                    return -1;
529                }
530            }
531            else {
532                fprintf(stderr, "Couldn't reopen /dev/ppp");
533                return -1;
534            }
535        }
536        else {
537            fprintf(stderr, "Couldn't connect pppox, err: %d, %s", err, strerror(errno));
538            return -1;
539        }
540    }
541    return 0;
542}
543/* foxconn wklin modified end, 07/31/2007 */
544
545/**************************************************************************
546** Function:    pptp_pppox_release()
547** Description: Release the connection between user program and pppox kernel
548**                  driver with ioctl() and connect(), and clear the
549**                  essential information in kernel.
550** Parameters:  (int *) poxfd -- pointer of file descriptor for pppox
551**              (int *) pppfd -- pointer of file descriptor for ppp device
552** Return:      (int)err -- Fail = -1
553**                          Success = 0.
554**************************************************************************/
555void pptp_pppox_release(int *poxfd, int *pppfd)
556{
557    struct sockaddr_pppox lsp;
558    int err = -1;
559
560    if (*poxfd >= 0) {
561        memset(&lsp, 0, sizeof(struct sockaddr_pppox));
562        lsp = pptp_pppox_get_info();
563        if (*pppfd >= 0) {
564            /* Detach from PPP */
565    	    if (ioctl(*pppfd, PPPIOCDETACH) < 0)
566                ; /* fprintf(stderr, "pptp_pppox_release ioctl(PPPIOCDETACH)
567                     failed\n"); */ /* foxconn wklin removed, 07/26/2007 */
568	    }
569
570        /* Release pptp kernel connection */
571        lsp.sa_addr.pppoe.sid = 0;
572        err = connect(*poxfd, (struct sockaddr*)&lsp,
573            sizeof(struct sockaddr_pppox));
574        if (err != 0)
575            fprintf(stderr, "Couldn't connect to pptp kernel module\n");
576    }
577    else
578        fprintf(stderr, "Couldn't connect socket to pppox\n");
579}
580/* Foxconn added end, Winster Chan, 06/26/2006 */
581
582int
583open_interface(char *if_name, unsigned short type, char *hw_addr)
584{
585    int optval = 1, rv;
586    struct ifreq ifr;
587
588    if ((rv = socket(PF_INET, SOCK_PACKET, htons(type))) < 0) {
589        perror("pppoe: socket");
590        return -1;
591    }
592
593    if (setsockopt(rv, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
594        perror("pppoe: setsockopt");
595        return -1;
596    }
597
598    if (hw_addr != NULL) {
599        strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
600
601        if (ioctl(rv, SIOCGIFHWADDR, &ifr) < 0) {
602            perror("pppoe: ioctl(SIOCGIFHWADDR)");
603            return -1;
604        }
605
606        if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
607            fprintf(error_file, "pppoe: interface %s is not Ethernet!\n", if_name);
608            return -1;
609        }
610        memcpy(hw_addr, ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data));
611    }
612    return rv;
613}
614
615/* Foxconn added start Winster Chan 12/02/2005 */
616int
617get_padx_tag(struct pppoe_tag *pTag, int nLen, pPadxTag pTagStruc, const unsigned short tagType)
618{
619    int bExitLoop = 0, nSearchLen = 0, bTagFound = 0;
620    struct pppoe_tag *pNextTag;
621
622    pTagStruc->usPadLen = 0;
623    pTagStruc->nPadLen = 0;
624    pTagStruc->pPadStart = NULL;
625
626    while (!bExitLoop && (nSearchLen < nLen)) {
627        if (htons(pTag->type) == tagType) {
628            pTagStruc->usPadLen = pTag->length;
629            pTagStruc->nPadLen = (int)(htons(pTag->length));
630            pTagStruc->pPadStart = (char *)pTag + TAG_STRUCT_SIZE;
631            bExitLoop = 1;
632            bTagFound = 1;
633        }
634        else {
635            pNextTag = (struct pppoe_tag *)((char *)pTag +
636                (TAG_STRUCT_SIZE + (int)(htons(pTag->length))));
637            nSearchLen += (int)((TAG_STRUCT_SIZE + (int)(htons(pTag->length))));
638            pTag = pNextTag;
639        }
640    }
641
642    return bTagFound;
643}
644/* Foxconn added end Winster Chan 12/02/2005 */
645
646int
647create_padi(struct pppoe_packet *packet, const char *src, const char *name)
648{
649    int size;
650
651    if (packet == NULL)
652	return 0;
653
654    /* printf("Winster: create_padi\n"); */
655
656    size = sizeof(struct pppoe_packet) + sizeof(struct pppoe_tag);
657    if (name != NULL)
658	size += strlen(name);
659
660#ifdef __linux__
661    memcpy(packet->ethhdr.h_dest, MAC_BCAST_ADDR, 6);
662    memcpy(packet->ethhdr.h_source, src, 6);
663    packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC);
664#else
665    memcpy(packet->ethhdr.ether_dhost, MAC_BCAST_ADDR, 6);
666    memcpy(packet->ethhdr.ether_shost, src, 6);
667    packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC);
668#endif
669    packet->ver = 1;
670    packet->type = 1;
671    packet->code = CODE_PADI;
672    packet->session = 0;
673    packet->length = htons(size - sizeof(struct pppoe_packet));
674
675    /* fill out a blank service-name tag */
676    (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_SERVICE_NAME);
677    (*(struct pppoe_tag *)(packet+1)).length = name ? htons(strlen(name)) : 0;
678    if (name != NULL)
679	memcpy((char *)(packet + 1) + sizeof(struct pppoe_tag), name,
680	       strlen(name));
681
682    return size;
683}
684
685int
686create_padr(struct pppoe_packet *packet, const char *src, const char *dst,
687	    char *name)
688{
689    int size;
690    /* Foxconn added start Winster Chan 11/25/2005 */
691    char *pCookieStart = NULL;
692    int nCookieSize = 0;
693    int nNameSize = 0;
694    unsigned short usCookieSize = 0;
695    sPadxTag sTag;
696    /* Foxconn added end Winster Chan 11/25/2005 */
697    /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */
698    char *pRelaySessionIdStart = NULL;
699    int nRelaySessionIdSize = 0;
700    unsigned short usRelaySessionIdSize = 0;
701    char *pPacketPoint = packet;
702    /* Foxconn add end, Max Ding, 09/22/2008 */
703
704    if (packet == NULL)
705	return 0;
706
707    size = sizeof(struct pppoe_packet) + TAG_STRUCT_SIZE;
708    if (name != NULL) {
709    	size += strlen(name);
710        /* Foxconn added start Winster Chan 11/25/2005 */
711        nNameSize = strlen(name);
712        /* Foxconn added end Winster Chan 11/25/2005 */
713    }
714
715    /* Foxconn added start Winster Chan 12/02/2005 */
716    /* Add length of AC cookie to packet size */
717    if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_AC_COOKIE)) {
718        nCookieSize = sTag.nPadLen;
719        usCookieSize = sTag.usPadLen;
720        pCookieStart = sTag.pPadStart;
721        size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen);
722    }
723    /* Foxconn added end Winster Chan 12/02/2005 */
724    /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */
725    if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_RELAY_SESSION_ID)) {
726        nRelaySessionIdSize = sTag.nPadLen;
727        usRelaySessionIdSize = sTag.usPadLen;
728        pRelaySessionIdStart = sTag.pPadStart;
729        size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen);
730    }
731    /* Foxconn add end, Max Ding, 09/22/2008 */
732
733#ifdef __linux__
734    memcpy(packet->ethhdr.h_dest, dst, 6);
735    memcpy(packet->ethhdr.h_source, src, 6);
736    packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC);
737#else
738    memcpy(packet->ethhdr.ether_dhost, dst, 6);
739    memcpy(packet->ethhdr.ether_shost, src, 6);
740    packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC);
741#endif
742    packet->ver = 1;
743    packet->type = 1;
744    packet->code = CODE_PADR;
745    packet->session = 0;
746    packet->length = htons(size - sizeof(struct pppoe_packet));
747
748    /* fill out a blank service-name tag */
749    (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_SERVICE_NAME);
750    (*(struct pppoe_tag *)(packet+1)).length = name ? htons(strlen(name)) : 0;
751    if (name != NULL)
752	memcpy((char *)(packet + 1) + TAG_STRUCT_SIZE, name,
753	       strlen(name));
754
755    pPacketPoint = (char *)(packet+1)+TAG_STRUCT_SIZE+nNameSize;/* Foxconn added by Max Ding, 09/23/2008 @add TAG_RELAY_SESSION_ID */
756    /* foxconn modified start, wklin, 03/27/2007, winster doesn't count name len */
757    /* Foxconn added start Winster Chan 11/25/2005 */
758    /* fill out the AC cookie tag from PADO */
759    if (nCookieSize > 0) {
760        (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE+
761                               nNameSize)).type = htons(TAG_AC_COOKIE);
762        (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE+
763                               nNameSize)).length = usCookieSize;
764        memcpy((char *)(packet+1)+(2*TAG_STRUCT_SIZE)+nNameSize,
765            (char *)pCookieStart, nCookieSize);
766        pPacketPoint = (char *)(packet+1)+(2*TAG_STRUCT_SIZE)+nNameSize+nCookieSize;/* Foxconn added by Max Ding, 09/23/2008 @add TAG_RELAY_SESSION_ID */
767    }
768    /* Foxconn added end Winster Chan 11/25/2005 */
769    /* foxconn modified end, wklin, 03/27/2007 */
770    /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */
771    if (nRelaySessionIdSize > 0) {
772        (*(struct pppoe_tag *)(pPacketPoint)).type = htons(TAG_RELAY_SESSION_ID);
773        (*(struct pppoe_tag *)(pPacketPoint)).length = usRelaySessionIdSize;
774        memcpy((pPacketPoint+TAG_STRUCT_SIZE),
775            (char *)pRelaySessionIdStart, nRelaySessionIdSize);
776        pPacketPoint += TAG_STRUCT_SIZE + nRelaySessionIdSize;
777    }
778    /* Foxconn add end, Max Ding, 09/22/2008 */
779
780    memset(((char *)packet) + size, 0, 14);
781    return size;
782}
783
784/* Foxconn added end Winster Chan 12/02/2005 */
785int
786create_padt(struct pppoe_packet *packet, const char *src, const char *dst, unsigned short nSessId)
787{
788    int size;
789    char *pCookieStart = NULL;
790    int nCookieSize = 0;
791    unsigned short usCookieSize = 0;
792    sPadxTag sTag;
793
794    if (packet == NULL)
795	return 0;
796
797    size = sizeof(struct pppoe_packet) + TAG_STRUCT_SIZE;
798
799    if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_AC_COOKIE)) {
800        nCookieSize = sTag.nPadLen;
801        usCookieSize = sTag.usPadLen;
802        pCookieStart = sTag.pPadStart;
803        size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen);
804    }
805
806#ifdef __linux__
807    memcpy(packet->ethhdr.h_dest, dst, 6);
808    memcpy(packet->ethhdr.h_source, src, 6);
809    packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC);
810#else
811    memcpy(packet->ethhdr.ether_dhost, dst, 6);
812    memcpy(packet->ethhdr.ether_shost, src, 6);
813    packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC);
814#endif
815    packet->ver = 1;
816    packet->type = 1;
817    packet->code = CODE_PADT;
818    /*packet->session = session;*/
819    packet->session = nSessId;
820    packet->length = htons(size - sizeof(struct pppoe_packet));
821
822    /* fill out a blank generic-error tag */
823    (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_GENERIC_ERROR);
824    (*(struct pppoe_tag *)(packet+1)).length = 0;
825
826    /* fill out the AC cookie tag from PADO */
827    if (nCookieSize > 0) {
828        (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE)).type
829            = htons(TAG_AC_COOKIE);
830        (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE)).length
831            = usCookieSize;
832        memcpy((char *)(packet+1)+(2*TAG_STRUCT_SIZE),
833            (char *)pCookieStart, nCookieSize);
834    }
835
836    memset(((char *)packet) + size, 0, 14);
837    return size;
838}
839/* Foxconn added end Winster Chan 12/02/2005 */
840
841/* Foxconn added start pling 09/09/2009 */
842int create_lcp_terminate_request
843(
844    struct pppoe_packet *packet,
845    const char *src, const char *dst,
846    unsigned short sess_id
847)
848{
849    int size;
850    struct pppoe_packet *ppp_data_start;
851    char ppp_data[] =
852    {
853        0xc0, 0x21,     /* PPP Link Control Protocol */
854        0x05,           /* Code: Terminate request */
855        0x01,           /* Identifier */
856        0x00, 0x10,     /* Length: 16 */
857        0x55, 0x73, 0x65, 0x72, 0x20, /* "user " */
858        0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74 /* "request" */
859    };
860
861    if (packet == NULL)
862	    return 0;
863
864    size = sizeof(struct pppoe_packet) + sizeof(ppp_data);
865
866#ifdef __linux__
867    memcpy(packet->ethhdr.h_dest, dst, 6);
868    memcpy(packet->ethhdr.h_source, src, 6);
869    packet->ethhdr.h_proto = htons(ETH_P_PPPOE_SESS);
870#else
871    memcpy(packet->ethhdr.ether_dhost, dst, 6);
872    memcpy(packet->ethhdr.ether_shost, src, 6);
873    packet->ethhdr.ether_type = htons(ETH_P_PPPOE_SESS);
874#endif
875    packet->ver = 1;
876    packet->type = 1;
877    packet->code = CODE_SESS;
878    packet->session = sess_id;
879    packet->length = htons(size - sizeof(struct pppoe_packet));
880
881    ppp_data_start = packet + 1;
882    memcpy(ppp_data_start, ppp_data, sizeof(ppp_data));
883
884    memset(((char *)packet) + size, 0, 14);
885    return size;
886}
887/* Foxconn added end pling 09/09/2009 */
888
889unsigned short fcstab[256] = {
890    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
891    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
892    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
893    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
894    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
895    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
896    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
897    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
898    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
899    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
900    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
901    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
902    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
903    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
904    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
905    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
906    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
907    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
908    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
909    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
910    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
911    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
912    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
913    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
914    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
915    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
916    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
917    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
918    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
919    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
920    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
921    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
922};
923
924#define PPPINITFCS16    0xffff  /* Initial FCS value */
925#define PPPGOODFCS16    0xf0b8  /* Good final FCS value */
926/*
927 * Calculate a new fcs given the current fcs and the new data.
928 */
929unsigned short pppfcs16(register unsigned short fcs,
930			register unsigned char * cp,
931			register int len)
932{
933/*    assert(sizeof (unsigned short) == 2);
934    assert(((unsigned short) -1) > 0); */
935
936    while (len--)
937	fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
938
939    return (fcs);
940}
941
942#define FRAME_ESC 0x7d
943#define FRAME_FLAG 0x7e
944#define FRAME_ADDR 0xff
945#define FRAME_CTL 0x03
946#define FRAME_ENC 0x20
947
948#define ADD_OUT(c) { *out++ = (c); n++; if (opt_verbose) fprintf(log_file, "%x ", (c)); }
949
950void encode_ppp(int fd, unsigned char *buf, int len)
951{
952    static int first = 0;
953    unsigned char out_buf[PACKETBUF];
954    unsigned char *out = out_buf;
955    unsigned char header[2], tail[2];
956    int i,n;
957    unsigned short fcs;
958#ifndef MULTIPLE_PPPOE
959    time_t tm;
960#endif
961    header[0] = FRAME_ADDR;
962    header[1] = FRAME_CTL;
963    fcs = pppfcs16(PPPINITFCS16, header, 2);
964    fcs = pppfcs16(fcs, buf, len) ^ 0xffff;
965    tail[0] = fcs & 0x00ff;
966    tail[1] = (fcs >> 8) & 0x00ff;
967#ifndef MULTIPLE_PPPOE
968    if (opt_verbose)
969    {
970	time(&tm);
971	fprintf(log_file, "%sWriting to pppd: \n", ctime(&tm));
972    }
973#endif
974    n = 0;
975    if (!first) {
976	ADD_OUT(FRAME_FLAG);
977	first = 1;
978    }
979    ADD_OUT(FRAME_ADDR); /* the header - which is constant */
980    ADD_OUT(FRAME_ESC);
981    ADD_OUT(FRAME_CTL ^ FRAME_ENC);
982
983    for (i = 0; i < len; i++)
984	if (buf[i] == FRAME_FLAG || buf[i] == FRAME_ESC || buf[i] < 0x20)
985	{
986	    ADD_OUT(FRAME_ESC);
987	    ADD_OUT(buf[i] ^ FRAME_ENC);
988	}
989	else
990	    ADD_OUT(buf[i]);
991
992    for (i = 0; i < 2; i++) {
993	if (tail[i] == FRAME_FLAG || tail[i] == FRAME_ESC || tail[i] < 0x20) {
994	    ADD_OUT(FRAME_ESC);
995	    ADD_OUT(tail[i] ^ FRAME_ENC);
996	} else
997	    ADD_OUT(tail[i]);
998    }
999    ADD_OUT(FRAME_FLAG);
1000
1001    write(fd, out_buf, n);
1002
1003#ifndef MULTIPLE_PPPOE
1004    if (opt_verbose)
1005	fprintf(log_file, "\n");
1006#endif
1007}
1008
1009int
1010create_sess(struct pppoe_packet *packet, const char *src, const char *dst,
1011	    unsigned char *buf, int bufsize, int sess, int *bufRemain)
1012{
1013    int size;
1014    int i, o = 0;
1015    int nBufLen = 0;
1016    int nTotalLen = 0, nAllLen = 0;
1017    int nTemp = 0;
1018    unsigned short usTotalLen = 0x0;
1019    unsigned char bufLen[2];
1020
1021    /* Clear the length of remain buffer */
1022    *bufRemain = 0;
1023
1024    if (opt_fwd || !((buf[0] == FRAME_FLAG) || (buf[0] == FRAME_ADDR)))
1025    {
1026    	if (opt_fwd_search) /* search for a valid packet */
1027    	{
1028    	    while (*buf++ != FRAME_FLAG && bufsize != 0)
1029    		bufsize--;
1030            if (bufsize == 0) {
1031                fprintf(error_file, "create_sess: bufsize == 0\n");
1032                return 0;
1033            }
1034    	}
1035    	else
1036    	{
1037    	    /* fprintf(error_file, "create_sess: invalid data\n"); */ /* foxconn wklin
1038                                                                         removed,
1039                                                                         07/26/2007
1040                                                                         */
1041    	    return 0;
1042    	}
1043    }
1044
1045    bufLen[0] = 0x0;
1046    bufLen[1] = 0x0;
1047    if (bufsize <= 4) {
1048        *bufRemain = bufsize;
1049        return 0;
1050    }
1051    else {
1052        nTemp = (buf[0] == FRAME_FLAG) ? 4 : 3;
1053        for (i = nTemp; i < bufsize; i++) {
1054            if (buf[i] == FRAME_ESC) {
1055                if ((o == 4) || (o == 5))
1056                    bufLen[o-4] = buf[++i] ^ FRAME_ENC;
1057                else
1058                    ++i;
1059            }
1060            else {
1061                if ((o == 4) || (o == 5))
1062                    bufLen[o-4] = buf[i];
1063            }
1064            o++;
1065
1066            /* Get the total length from IP packet header */
1067            if (o == 6) {
1068                usTotalLen = ntohs(*(unsigned short *)bufLen);
1069                nTotalLen = (int)usTotalLen;
1070                nAllLen = nTotalLen + 5;
1071            }
1072
1073            /* Get the total buffer length of packet */
1074            if ((o >= 6) && (o == nAllLen)) {
1075                nBufLen = i + 1;
1076                break;
1077            }
1078        }
1079
1080        if ((o < nAllLen) || (o < 6)) {
1081            *bufRemain = bufsize;
1082            return 0;
1083        }
1084        o = 0;
1085    }
1086
1087    /* for (i = (buf[0] == FRAME_FLAG ? 4 : 3); i < bufsize; i++) { */
1088    for (i = nTemp; i < bufsize; i++) {
1089        if (buf[i] == FRAME_ESC) {
1090            buf[o++] = buf[++i] ^ FRAME_ENC;
1091        }
1092        else {
1093            buf[o++] = buf[i];
1094        }
1095
1096        if (o == nAllLen)
1097            break;
1098    }   /* End for() */
1099
1100    /* Compute the length of remain buffer */
1101    *bufRemain = bufsize - nBufLen;
1102
1103    bufsize = nTotalLen + 2;
1104
1105    if (packet == NULL) {
1106        return 0;
1107    }
1108
1109    size = sizeof(struct pppoe_packet) + bufsize;
1110
1111#ifdef __linux__
1112    memcpy(packet->ethhdr.h_dest, dst, 6);
1113    memcpy(packet->ethhdr.h_source, src, 6);
1114    packet->ethhdr.h_proto = htons(ETH_P_PPPOE_SESS);
1115#else
1116    memcpy(packet->ethhdr.ether_dhost, dst, 6);
1117    memcpy(packet->ethhdr.ether_shost, src, 6);
1118    packet->ethhdr.ether_type = htons(ETH_P_PPPOE_SESS);
1119#endif
1120    packet->ver = 1;
1121    packet->type = 1;
1122    packet->code = CODE_SESS;
1123    packet->session = sess;
1124    packet->length = htons(size - sizeof(struct pppoe_packet));
1125
1126    return size;
1127}
1128
1129int
1130send_packet(int sock, struct pppoe_packet *packet, int len, const char *ifn)
1131{
1132    struct sockaddr addr;
1133    int c;
1134#ifndef MULTIPLE_PPPOE
1135    time_t tm;
1136#endif
1137    memset(&addr, 0, sizeof(addr));
1138    strcpy(addr.sa_data, ifn);
1139
1140#ifndef MULTIPLE_PPPOE
1141    if (opt_verbose == 1)
1142    {
1143	time(&tm);
1144	fprintf(log_file, "%sSending ", ctime(&tm));
1145	print_packet(packet);
1146	fputc('\n', log_file);
1147    }
1148#endif
1149
1150    if ((c = sendto(sock, packet, len, 0, &addr, sizeof(addr))) < 0) {
1151	/* fprintf(error_file, "send_packet c[%d] = sendto(len = %d)\n", c, len); */
1152	perror("pppoe: sendto (send_packet)");
1153    }
1154
1155    return c;
1156}
1157#ifdef MULTIPLE_PPPOE
1158int
1159read_packet_nowait(int sock, struct pppoe_packet *packet, int *len)
1160{
1161    socklen_t fromlen = PACKETBUF;
1162
1163    if (recvfrom(sock, packet, PACKETBUF, 0,
1164             NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) {
1165        perror("pppoe: recv (read_packet_nowait)");
1166        return -1;
1167    }
1168
1169    return sock;
1170}
1171
1172int
1173read_packet(int sock, struct pppoe_packet *packet, int *len)
1174{
1175    socklen_t fromlen = PACKETBUF;
1176    fd_set fdset;
1177    struct timeval tma;
1178
1179    FD_ZERO(&fdset);
1180    FD_SET(sock, &fdset);
1181    tma.tv_usec = 0;
1182    tma.tv_sec = 3; /* wait for 3 seconds at most */
1183    while(1) {
1184        if (select(sock + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL,
1185		    &tma) <= 0) {
1186            return -1; /* timeout or error */
1187        } else if (FD_ISSET(sock, &fdset)) {
1188            if (recvfrom(sock, packet, PACKETBUF, 0,
1189                  NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) {
1190            	perror("pppoe: recv (read_packet)");
1191                return -1;
1192            } else if (memcmp(packet->ethhdr.h_dest,src_addr,sizeof(src_addr))!=0){
1193		/* fprintf(stderr, "pppoe: received a packet not for me.\n");*/
1194		continue;
1195	    }
1196        }
1197        return sock;
1198    }
1199}
1200#endif
1201#ifndef MULTIPLE_PPPOE
1202/* foxconn wklin added start, 08/10/2007 */
1203int
1204read_packet2(int sock, struct pppoe_packet *packet, int *len)
1205{
1206#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6
1207    int fromlen = PACKETBUF;
1208#else
1209    socklen_t fromlen = PACKETBUF;
1210#endif
1211    time_t tm;
1212
1213    if (recvfrom(sock, packet, PACKETBUF, 0,
1214                 NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) {
1215        perror("pppoe: recv (read_packet2)");
1216        return -1;
1217    }
1218
1219    if (opt_verbose)
1220    {
1221        time(&tm);
1222        fprintf(log_file, "Received packet at %s", ctime(&tm));
1223        print_packet(packet);
1224        fputc('\n', log_file);
1225    }
1226
1227     return sock;
1228}
1229/* foxconn wklin added end, 08/10/2007 */
1230
1231int
1232read_packet(int sock, struct pppoe_packet *packet, int *len)
1233{
1234/*    struct sockaddr_in from; */
1235#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6
1236    int fromlen = PACKETBUF;
1237#else
1238    socklen_t fromlen = PACKETBUF;
1239#endif
1240    time_t tm;
1241
1242    time(&tm);
1243
1244    while(1) {
1245	/* wklin modified start, 01/10/2007 */
1246        fd_set fdset;
1247        struct timeval tm;
1248
1249	FD_ZERO(&fdset);
1250	FD_SET(sock, &fdset);
1251    	tm.tv_usec = 0;
1252	tm.tv_sec = 3; /* wait for 3 seconds */
1253	if (select(sock + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) <= 0) {
1254            return -1; /* timeout or error */
1255	} else if (FD_ISSET(sock, &fdset)) {
1256	    if (recvfrom(sock, packet, PACKETBUF, 0,
1257		 NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) {
1258	        perror("pppoe: recv (read_packet)");
1259	        return -1;
1260	    }
1261	}
1262	/* wklin modified end, 01/10/2007 */
1263	if (opt_verbose)
1264	{
1265	    fprintf(log_file, "Received packet at %s", ctime(&tm));
1266	    print_packet(packet);
1267	    fputc('\n', log_file);
1268	}
1269
1270	return sock;
1271    }
1272}
1273#endif
1274
1275void sigchild(int src) {
1276    clean_child = 1;
1277}
1278
1279void cleanup_and_exit(int status) {
1280#ifdef MULTIPLE_PPPOE
1281    if (pppfd > 0)
1282        close(pppfd);
1283    if (poxfd > 0)
1284        close(poxfd);
1285    if (disc_sock > 0)
1286        close(disc_sock);
1287    if (sess_sock > 0)
1288        close(sess_sock);
1289    close(1);
1290
1291    exit(status);
1292#else
1293    /* Foxconn modified start, Winster Chan, 06/26/2006 */
1294#ifdef NEW_WANDETECT
1295    if (!bWanDetect) /* Foxconn added by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1296#endif
1297    {
1298        pptp_pppox_release(&poxfd, &pppfd);
1299        close(pppfd); pppfd = -1;
1300        close(poxfd); poxfd = -1;
1301    }
1302    /* Foxconn modified end, Winster Chan, 06/26/2006 */
1303
1304    close(disc_sock);
1305#ifdef NEW_WANDETECT
1306    if (!bWanDetect) /* Foxconn added by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1307#endif
1308        close(sess_sock);
1309    close(1);
1310
1311    exit(status);
1312#endif
1313}
1314
1315void sigint(int src)
1316{
1317#ifdef MULTIPLE_PPPOE
1318    struct pppoe_packet *packet = NULL;
1319    int pkt_size;
1320    FILE *fp;
1321
1322    /* Foxconn modified start pling 10/08/2009 */
1323    /* Don't reference pppd_listen any more as this var is not used. */
1324    /* if (disc_sock >= 0 && (pppd_listen >= 0)) { */
1325    if (disc_sock > 0) {
1326    /* Foxconn modified end pling 10/08/2009 */
1327        /* allocate packet once */
1328        packet = malloc(PACKETBUF);
1329        assert(packet != NULL);
1330
1331        /* send PADT */
1332        if ((pkt_size = create_padt(packet, src_addr, dst_addr, session)) == 0) {
1333              fprintf(stderr, "pppoe: unable to create PADT packet\n");
1334              if (packet != NULL)
1335                  free(packet);
1336              exit(1);
1337        }
1338        if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
1339            fprintf(stderr, "pppoe: unable to send PADT packet\n");
1340            if (packet != NULL)
1341                free(packet);
1342            exit(1);
1343        }  else {
1344            ; /* fprintf(stderr, "PPPOE: PADT sent*\n"); */
1345        }
1346    }
1347
1348    if (ppp_ifunit == 0)
1349        fp = fopen(PPP_PPPOE_SESSION, "w+");
1350    else
1351        fp = fopen(PPP_PPPOE2_SESSION, "w+");
1352
1353    if (fp) {
1354        /* Clear the PPPoE server MAC address and Session ID */
1355        fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n",
1356            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0);
1357        fclose(fp);
1358    }
1359
1360    if (packet != NULL)
1361        free(packet);
1362    cleanup_and_exit(1);
1363#else
1364    /* Foxconn added start Winster Chan 12/02/2005 */
1365    struct pppoe_packet *packet = NULL;
1366    int pkt_size;
1367    FILE *fp;
1368    time_t tm;
1369
1370    /* Foxconn modified start pling 10/08/2009 */
1371    /* Don't reference pppd_listen any more as this var is not used. */
1372    /* if (disc_sock && (pppd_listen > 0)) { */
1373    if (disc_sock > 0) {
1374    /* Foxconn modified end pling 10/08/2009 */
1375        /* allocate packet once */
1376        packet = malloc(PACKETBUF);
1377        assert(packet != NULL);
1378
1379        /* send PADT */
1380        if ((pkt_size = create_padt(packet, src_addr, dst_addr, session)) == 0) {
1381  	        fprintf(stderr, "pppoe: unable to create PADT packet\n");
1382            /* exit(1); */
1383        }
1384        if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
1385            fprintf(stderr, "pppoe: unable to send PADT packet\n");
1386            /* exit(1); */
1387        }  else {
1388            time(&tm);
1389            fprintf(stderr, "PPPOE: PADT sent* %s\n",ctime(&tm)); /* foxconn wklin added, 07/26/2007 */
1390        }
1391    }
1392    /* Foxconn added end Winster Chan 12/02/2005 */
1393
1394    /* Foxconn added start Winster Chan 12/05/2005 */
1395    if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) {
1396        perror(PPP_PPPOE_SESSION);
1397    }
1398    else {
1399        /* Clear the PPPoE server MAC address and Session ID */
1400        fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n",
1401            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0);
1402        fclose(fp);
1403    }
1404
1405    if (packet != NULL)
1406        free(packet);
1407
1408    /* Foxconn added end Winster Chan 12/05/2005 */
1409    cleanup_and_exit(1);
1410#endif
1411}
1412
1413/*Foxconn added start James 11/12/2008 @new_internet_detection*/
1414#ifdef NEW_WANDETECT
1415void sigint2(int src)
1416{
1417    struct pppoe_packet *packet = NULL;
1418    int pkt_size;
1419    FILE *fp;
1420    time_t tm;
1421
1422    /* allocate packet once */
1423    packet = malloc(PACKETBUF);
1424    assert(packet != NULL);
1425
1426    /* Foxconn added start pling 09/09/2009 */
1427    /* Send LCP terminate request first, before PADT,
1428     *  to make the PPP server terminates our session.
1429     */
1430    if ((pkt_size = create_lcp_terminate_request(packet,
1431                        src_addr, dst_addr, session)) == 0) {
1432        fprintf(stderr, "pppoe: unable to create LCP terminate req packet\n");
1433    } else {
1434        sleep(1);
1435        if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
1436            fprintf(stderr, "pppoe: unable to send PADT packet\n");
1437        } else {
1438            time(&tm);
1439            fprintf(stderr, "PPPOE: LCP Terminate Req sent* %s\n",ctime(&tm));
1440            sleep(1);
1441        }
1442    }
1443    /* Foxconn added end pling 09/09/2009 */
1444
1445    /* send PADT */
1446    if ((pkt_size = create_padt(packet, src_addr, dst_addr, session)) == 0) {
1447            fprintf(stderr, "pppoe: unable to create PADT packet\n");
1448        /* exit(1); */
1449    }
1450    if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
1451        fprintf(stderr, "pppoe: unable to send PADT packet\n");
1452        /* exit(1); */
1453    }  else {
1454        time(&tm);
1455        fprintf(stderr, "PPPOE: PADT sent* %s\n",ctime(&tm)); /* foxconn wklin added, 07/26/2007 */
1456    }
1457
1458    /* Foxconn added end Winster Chan 12/02/2005 */
1459
1460    /* Foxconn added start Winster Chan 12/05/2005 */
1461    if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) {
1462        perror(PPP_PPPOE_SESSION);
1463    }
1464    else {
1465        /* Clear the PPPoE server MAC address and Session ID */
1466        fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n",
1467            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0);
1468        fclose(fp);
1469    }
1470    if (packet != NULL)
1471        free(packet);
1472
1473    /* Foxconn added end Winster Chan 12/05/2005 */
1474    cleanup_and_exit(1);
1475
1476}
1477#endif
1478/* Foxconn added end James 11/12/2008 @new_internet_detection */
1479
1480void sess_handler(void) {
1481    /* pull packets of sess_sock and feed to pppd */
1482    static struct pppoe_packet *packet = NULL;
1483    int pkt_size;
1484
1485#ifdef BUGGY_AC
1486/* the following code deals with buggy AC software which sometimes sends
1487   duplicate packets */
1488#define DUP_COUNT 10
1489#define DUP_LENGTH 20
1490    static unsigned char dup_check[DUP_COUNT][DUP_LENGTH];
1491    int i, ptr = 0;
1492#endif /* BUGGY_AC */
1493
1494    if (!packet) {
1495#ifdef BUGGY_AC
1496        memset(dup_check, 0, sizeof(dup_check));
1497#endif
1498        /* allocate packet once */
1499        packet = malloc(PACKETBUF);
1500        assert(packet != NULL);
1501    }
1502
1503    /* while(1) */
1504    {
1505#ifdef MULTIPLE_PPPOE
1506        if (read_packet_nowait(sess_sock,packet,&pkt_size) != sess_sock)
1507#else
1508	    if (read_packet2(sess_sock,packet,&pkt_size) != sess_sock)
1509#endif
1510                return;
1511#ifdef __linux__
1512	    if (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr)) != 0)
1513#else
1514	    if (memcmp(packet->ethhdr.ether_shost, dst_addr, sizeof(dst_addr)) != 0)
1515#endif
1516	        return; /* packet not from AC */
1517#ifdef MULTIPLE_PPPOE
1518        if (memcmp(packet->ethhdr.h_dest, src_addr, sizeof(src_addr)) != 0) {
1519	    /* fprintf(stderr, "pppoe: received a session packet not for
1520	     * me.\n"); */
1521            return;
1522		}
1523#endif
1524	    if (packet->session != session)
1525	        return; /* discard other sessions */
1526#ifdef __linux__
1527	    if (packet->ethhdr.h_proto != htons(ETH_P_PPPOE_SESS))
1528	    {
1529	        fprintf(log_file, "pppoe: invalid session proto %x detected\n",
1530		        ntohs(packet->ethhdr.h_proto));
1531	        return;
1532	    }
1533#else
1534	    if (packet->ethhdr.ether_type != htons(ETH_P_PPPOE_SESS))
1535	    {
1536	        fprintf(log_file, "pppoe: invalid session proto %x detected\n",
1537		        ntohs(packet->ethhdr.ether_type));
1538                return;
1539	    }
1540#endif
1541	    if (packet->code != CODE_SESS) {
1542	        fprintf(log_file, "pppoe: invalid session code %x\n", packet->code);
1543	        return;
1544	    }
1545#if BUGGY_AC
1546    	/* we need to go through a list of recently-received packets to
1547	       make sure the AC hasn't sent us a duplicate */
1548	    for (i = 0; i < DUP_COUNT; i++)
1549	        if (memcmp(packet, dup_check[i], sizeof(dup_check[0])) == 0)
1550		        return; /* we've received a dup packet */
1551#define min(a,b) ((a) < (b) ? (a) : (b))
1552	    memcpy(dup_check[ptr], packet, min(ntohs(packet->length),
1553						    sizeof(dup_check[0])));
1554	    ptr = ++ptr % DUP_COUNT;
1555#endif /* BUGGY_AC */
1556
1557	    encode_ppp(1, (unsigned char *)(packet+1), ntohs(packet->length));
1558    }
1559}
1560
1561void pppd_handler(void) {
1562  /* take packets from pppd and feed them to sess_sock */
1563  struct pppoe_packet *packet = NULL;
1564#ifndef MULTIPLE_PPPOE
1565  time_t tm;
1566#endif
1567  static sPktBuf pktBuf[BUFRING]; /* foxconn wklin modified, use static */
1568  int nPkt = 0;
1569  /* unsigned char buf[PACKETBUF]; */
1570  int len, pkt_size;
1571  int i, bufRemain = 0, bufPos;
1572  unsigned char *currBufStart;
1573  static int first_in = 1; /* foxconn wklin added, 08/10/2007 */
1574
1575  if (first_in) {
1576      first_in = 0;
1577      /* Clear data buffer */
1578      for (i=0; i<BUFRING; i++) {
1579           memset(pktBuf[i].packetBuf, 0x0, sizeof(pktBuf[i].packetBuf));
1580      }
1581  }
1582
1583  {
1584    /* Read in data buffer, Maximum size is 4095 bytes for evey one read() */
1585    if ((len = read(0, &(pktBuf[nPkt].packetBuf[(20+bufRemain)]), (4095-bufRemain))) < 0) {
1586      perror("pppoe");
1587      fprintf(error_file, "pppd_handler: read packet error len < 0\n");
1588      /* exit(1); */
1589      return;
1590    }
1591    if (len == 0) {
1592      /* foxconn wklin modified start, 07/27/2007 */
1593      /* fprintf(error_file, "pppd_handler: read packet len = 0 bytes\n"); */
1594      /* usleep(10000);*/ /* sleep 10ms */
1595      /* foxconn wklin modified end, 07/27/2007 */
1596      /* continue; */
1597        return;
1598    }
1599    /* Append the length of previous remained data */
1600    len += bufRemain;
1601#ifndef MULTIPLE_PPPOE
1602    if (opt_verbose == 1) {
1603        time(&tm);
1604        fprintf(log_file, "\n%sInput of %d bytes:\n", ctime(&tm), len);
1605        /*print_hex(buf, len);*/
1606        print_hex(pktBuf[nPkt].packetBuf, len);
1607        fputc('\n', log_file);
1608    }
1609#endif
1610    bufPos = 0;
1611    packet = &(pktBuf[nPkt].packetBuf[0]);
1612    currBufStart = &(pktBuf[nPkt].packetBuf[20]);
1613    do {
1614        /* Segment and compose packet from buffer */
1615        if ((pkt_size = create_sess(packet, src_addr, dst_addr, currBufStart, len,
1616                                    session, &bufRemain)) == 0) {
1617          /* Copy incomplete content to next buffer */
1618          if (bufRemain > 0) {
1619            if ((nPkt+1) < BUFRING) {
1620                memcpy(&(pktBuf[nPkt+1].packetBuf[20]),
1621                       &(pktBuf[nPkt].packetBuf[(4115-bufRemain)]),         /* 4115 = 4095 + 20 */
1622                       bufRemain);
1623            }
1624            else {
1625                memcpy(&(pktBuf[0].packetBuf[20]),
1626                       &(pktBuf[(BUFRING-1)].packetBuf[(4115-bufRemain)]),  /* 4115 = 4095 + 20 */
1627                       bufRemain);
1628            }
1629          }
1630          break;
1631        }
1632
1633        len -= bufRemain;
1634
1635        /* Send the completely composed packet */
1636        if (send_packet(sess_sock, packet, pkt_size, if_name) < 0) {
1637          fprintf(error_file, "pppd_handler: unable to send PPPoE packet\n");
1638          /* exit(1); */
1639          return;
1640        }
1641
1642        /* Check if all the contents of buffer were processed */
1643        if (bufRemain <= 0) {
1644            break;
1645        }
1646        else {
1647            /* Renew the positions of packet header and data buffer */
1648            bufPos += len;
1649            currBufStart = &(pktBuf[nPkt].packetBuf[bufPos+20]);
1650            packet = &(pktBuf[nPkt].packetBuf[bufPos]);
1651            len = bufRemain;
1652        }
1653    } while (bufRemain > 0);
1654
1655    /* Process next read buffer */
1656    nPkt++;
1657    if (nPkt >= BUFRING)
1658        nPkt = 0;
1659
1660  }
1661}
1662#ifdef MULTIPLE_PPPOE
1663/* Foxconn Bob Guo added start 10/25/2007*/
1664#define SERVER_RECORD_FILE	"/tmp/ppp/PPPoE_server_record"
1665#define UPTIME_FILE			"/proc/uptime"
1666
1667static int checkServerRecord(unsigned char *pServerMac)
1668{
1669	FILE *fp=NULL;
1670	char line[64];
1671	char macAddr[32];
1672	char *token;
1673	int iTimeStamp = 0;
1674
1675	fp = fopen(SERVER_RECORD_FILE, "r");
1676	if(fp == NULL)
1677	{
1678		goto _exit;
1679	}
1680
1681	sprintf(macAddr, "%02x:%02x:%02x:%02x:%02x:%02x", *pServerMac, *(pServerMac+1), *(pServerMac+2),
1682													*(pServerMac+3), *(pServerMac+4), *(pServerMac+5));
1683
1684	while (fgets(line, sizeof(line), fp))
1685	{
1686		if( strncmp(line, macAddr, strlen(macAddr)) == 0)
1687		{
1688            /* the mac address exist in the list */
1689			token = strtok(line, " ");
1690			if(token == NULL)
1691				goto _exit;
1692			token = strtok(NULL, " ");
1693			if(token)
1694			{
1695				iTimeStamp = atoi(token);
1696			}
1697			break;
1698		}
1699	}
1700
1701_exit:
1702
1703	if(fp)
1704		fclose(fp);
1705
1706	return iTimeStamp;
1707}
1708
1709static void updateServerRecord(unsigned char *pServerMac)
1710{
1711    FILE *fp=NULL, *fp_uptime=NULL;
1712	char line[64];
1713	char macAddr[32];
1714	char uptime[32];
1715    char *token;
1716    int bFound;
1717
1718	fp = fopen(SERVER_RECORD_FILE, "r+");
1719	if(fp == NULL)
1720	{
1721		fp = fopen(SERVER_RECORD_FILE, "w+");
1722		if(fp == NULL)
1723			goto _exit;
1724	}
1725
1726	sprintf(macAddr, "%02x:%02x:%02x:%02x:%02x:%02x", *pServerMac, *(pServerMac+1), *(pServerMac+2),
1727													*(pServerMac+3), *(pServerMac+4), *(pServerMac+5));
1728
1729	fp_uptime = fopen(UPTIME_FILE, "r");
1730	if(fp_uptime == NULL)
1731		goto _exit;
1732
1733	if(fgets(line, sizeof(line), fp_uptime))
1734	{
1735		token = strtok(line, " .\t\n");
1736		if(token == NULL)
1737			goto _exit;
1738
1739        int i = atoi(token);
1740        sprintf(uptime, "%010d", i);
1741	}
1742
1743	bFound = 0;
1744
1745	while (fgets(line, sizeof(line), fp))
1746	{
1747		if( strncmp(line, macAddr, strlen(macAddr)) == 0)
1748		{
1749            /* the mac address exist in the list */
1750			bFound = 1;
1751			break;
1752		}
1753	}
1754
1755	if(bFound)
1756	{
1757		int ioffset = 0 - (strlen(line));
1758		fseek(fp, ioffset, SEEK_CUR);
1759	}
1760	else
1761	{
1762		fseek(fp, 0, SEEK_END);
1763	}
1764	fprintf(fp, "%s %s\n", macAddr, uptime);
1765
1766_exit:
1767	if(fp)
1768		fclose(fp);
1769	if(fp_uptime)
1770		fclose(fp_uptime);
1771
1772}
1773
1774/* Foxconn Bob Guo added end 10/25/2007 */
1775#endif
1776int main(int argc, char **argv)
1777{
1778    struct pppoe_packet *packet = NULL;
1779#ifdef MULTIPLE_PPPOE
1780    /* Foxconn Bob Guo added start 10/25/2007*/
1781    struct pppoe_packet *packet2 = NULL;
1782    struct pppoe_packet *packet_temp = NULL;
1783    int pkt2_size;
1784    int iOldestTimeStamp, iTimeStamp;
1785    /* Foxconn Bob Guo added end 10/25/2007*/
1786#endif
1787    int pkt_size;
1788    /* Foxconn added start Winster Chan 12/05/2005 */
1789    FILE *fp;
1790    char buf[64];
1791    /* Foxconn added end Winster Chan 12/05/2005 */
1792    int fd; /* wklin added, 07/26/2007 */
1793
1794    int opt;
1795    int ret_sock; /* foxconn wklin added, 12/27/2007 */
1796
1797    /* foxconn wklin added start, 08/10/2007 */
1798    fd_set allfdset;
1799#ifndef MULTIPLE_PPPOE
1800    struct timeval alltm;
1801#endif
1802    /* foxconn wklin added end, 08/10/2007 */
1803    time_t tm;
1804
1805#ifdef NEW_WANDETECT
1806    bWanDetect = 0;/* Foxconn added by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1807#endif
1808
1809    /* initialize error_file here to avoid glibc2.1 issues */
1810     error_file = stderr;
1811
1812    /* foxconn wklin added start, 07/26/2007 */
1813    fd = open("/dev/console", O_WRONLY);
1814    if (fd != -1)
1815        dup2(fd, 2);
1816    /* foxconn wklin added end, 07/26/2007 */
1817
1818    /* parse options */
1819    /* foxconn wklin modified, 03/27/2007, add service name option S */
1820#ifdef MULTIPLE_PPPOE
1821    /* while ((opt = getopt(argc, argv, "I:L:VE:F:S:P:")) != -1) */
1822    while ((opt = getopt(argc, argv, "I:L:VE:F:S:R:P:")) != -1)/* Foxconn modified by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1823#else
1824    /* while ((opt = getopt(argc, argv, "I:L:VE:F:S:")) != -1) */
1825    while ((opt = getopt(argc, argv, "I:L:VE:F:S:R:")) != -1)/* Foxconn modified by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1826#endif
1827	switch(opt)
1828	{
1829	case 'F': /* sets invalid forwarding */
1830	    if (*optarg == 'a') /* always forward */
1831		opt_fwd = 1;
1832	    else if (*optarg == 's') /* search for flag */
1833		opt_fwd_search = 1;
1834	    else
1835		fprintf(stderr, "Invalid forward option %c\n", *optarg);
1836	    break;
1837
1838	case 'I': /* sets interface */
1839	    if (if_name != NULL)
1840		free(if_name);
1841        /* foxconn wklin modified, 03/27/2007 */
1842	    if ((if_name=malloc(strlen(optarg)+1)) == NULL)
1843	    {
1844		fprintf(stderr, "malloc\n");
1845		exit(1);
1846	    }
1847	    strcpy(if_name, optarg);
1848#ifndef MULTIPLE_PPPOE
1849            /* wklin added start, 01/15/2007 */
1850            if (log_file != NULL)
1851                fclose(log_file);
1852            if ((log_file=fopen("/dev/null", "w")) == NULL) {
1853                fprintf(stderr, "fopen\n");
1854                exit(1);
1855            }
1856            /* wklin added end, 01/15/2007 */
1857#endif
1858	    break;
1859
1860	case 'L': /* log file */
1861	    opt_verbose = 1;
1862	    if (log_file != NULL)
1863		fclose(log_file);
1864	    if ((log_file=fopen(optarg, "w")) == NULL)
1865	    {
1866		fprintf(stderr, "fopen\n");
1867		exit(1);
1868	    }
1869	    if (setvbuf(log_file, NULL, _IONBF, 0) != 0)
1870	    {
1871		fprintf(stderr, "setvbuf\n");
1872		exit(1);
1873	    }
1874	    break;
1875	case 'V': /* version */
1876	    printf("pppoe version %d.%d\n", VERSION_MAJOR, VERSION_MINOR);
1877	    exit(0);
1878	    break;
1879	case 'E': /* error file */
1880	    if ((error_file = fopen(optarg, "w")) == NULL)
1881	    {
1882		fprintf(stderr, "fopen\n");
1883		exit(1);
1884	    }
1885	    if (setvbuf(error_file, NULL, _IONBF, 0) != 0)
1886	    {
1887		fprintf(stderr, "setvbuf\n");
1888		exit(1);
1889	    }
1890	    break;
1891        /* foxconn wklin added start, 03/27/2007, service name */
1892	case 'S': /* set service name*/
1893	    if (service_name != NULL)
1894		    free(service_name);
1895	    if ((service_name=malloc(strlen(optarg)+1)) == NULL) {
1896#ifdef MULTIPLE_PPPOE
1897            fprintf(stderr, "pppoe: malloc error.\n");
1898#else
1899		    fprintf(stderr, "malloc\n");
1900#endif
1901		    exit(1);
1902	    }
1903	    strcpy(service_name, optarg);
1904	    break;
1905        /* foxconn wklin added end, 03/27/2007 */
1906#ifdef MULTIPLE_PPPOE
1907        /* foxconn wklin added start, 08/16/2007, service name */
1908    case 'P': /* ppp ifunit */
1909        ppp_ifunit = 1;
1910        break;
1911        /* foxconn wklin added end, 08/16/2007 */
1912#endif
1913        /* Foxconn add start, Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1914        case 'R': /* wan detect purpose */
1915#ifdef NEW_WANDETECT
1916            bWanDetect = 1;
1917#endif
1918            break;
1919        /* Foxconn add end, Max Ding, 04/23/2009 */
1920	default:
1921	    fprintf(stderr, "Unknown option %c\n", optopt);
1922	    exit(1);
1923	}
1924
1925    /* allocate packet once */
1926    packet = malloc(PACKETBUF);
1927    assert(packet != NULL);
1928
1929    /* create the raw socket we need */
1930
1931    signal(SIGINT, sigint);
1932    signal(SIGTERM, sigint);
1933#ifdef NEW_WANDETECT
1934    signal(SIGUSR1, sigint2);/*Foxconn added James 11/11/2008 @new_internet_detection*/
1935#endif
1936
1937#ifndef MULTIPLE_PPPOE
1938#ifdef NEW_WANDETECT
1939    if (!bWanDetect) /* Foxconn added by Max Ding, 04/23/2009 not use pppd to reduce memory usage */
1940#endif
1941    {
1942        /* Foxconn added start, Winster Chan, 06/26/2006 */
1943        pptp_pppox_open(&poxfd, &pppfd);
1944        /* Foxconn added end, Winster Chan, 06/26/2006 */
1945    }
1946#endif
1947
1948    if ((disc_sock = open_interface(if_name,ETH_P_PPPOE_DISC,src_addr)) < 0)
1949    {
1950		fprintf(error_file, "pppoe: unable to create raw socket\n");
1951#ifdef MULTIPLE_PPPOE
1952        exit(1);
1953#else
1954		return 1;
1955#endif
1956    }
1957#ifdef MULTIPLE_PPPOE
1958    /* initiate connection */
1959    if (ppp_ifunit == 0)
1960        fp = fopen(PPP_PPPOE_SESSION, "r");
1961    else /* ifunit == 1 */
1962	fp = fopen(PPP_PPPOE2_SESSION, "r");
1963
1964    if (fp) {
1965#else
1966    /* initiate connection */
1967
1968    /* Foxconn added start Winster Chan 12/05/2005 */
1969    if (!(fp = fopen(PPP_PPPOE_SESSION, "r"))) {
1970        ; /* perror(PPP_PPPOE_SESSION); */ /* foxconn wklin removed, 08/13/2007 */
1971    }
1972    else {
1973#endif
1974        unsigned int nMacAddr[ETH_ALEN];
1975        int nSessId, i;
1976        char cMacAddr[ETH_ALEN];
1977        unsigned short usSessId;
1978
1979        /* Init variables */
1980        for (i=0; i<ETH_ALEN; i++) {
1981            nMacAddr[i] = 0;
1982            cMacAddr[i] = 0x0;
1983        }
1984        nSessId = 0;
1985
1986        /* Get the PPPoE server MAC address and Session ID from file */
1987        if(fgets(buf, sizeof(buf), fp)) {
1988            sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x %d",
1989                &nMacAddr[0], &nMacAddr[1], &nMacAddr[2],
1990                &nMacAddr[3], &nMacAddr[4], &nMacAddr[5],
1991                &nSessId);
1992
1993            /* Transfer types of data */
1994            for (i=0; i<ETH_ALEN; i++) {
1995                cMacAddr[i] = (char)nMacAddr[i];
1996            }
1997            usSessId = (unsigned short)nSessId;
1998
1999            /* Check if the previous MAC address and Session ID exist. */
2000            if (!((cMacAddr[0]==0x0) && (cMacAddr[1]==0x0) && (cMacAddr[2]==0x0) &&
2001                 (cMacAddr[3]==0x0) && (cMacAddr[4]==0x0) && (cMacAddr[5]==0x0)) &&
2002                (htons(usSessId) != 0x0)) {
2003
2004                /* send PADT to server to clear the previous connection */
2005                if ((pkt_size = create_padt(packet, src_addr, cMacAddr,
2006                                    (unsigned short)htons(usSessId))) == 0) {
2007          	        fprintf(stderr, "pppoe: unable to create PADT packet\n");
2008                    fclose(fp);
2009                    /*exit(1);*/
2010#ifdef MULTIPLE_PPPOE
2011                    exit(1);
2012#else
2013                    cleanup_and_exit(1); /* foxconn modified by EricHuang, 05/24/2007 */
2014#endif
2015                }
2016                if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
2017                    fprintf(stderr, "pppoe: unable to send PADT packet\n");
2018                    fclose(fp);
2019#ifdef MULTIPLE_PPPOE
2020                    exit(1);
2021#else
2022                    /*exit(1);*/
2023                    cleanup_and_exit(1); /* foxconn modified by EricHuang, 05/24/2007 */
2024#endif
2025                } else {
2026#ifdef MULTIPLE_PPPOE
2027                    ; /* fprintf(stderr, "PPPOE: PADT sent\n"); */
2028#else
2029                    time(&tm);
2030                    fprintf(stderr, "PPPOE: PADT sent %s\n",ctime(&tm)); /* foxconn wklin added, 07/26/2007 */
2031#endif
2032                }
2033
2034                /* Foxconn modified start, Winster Chan, 06/26/2006 */
2035                /*pptp_pppox_release(&poxfd, &pppfd);*/ /* foxconn removed by EricHuang, 05/24/2007 */
2036                /* Foxconn modified end, Winster Chan, 06/26/2006 */
2037
2038                /* Waiting 3 seconds for server finishing the termination */
2039                sleep(3);
2040            }
2041        }
2042        fclose(fp);
2043    }
2044    /* Foxconn added end Winster Chan 12/05/2005 */
2045#ifdef MULTIPLE_PPPOE
2046    memset(dst_addr, 0, sizeof(dst_addr));
2047
2048resend_padi:
2049#endif
2050    /* start the PPPoE session */
2051    /* foxconn wklin modified, 03/27/2007, add service name */
2052    if ((pkt_size = create_padi(packet, src_addr, service_name)) == 0) {
2053	fprintf(stderr, "pppoe: unable to create PADI packet\n");
2054	exit(1);
2055    }
2056    /* send the PADI packet */
2057    if (send_packet(disc_sock, packet, pkt_size, if_name) < 0) {
2058	fprintf(stderr, "pppoe: unable to send PADI packet\n");
2059	exit(1);
2060    }
2061
2062    time(&tm); /* foxconn wklin added, 12/27/2007 */
2063    /* wait for PADO */
2064    while ((ret_sock = read_packet(disc_sock, packet, &pkt_size)) != disc_sock ||
2065	   (packet->code != CODE_PADO )) { /* foxconn wklin modified, 12/27/2007 */
2066#ifndef MULTIPLE_PPPOE
2067	fprintf(log_file, "pppoe: unexpected packet %x\n",
2068		packet->code);
2069#endif
2070	/* foxconn wklin added start, 12/27/2007 */
2071	if (ret_sock == disc_sock &&
2072		(packet->code == CODE_PADI || packet->code == CODE_PADR)) {
2073	    if (time(NULL) - tm < 3)
2074		continue;
2075
2076	}
2077	/* foxconn wklin added end, 12/27/2007 */
2078	/* wklin added start, 01/10/2007 */
2079    	/* fprintf(stderr, "pppoe: resend PADI\n"); */
2080    	/* start the PPPoE session */
2081        /* foxconn wklin modified, 03/27/2007, add service name */
2082    	if ((pkt_size = create_padi(packet, src_addr, service_name)) == 0) {
2083		fprintf(stderr, "pppoe: unable to create PADI packet\n");
2084		exit(1);
2085    	}
2086    	/* send the PADI packet */
2087    	if (send_packet(disc_sock, packet, pkt_size, if_name) < 0) {
2088		fprintf(stderr, "pppoe: unable to send PADI packet\n");
2089		exit(1);
2090    	}
2091	/* wklin added end, 01/10/2007 */
2092	time(&tm); /* foxconn wklin added, 12/27/2007 */
2093#ifndef MULTIPLE_PPPOE
2094	continue;
2095#endif
2096    }
2097#ifdef MULTIPLE_PPPOE
2098    /* foxconn Bob Guo added start 10/25/2007 */
2099
2100    iOldestTimeStamp = checkServerRecord(packet->ethhdr.h_source);
2101    if(iOldestTimeStamp)
2102    {
2103        packet2 = malloc(PACKETBUF);
2104        if(packet2)
2105        {
2106            while( read_packet(disc_sock, packet2, &pkt2_size) == disc_sock )
2107            {
2108                if(packet2->code == CODE_PADO)
2109                {
2110                    iTimeStamp = checkServerRecord(packet2->ethhdr.h_source);
2111                    if(iTimeStamp < iOldestTimeStamp)
2112                    {
2113                        packet_temp = packet;
2114                        packet = packet2;
2115                        packet2 = packet_temp;
2116                        pkt_size = pkt2_size;
2117                    }
2118                }
2119            }
2120            free(packet2);
2121        }
2122    }
2123    /* foxconn Bob Guo added end 10/25/2007 */
2124#endif
2125    /* Foxconn added start pling 12/20/2006 */
2126    /* Touch a file on /tmp to indicate PADO is received */
2127    if (1)
2128    {
2129        FILE *fp;
2130        struct sysinfo info;
2131#ifdef MULTIPLE_PPPOE
2132        /* fprintf(stderr, "PPPOE%d: PADO received\n", ppp_ifunit); */
2133#else
2134        /* foxconn wklin modified start, 07/26/2007 */
2135        /* system("echo \"DEBUG: PADO received\" > /dev/console"); */
2136        time(&tm);
2137        fprintf(stderr, "PPPOE: PADO received %s\n", ctime(&tm));
2138        /* foxconn wklin modified end, 07/26/2007 */
2139#endif
2140        if ((fp = fopen("/tmp/PADO", "w")) != NULL) {
2141            sysinfo(&info);  /* save current time in file */
2142            fprintf(fp, "%ld", info.uptime);
2143            fclose(fp);
2144        }
2145    }
2146    /* Foxconn added end ling 12/20/2006 */
2147
2148
2149#ifdef __linux__
2150    memcpy(dst_addr, packet->ethhdr.h_source, sizeof(dst_addr));
2151#else
2152    memcpy(dst_addr, packet->ethhdr.ether_shost, sizeof(dst_addr));
2153#endif
2154    /* Foxconn added start Winster Chan 11/25/2005 */
2155    /* Stored tags of PADO */
2156    memset(pado_tags, 0x0, sizeof(pado_tags));
2157    if ((htons(packet->length) < 0) || (htons(packet->length) > sizeof(pado_tags))) {
2158        pado_tag_size = sizeof(pado_tags);
2159    }
2160    else {
2161        pado_tag_size = (int)(htons(packet->length));
2162    }
2163    memcpy((char *)pado_tags, (char *)(packet + 1), pado_tag_size);
2164    /* Foxconn added end Winster Chan 11/25/2005 */
2165
2166    /* send PADR */
2167    /* foxconn wklin modified, 03/27/2007, add service name */
2168    if ((pkt_size = create_padr(packet, src_addr, dst_addr, service_name)) == 0) {
2169	fprintf(stderr, "pppoe: unable to create PADR packet\n");
2170	exit(1);
2171    }
2172    if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
2173	fprintf(stderr, "pppoe: unable to send PADR packet\n");
2174	exit(1);
2175    }
2176
2177    /* foxconn wklin modified start, 07/31/2008 */
2178    /* 0. Process only packets from our target pppoe server.
2179     * 1. track the time when sending PADR.
2180     * 2. If received PADO, resend PADR (needed?).
2181     * 3. If retried for 5 times, send PADT.
2182     * 4. If wait for more than 10 seconds after sending the previous PADR,
2183     *    send PADT.
2184     */
2185    time(&tm);
2186    /* wait for PADS */
2187#ifdef __linux__
2188    while ((ret_sock=read_packet(disc_sock, packet, &pkt_size)) != disc_sock ||
2189            (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr)) != 0) ||
2190            (packet->code != CODE_PADS && packet->code != CODE_PADT))
2191#else
2192    while (read_packet(disc_sock, packet, &pkt_size) != disc_sock ||
2193	   (memcmp(packet->ethhdr.ether_shost,
2194		   dst_addr, sizeof(dst_addr)) != 0))
2195#endif
2196    {
2197        static int retried=0; /* wklin added, 01/26/2007 */
2198
2199        if (ret_sock != disc_sock) {
2200            if (time(NULL)-tm > 10) {
2201                retried = 0;
2202                packet->code = CODE_PADT;  /* fake packet */
2203                break;
2204            }
2205            else
2206                continue;
2207        }
2208        /* Resend PADR only if it's from our target pppoe server and
2209         * the code is PADO, otherwise ignore the received packet.
2210         */
2211        if (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr)) == 0) {
2212            if (packet->code != CODE_PADO) { /* PADI? PADR? */
2213                retried = 0;
2214                packet->code = CODE_PADT; /* fake packet */
2215                break;
2216            }
2217
2218            /* Received PADO */
2219            if (retried++ == 5) {
2220                retried = 0;
2221                packet->code = CODE_PADT;
2222                break;
2223            }
2224
2225            /* Foxconn add start James 04/10/2009 */
2226            /*if we recieve two PADO(from the same MAC) in 2 seconds, we only send one PADR.*/
2227            if (time(NULL) - tm < 2)
2228                continue;
2229            /* Foxconn add end James 04/10/2009 */
2230
2231            /* send PADR */
2232            /* foxconn wklin modified, 03/27/2007, add service name */
2233            if ((pkt_size = create_padr(packet, src_addr, dst_addr, service_name)) == 0) {
2234	        fprintf(stderr, "pppoe: unable to create PADR packet\n");
2235                exit(1);
2236            }
2237            if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) {
2238	        fprintf(stderr, "pppoe: unable to send PADR packet\n");
2239                exit(1);
2240            }
2241            time(&tm); /* track the time when sending PADR */
2242        }
2243        /* else.. packets not from target server */
2244#ifndef MULTIPLE_PPPOE
2245        /* wklin modified end, 01/26/2007 */
2246        continue;
2247#endif
2248    } /* end while waiting PADS */
2249    /* foxconn wklin modified end, 07/31/2008 */
2250
2251    /* foxconn James added start, 11/12/2008 @new_internet_detection */
2252#ifdef NEW_WANDETECT
2253    if (bWanDetect && packet->code == CODE_PADS)
2254    {
2255        FILE *fp;
2256        struct sysinfo info;
2257
2258        time(&tm);
2259        fprintf(stderr, "PPPOE: PADS received %s\n", ctime(&tm));
2260        if ((fp = fopen("/tmp/PADS", "w")) != NULL) {
2261            sysinfo(&info);  /* save current time in file */
2262            fprintf(fp, "%ld", info.uptime);
2263            fclose(fp);
2264        }
2265    }
2266#endif
2267    /* foxconn James added end, 11/12/2008 @new_internet_detection */
2268
2269    if (packet->code == CODE_PADT) /* early termination */
2270    {
2271#ifdef MULTIPLE_PPPOE
2272        sleep(3);
2273        goto resend_padi;
2274#else
2275	    cleanup_and_exit(0);
2276#endif
2277    }
2278
2279    session = packet->session;
2280
2281    /* foxconn wklin added start, 07/31/2007 */
2282    if (session == 0) { /* PADS generic error */
2283        sleep(3); /* wait for 3 seconds and exit, retry */
2284#ifdef MULTIPLE_PPPOE
2285		goto resend_padi;
2286#else
2287	    cleanup_and_exit(0);
2288#endif
2289    }
2290
2291    /* Foxconn add start, Max Ding, 04/23/2009 not use pppd to reduce memory usage */
2292#ifdef NEW_WANDETECT
2293    if (bWanDetect)
2294    {
2295        /* Create PADT to end it */
2296        sigint2(SIGUSR1);
2297        /*cleanup_and_exit(0);*/
2298    }
2299#endif
2300    /* Foxconn add end, Max Ding, 04/23/2009 */
2301
2302    time(&tm);
2303#ifdef MULTIPLE_PPPOE
2304    fprintf(stderr, "PPPOE%d: PADS received (%d) %s\n",
2305            ppp_ifunit, ntohs(session), ctime(&tm));
2306    /* Foxconn Bob Guo added start 10/25/2007*/
2307    updateServerRecord(packet->ethhdr.h_source);
2308    /* Foxconn Bob Guo added end 10/25/2007*/
2309#else
2310    fprintf(stderr, "PPPOE: session id = %d, %s\n", htons(session), ctime(&tm));
2311#endif
2312
2313    /* foxconn wklin added end, 07/31/2007 */
2314
2315    if ((sess_sock = open_interface(if_name,ETH_P_PPPOE_SESS,NULL)) < 0) {
2316    	fprintf(log_file, "pppoe: unable to create raw socket\n");
2317#ifdef MULTIPLE_PPPOE
2318        exit(1);
2319#else
2320    	cleanup_and_exit(1);
2321#endif
2322    }
2323
2324    /* Foxconn added start, Winster Chan, 06/26/2006 */
2325    memcpy(dstMac, dst_addr, ETH_ALEN);
2326    sessId = packet->session;
2327
2328    /* Connect pptp kernel module */
2329
2330#ifdef MULTIPLE_PPPOE
2331    pptp_pppox_open(&poxfd, &pppfd);
2332
2333    if (poxfd == -1) {
2334        fprintf(stderr, "pppoe: poxfd == -1\n");
2335        cleanup_and_exit(1);
2336        /*
2337	    close(poxfd);
2338	    exit(1);*/
2339    }
2340
2341    if (pppfd == -1) {
2342        fprintf(stderr, "pppoe: pppfd == -1\n");
2343        cleanup_and_exit(1);
2344        /*
2345	    close(pppfd);
2346	    exit(1);*/
2347    }
2348
2349    if ( 0 > pptp_pppox_connect(&poxfd, &pppfd)) {
2350        fprintf(stderr, "error connect to pppox\n");
2351        cleanup_and_exit(1);
2352
2353
2354	/*
2355	exit(1);*/
2356    }
2357
2358    if (ppp_ifunit == 0)
2359        fp = fopen(PPP_PPPOE_SESSION, "w+");
2360    else
2361        fp = fopen(PPP_PPPOE2_SESSION, "w+");
2362
2363    if (fp) {
2364        /* Save the PPPoE server MAC address and Session ID */
2365        fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n",
2366            (unsigned char)(dst_addr[0]), (unsigned char)(dst_addr[1]),
2367            (unsigned char)(dst_addr[2]), (unsigned char)(dst_addr[3]),
2368            (unsigned char)(dst_addr[4]), (unsigned char)(dst_addr[5]),
2369            (int)htons(session));
2370        fclose(fp);
2371    }
2372#else
2373
2374    /* foxconn wklin modified start, 07/31/2007 */
2375    if ( 0 > pptp_pppox_connect(&poxfd, &pppfd))
2376        cleanup_and_exit(1);
2377    /* foxconn wklin modified end, 07/31/2007 */
2378    /* Foxconn added end, Winster Chan, 06/26/2006 */
2379
2380    /* Foxconn added start Winster Chan 12/05/2005 */
2381    if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) {
2382        perror(PPP_PPPOE_SESSION);
2383    }
2384    else {
2385        /* Save the PPPoE server MAC address and Session ID */
2386        fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n",
2387            (unsigned char)(dst_addr[0]), (unsigned char)(dst_addr[1]),
2388            (unsigned char)(dst_addr[2]), (unsigned char)(dst_addr[3]),
2389            (unsigned char)(dst_addr[4]), (unsigned char)(dst_addr[5]),
2390            (int)htons(session));
2391        fclose(fp);
2392    }
2393    /* Foxconn added end Winster Chan 12/05/2005 */
2394#endif
2395    clean_child = 0;
2396    signal(SIGCHLD, sigchild);
2397
2398    while (1) {
2399	    FD_ZERO(&allfdset);
2400	    FD_SET(sess_sock, &allfdset);
2401	    FD_SET(disc_sock, &allfdset);
2402	    FD_SET(0, &allfdset);
2403	    if (select((sess_sock>disc_sock?sess_sock:disc_sock) + 1, &allfdset,
2404                    (fd_set *) NULL, (fd_set *) NULL, NULL) <= 0)
2405            continue; /* timeout or error */
2406
2407        if (FD_ISSET(disc_sock, &allfdset)) {
2408#ifdef MULTIPLE_PPPOE
2409            if (read_packet_nowait(disc_sock, packet, &pkt_size) == disc_sock) {
2410		        if (memcmp(packet->ethhdr.h_dest, src_addr, sizeof(src_addr))!=0){
2411		            /* fprintf(stderr, "pppoe: received a packet not for
2412		            * me.\n");*/
2413		            continue;
2414		        }
2415                if (packet->code == CODE_PADT && packet->session == session) {
2416                    time(&tm);
2417                    fprintf(stderr, "PPPOE%d: PADT received (%d) %s\n", ppp_ifunit, ntohs(session), ctime(&tm));
2418                    break; /* go terminate */
2419		        }
2420            }
2421#else
2422            if ((read_packet2(disc_sock, packet, &pkt_size) == disc_sock) &&
2423	       (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr))==0)){
2424                if (packet->code == CODE_PADT) {
2425                    time(&tm);
2426                    fprintf(stderr, "PPPOE: PADT received (%d/%d), %s\n",
2427                        ntohs(packet->session), ntohs(session),ctime(&tm));
2428                }
2429                if (packet->code == CODE_PADT && packet->session == session)
2430                    break; /* cleanup and exit */
2431            }
2432#endif
2433        }
2434
2435        if (FD_ISSET(sess_sock, &allfdset)) {
2436            sess_handler();
2437        }
2438
2439        if (FD_ISSET(0, &allfdset)) {
2440            pppd_handler();
2441        }
2442    }
2443    cleanup_and_exit(0); /* foxconn wklin added, 08/10/2007 */
2444    return 0;
2445}
2446
2447
2448