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