1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17#include <stdio.h>
18#include <sys/time.h>
19#include <sys/types.h>
20#include <sys/file.h>
21#include <unistd.h>
22#include <getopt.h>
23#include <stdlib.h>
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#include <signal.h>
28#include <time.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <net/if.h>
32#include <errno.h>
33#include <netinet/udp.h>
34#include <netinet/ip.h>
35#include <netpacket/packet.h>
36//#include <net/ethernet.h>
37#include <features.h>
38
39#include <sys/uio.h>
40#include <fcntl.h>
41#include <sys/cdefs.h>
42#include <net/ppp_defs.h>
43#include <net/if_ppp.h>
44#include <linux/if_ether.h>
45//#include <netinet/if_ether.h>
46#include <ctype.h>
47
48#define eprintf(fmt, args...) do{\
49	FILE *ffp = fopen("/tmp/detect_wrong.log", "a+");\
50	if(ffp) {\
51		fprintf(ffp, fmt, ## args);\
52		fclose(ffp);\
53	}\
54}while(0)
55
56/************************************/
57/* Defaults _you_ may want to tweak */
58/************************************/
59
60/* the period of time the client is allowed to use that address */
61#define LEASE_TIME              (60*60*24*10) /* 10 days of seconds */
62
63/* where to find the DHCP server configuration file */
64#define DHCPD_CONF_FILE         "/etc/udhcpd.conf"
65
66/*****************************************************************/
67/* Do not modify below here unless you know what you are doing!! */
68/*****************************************************************/
69
70/* DHCP protocol -- see RFC 2131 */
71#define SERVER_PORT             67
72#define CLIENT_PORT             68
73
74#define DHCP_MAGIC              0x63825363
75
76/* DHCP option codes (partial list) */
77#define DHCP_PADDING            0x00
78#define DHCP_SUBNET             0x01
79#define DHCP_TIME_OFFSET        0x02
80#define DHCP_ROUTER             0x03
81#define DHCP_TIME_SERVER        0x04
82#define DHCP_NAME_SERVER        0x05
83#define DHCP_DNS_SERVER         0x06
84#define DHCP_LOG_SERVER         0x07
85#define DHCP_COOKIE_SERVER      0x08
86#define DHCP_LPR_SERVER         0x09
87#define DHCP_HOST_NAME          0x0c
88#define DHCP_BOOT_SIZE          0x0d
89#define DHCP_DOMAIN_NAME        0x0f
90#define DHCP_SWAP_SERVER        0x10
91#define DHCP_ROOT_PATH          0x11
92#define DHCP_IP_TTL             0x17
93#define DHCP_MTU                0x1a
94#define DHCP_BROADCAST          0x1c
95#define DHCP_NTP_SERVER         0x2a
96#define DHCP_WINS_SERVER        0x2c
97#define DHCP_REQUESTED_IP       0x32
98#define DHCP_LEASE_TIME         0x33
99#define DHCP_OPTION_OVER        0x34
100#define DHCP_MESSAGE_TYPE       0x35
101#define DHCP_SERVER_ID          0x36
102#define DHCP_PARAM_REQ          0x37
103#define DHCP_MESSAGE            0x38
104#define DHCP_MAX_SIZE           0x39
105#define DHCP_T1                 0x3a
106#define DHCP_T2                 0x3b
107#define DHCP_VENDOR             0x3c
108#define DHCP_CLIENT_ID          0x3d
109
110#define DHCP_END                0xFF
111
112
113#define BOOTREQUEST             1
114#define BOOTREPLY               2
115
116#define ETH_10MB                1
117#define ETH_10MB_LEN            6
118#define DHCPDISCOVER            1
119#define DHCPOFFER               2
120#define DHCPREQUEST             3
121#define DHCPDECLINE             4
122#define DHCPACK                 5
123#define DHCPNAK                 6
124#define DHCPRELEASE             7
125#define DHCPINFORM              8
126
127#define BROADCAST_FLAG          0x8000
128
129#define OPTION_FIELD            0
130#define FILE_FIELD              1
131#define SNAME_FIELD             2
132
133/* miscellaneous defines */
134#define MAC_BCAST_ADDR          (unsigned char *) "\xff\xff\xff\xff\xff\xff"
135#define OPT_CODE 0
136#define OPT_LEN 1
137#define OPT_DATA 2
138
139#define INIT_SELECTING  0
140#define REQUESTING      1
141#define BOUND           2
142#define RENEWING        3
143#define REBINDING       4
144#define INIT_REBOOT     5
145#define RENEW_REQUESTED 6
146#define RELEASED        7
147#define DEFAULT_SCRIPT  "/usr/share/udhcpc/default.script"
148#define VERSION "0.9.8-pre"
149
150struct client_config_t {
151        char foreground;                /* Do not fork */
152        char quit_after_lease;          /* Quit after obtaining lease */
153        char abort_if_no_lease;         /* Abort if no lease */
154        char background_if_no_lease;    /* Fork to background if no lease */
155        char *interface;                /* The name of the interface to use */
156        char *pidfile;                  /* Optionally store the process ID */
157        char *script;                   /* User script to run at dhcp events */
158        unsigned char *clientid;        /* Optional client id to use */
159        unsigned char *hostname;        /* Optional hostname to use */
160        int ifindex;                    /* Index number of the interface to use */
161        unsigned char arp[6];           /* Our arp address */
162};
163
164static struct client_config_t client_config;
165
166struct dhcpMessage {
167        u_int8_t op;
168        u_int8_t htype;
169        u_int8_t hlen;
170        u_int8_t hops;
171        u_int32_t xid;
172        u_int16_t secs;
173        u_int16_t flags;
174        u_int32_t ciaddr;
175        u_int32_t yiaddr;
176        u_int32_t siaddr;
177        u_int32_t giaddr;
178        u_int8_t chaddr[16];
179        u_int8_t sname[64];
180        u_int8_t file[128];
181        u_int32_t cookie;
182        u_int8_t options[308]; /* 312 - cookie */
183};
184
185struct udp_dhcp_packet {
186        struct iphdr ip;
187        struct udphdr udp;
188        struct dhcpMessage data;
189};
190
191#define TYPE_MASK       0x0F
192
193enum {
194        OPTION_IP=1,
195        OPTION_IP_PAIR,
196        OPTION_STRING,
197        OPTION_BOOLEAN,
198        OPTION_U8,
199        OPTION_U16,
200        OPTION_S16,
201        OPTION_U32,
202        OPTION_S32
203};
204
205#define OPTION_REQ      0x10 /* have the client request this option */
206#define OPTION_LIST     0x20 /* There can be a list of 1 or more of these */
207
208struct dhcp_option {
209        char name[10];
210        char flags;
211        unsigned char code;
212};
213
214static int state;
215//static unsigned long requested_ip; /* = 0 */
216//static unsigned long server_addr;
217//static unsigned long timeout;
218//static int packet_num; /* = 0 */
219static int cfd;
220//static int signal_pipe[2];
221
222#define LISTEN_NONE 0
223#define LISTEN_KERNEL 1
224#define LISTEN_RAW 2
225static int listen_mode;
226
227/* supported options are easily added here */
228static struct dhcp_option options[] = {
229        /* name[10]     flags                                   code */
230        {"subnet",      OPTION_IP | OPTION_REQ,                 0x01},
231        {"timezone",    OPTION_S32,                             0x02},
232        {"router",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x03},
233        {"timesvr",     OPTION_IP | OPTION_LIST,                0x04},
234        {"namesvr",     OPTION_IP | OPTION_LIST,                0x05},
235        {"dns",         OPTION_IP | OPTION_LIST | OPTION_REQ,   0x06},
236        {"logsvr",      OPTION_IP | OPTION_LIST,                0x07},
237        {"cookiesvr",   OPTION_IP | OPTION_LIST,                0x08},
238        {"lprsvr",      OPTION_IP | OPTION_LIST,                0x09},
239        {"hostname",    OPTION_STRING | OPTION_REQ,             0x0c},
240        {"bootsize",    OPTION_U16,                             0x0d},
241        {"domain",      OPTION_STRING | OPTION_REQ,             0x0f},
242        {"swapsvr",     OPTION_IP,                              0x10},
243        {"rootpath",    OPTION_STRING,                          0x11},
244        {"ipttl",       OPTION_U8,                              0x17},
245        {"mtu",         OPTION_U16,                             0x1a},
246        {"broadcast",   OPTION_IP | OPTION_REQ,                 0x1c},
247        {"ntpsrv",      OPTION_IP | OPTION_LIST,                0x2a},
248        {"wins",        OPTION_IP | OPTION_LIST | OPTION_REQ,   0x2c},
249        {"requestip",   OPTION_IP,                              0x32},
250        {"lease",       OPTION_U32,                             0x33},
251        {"dhcptype",    OPTION_U8,                              0x35},
252        {"serverid",    OPTION_IP,                              0x36},
253        {"message",     OPTION_STRING,                          0x38},
254        {"tftp",        OPTION_STRING,                          0x42},
255        {"bootfile",    OPTION_STRING,                          0x43},
256        {"",            0x00,                                   0x00}
257};
258
259/* Lengths of the different option types */
260static int option_lengths[] = {
261        [OPTION_IP] =           4,
262        [OPTION_IP_PAIR] =      8,
263        [OPTION_BOOLEAN] =      1,
264        [OPTION_STRING] =       1,
265        [OPTION_U8] =           1,
266        [OPTION_U16] =          2,
267        [OPTION_S16] =          2,
268        [OPTION_U32] =          4,
269        [OPTION_S32] =          4
270};
271
272u_int16_t checksum(void *addr, int count);
273
274int listen_socket(unsigned int ip, int port, char *inf);
275
276int raw_socket(int ifindex);
277int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port,
278                   u_int32_t dest_ip, int dest_port, unsigned char *dest_arp, int ifindex);
279
280unsigned char *get_option(struct dhcpMessage *packet, int code);
281int get_packet(struct dhcpMessage *packet, int fd);
282int get_raw_packet(struct dhcpMessage *payload, int fd);
283int end_option(unsigned char *optionptr);
284
285int add_option_string(unsigned char *optionptr, unsigned char *string);
286
287int add_simple_option(unsigned char *optionptr, unsigned char code, u_int32_t data);
288
289void init_header(struct dhcpMessage *packet, char type);
290
291//static void init_packet(struct dhcpMessage *packet, char type);
292
293//static void add_requests(struct dhcpMessage *packet);
294
295int send_dhcp_discover(unsigned long xid);
296
297int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp);
298
299unsigned long random_xid(void);
300
301//static void change_mode(int new_mode);
302
303
304/**********************************   ppp   *************************************************/
305
306char DEFAULT_IF[16];
307#define BPF_BUFFER_IS_EMPTY 1
308#define BPF_BUFFER_HAS_DATA 0
309
310typedef unsigned short UINT16_t;
311
312typedef unsigned int UINT32_t;
313
314/* Ethernet frame types according to RFC 2516 */
315#define ETH_PPPOE_DISCOVERY 0x8863
316#define ETH_PPPOE_SESSION   0x8864
317
318/* But some brain-dead peers disobey the RFC, so frame types are variables */
319
320static UINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY;
321static UINT16_t Eth_PPPOE_Session   = ETH_PPPOE_SESSION;
322
323/* PPPoE codes */
324#define CODE_PADI           0x09
325#define CODE_PADO           0x07
326#define CODE_PADR           0x19
327#define CODE_PADS           0x65
328#define CODE_PADT           0xA7
329
330/* Extensions from draft-carrel-info-pppoe-ext-00 */
331/* I do NOT like PADM or PADN, but they are here for completeness */
332#define CODE_PADM           0xD3
333#define CODE_PADN           0xD4
334
335#define CODE_SESS           0x00
336
337/* PPPoE Tags */
338#define TAG_END_OF_LIST        0x0000
339#define TAG_SERVICE_NAME       0x0101
340#define TAG_AC_NAME            0x0102
341#define TAG_HOST_UNIQ          0x0103
342#define TAG_AC_COOKIE          0x0104
343#define TAG_VENDOR_SPECIFIC    0x0105
344#define TAG_RELAY_SESSION_ID   0x0110
345#define TAG_SERVICE_NAME_ERROR 0x0201
346#define TAG_AC_SYSTEM_ERROR    0x0202
347#define TAG_GENERIC_ERROR      0x0203
348
349/* Extensions from draft-carrel-info-pppoe-ext-00 */
350/* I do NOT like these tags one little bit */
351#define TAG_HURL               0x111
352#define TAG_MOTM               0x112
353#define TAG_IP_ROUTE_ADD       0x121
354/* Discovery phase states */
355#define STATE_SENT_PADI     0
356#define STATE_RECEIVED_PADO 1
357#define STATE_SENT_PADR     2
358#define STATE_SESSION       3
359#define STATE_TERMINATED    4
360
361/* How many PADI/PADS attempts? */
362#define MAX_PADI_ATTEMPTS 3
363
364/* Initial timeout for PADO/PADS */
365#define PADI_TIMEOUT 5
366/* States for scanning PPP frames */
367#define STATE_WAITFOR_FRAME_ADDR 0
368#define STATE_DROP_PROTO         1
369#define STATE_BUILDING_PACKET    2
370
371/* Special PPP frame characters */
372#define FRAME_ESC    0x7D
373#define FRAME_FLAG   0x7E
374#define FRAME_ADDR   0xFF
375#define FRAME_CTRL   0x03
376#define FRAME_ENC    0x20
377
378#define IPV4ALEN     4
379#define SMALLBUF   256
380
381/* A PPPoE Packet, including Ethernet headers */
382typedef struct PPPoEPacketStruct {
383    struct ethhdr ethHdr;       /* Ethernet header */
384//#ifdef PACK_BITFIELDS_REVERSED
385//    unsigned int type:4;        /* PPPoE Type (must be 1) */
386//    unsigned int ver:4;         /* PPPoE Version (must be 1) */
387//#else
388    unsigned int ver:4;         /* PPPoE Version (must be 1) */
389    unsigned int type:4;        /* PPPoE Type (must be 1) */
390//#endif
391    unsigned int code:8;        /* PPPoE code */
392    unsigned int session:16;    /* PPPoE session */
393    unsigned int length:16;     /* Payload length */
394    unsigned char payload[ETH_DATA_LEN]; /* A bit of room to spare */
395} PPPoEPacket;
396
397/* Header size of a PPPoE packet */
398#define PPPOE_OVERHEAD 6  /* type, code, session, length */
399#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD)
400#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD)
401#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - 2)
402
403/* PPPoE Tag */
404
405typedef struct PPPoETagStruct {
406    unsigned int type:16;       /* tag type */
407    unsigned int length:16;     /* Length of payload */
408    unsigned char payload[ETH_DATA_LEN]; /* A LOT of room to spare */
409} PPPoETag;
410
411/* Header size of a PPPoE tag */
412#define TAG_HDR_SIZE 4
413
414/* Chunk to read from stdin */
415#define READ_CHUNK 4096
416
417/* Function passed to parsePacket */
418typedef void ParseFunc(UINT16_t type,
419                       UINT16_t len,
420                       unsigned char *data,
421                       void *extra);
422
423#define PPPINITFCS16    0xffff  /* Initial FCS value */
424
425/* Keep track of the state of a connection -- collect everything in
426   one spot */
427
428typedef struct PPPoEConnectionStruct {
429    int discoveryState;         /* Where we are in discovery */
430    int discoverySocket;        /* Raw socket for discovery frames */
431    int sessionSocket;          /* Raw socket for session frames */
432    unsigned char myEth[ETH_ALEN]; /* My MAC address */
433    unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */
434    UINT16_t session;           /* Session ID */
435    char *ifName;               /* Interface name */
436    char *serviceName;          /* Desired service name, if any */
437    char *acName;               /* Desired AC name, if any */
438    int synchronous;            /* Use synchronous PPP */
439    int useHostUniq;            /* Use Host-Uniq tag */
440    int printACNames;           /* Just print AC names */
441    int skipDiscovery;          /* Skip discovery */
442    int noDiscoverySocket;      /* Don't even open discovery socket */
443    int killSession;            /* Kill session and exit */
444    FILE *debugFile;            /* Debug file for dumping packets */
445    int numPADOs;               /* Number of PADO packets received */
446    PPPoETag cookie;            /* We have to send this if we get it */
447    PPPoETag relayId;           /* Ditto */
448} PPPoEConnection;
449/* Structure used to determine acceptable PADO or PADS packet */
450struct PacketCriteria {
451    PPPoEConnection *conn;
452    int acNameOK;
453    int serviceNameOK;
454    int seenACName;
455    int seenServiceName;
456};
457
458#define CHECK_ROOM(cursor, start, len) \
459do {\
460    if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \
461        fprintf(stderr, "Would create too-long packet\n"); \
462        return; \
463    } \
464} while(0)
465
466/* True if Ethernet address is broadcast or multicast */
467#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)
468#define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF)
469#define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF)
470
471static char const RCSID[] =
472"$Id: dp.h,v 1.1.1.1 2008/07/21 09:20:37 james26_jang Exp $";
473
474
475char *strDup(char const *str);
476
477#define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0);
478
479int
480openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr);
481
482void
483dumpHex(FILE *fp, unsigned char const *buf, int len);
484
485UINT16_t
486etherType(PPPoEPacket *packet);
487
488//void
489//dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir);
490
491int
492parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra);
493
494void
495parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
496                 void *extra);
497
498int
499packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet);
500
501void
502parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
503              void *extra);
504
505int
506sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size);
507
508int
509receivePacket(int sock, PPPoEPacket *pkt, int *size);
510
511void
512sendPADI(PPPoEConnection *conn);
513
514void
515waitForPADO(PPPoEConnection *conn, int timeout);
516
517void
518discovery(PPPoEConnection *conn);
519
520int discover_all();
521