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