|  | /* | 
|  | * | 
|  | *  DHCP client library with GLib integration | 
|  | * | 
|  | *  Copyright (C) 2009-2012  Intel Corporation. All rights reserved. | 
|  | * | 
|  | *  This program is free software; you can redistribute it and/or modify | 
|  | *  it under the terms of the GNU General Public License version 2 as | 
|  | *  published by the Free Software Foundation. | 
|  | * | 
|  | *  This program is distributed in the hope that it will be useful, | 
|  | *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | *  GNU General Public License for more details. | 
|  | * | 
|  | *  You should have received a copy of the GNU General Public License | 
|  | *  along with this program; if not, write to the Free Software | 
|  | *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include <netinet/udp.h> | 
|  | #include <netinet/ip.h> | 
|  |  | 
|  | #include <glib.h> | 
|  |  | 
|  | #include "unaligned.h" | 
|  | #include "gdhcp.h" | 
|  |  | 
|  | #define CLIENT_PORT 68 | 
|  | #define SERVER_PORT 67 | 
|  |  | 
|  | #define DHCPV6_CLIENT_PORT 546 | 
|  | #define DHCPV6_SERVER_PORT 547 | 
|  | #define MAX_DHCPV6_PKT_SIZE 1500 | 
|  |  | 
|  | #define EXTEND_FOR_BUGGY_SERVERS 80 | 
|  |  | 
|  | static const uint8_t MAC_BCAST_ADDR[ETH_ALEN] __attribute__((aligned(2))) = { | 
|  | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 
|  | }; | 
|  |  | 
|  | static const uint8_t MAC_ANY_ADDR[ETH_ALEN] __attribute__((aligned(2))) = { | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 
|  | }; | 
|  |  | 
|  | /* DHCP packet */ | 
|  | #define DHCP_MAGIC              0x63825363 | 
|  | #define DHCP_OPTIONS_BUFSIZE    308 | 
|  | #define BOOTREQUEST             1 | 
|  | #define BOOTREPLY               2 | 
|  |  | 
|  | #define BROADCAST_FLAG		0x8000 | 
|  |  | 
|  | /* See RFC 2131 */ | 
|  | struct dhcp_packet { | 
|  | uint8_t op; | 
|  | uint8_t htype; | 
|  | uint8_t hlen; | 
|  | uint8_t hops; | 
|  | uint32_t xid; | 
|  | uint16_t secs; | 
|  | uint16_t flags; | 
|  | uint32_t ciaddr; | 
|  | uint32_t yiaddr; | 
|  | uint32_t siaddr_nip; | 
|  | uint32_t gateway_nip; | 
|  | uint8_t chaddr[16]; | 
|  | uint8_t sname[64]; | 
|  | uint8_t file[128]; | 
|  | uint32_t cookie; | 
|  | uint8_t options[DHCP_OPTIONS_BUFSIZE + EXTEND_FOR_BUGGY_SERVERS]; | 
|  | } __attribute__((packed)); | 
|  |  | 
|  | struct ip_udp_dhcp_packet { | 
|  | struct iphdr ip; | 
|  | struct udphdr udp; | 
|  | struct dhcp_packet data; | 
|  | } __attribute__((packed)); | 
|  |  | 
|  | /* See RFC 3315 */ | 
|  | struct dhcpv6_packet { | 
|  | uint8_t message; | 
|  | uint8_t transaction_id[3]; | 
|  | uint8_t options[]; | 
|  | } __attribute__((packed)); | 
|  |  | 
|  |  | 
|  | /* See RFC 2132 */ | 
|  | #define DHCP_PADDING		0x00 | 
|  | #define DHCP_SUBNET		0x01 | 
|  | #define DHCP_ROUTER		0x03 | 
|  | #define DHCP_TIME_SERVER	0x04 | 
|  | #define DHCP_NAME_SERVER	0x05 | 
|  | #define DHCP_DNS_SERVER		0x06 | 
|  | #define DHCP_HOST_NAME		0x0c | 
|  | #define DHCP_DOMAIN_NAME	0x0f | 
|  | #define DHCP_NTP_SERVER		0x2a | 
|  | #define DHCP_REQUESTED_IP	0x32 | 
|  | #define DHCP_LEASE_TIME		0x33 | 
|  | #define DHCP_OPTION_OVERLOAD	0x34 | 
|  | #define DHCP_MESSAGE_TYPE	0x35 | 
|  | #define DHCP_SERVER_ID		0x36 | 
|  | #define DHCP_PARAM_REQ		0x37 | 
|  | #define DHCP_ERR_MESSAGE	0x38 | 
|  | #define DHCP_MAX_SIZE		0x39 | 
|  | #define DHCP_VENDOR		0x3c | 
|  | #define DHCP_CLIENT_ID		0x3d | 
|  | #define DHCP_END		0xff | 
|  |  | 
|  | #define OPT_CODE		0 | 
|  | #define OPT_LEN			1 | 
|  | #define OPT_DATA		2 | 
|  | #define OPTION_FIELD		0 | 
|  | #define FILE_FIELD		1 | 
|  | #define SNAME_FIELD		2 | 
|  |  | 
|  | /* DHCP_MESSAGE_TYPE values */ | 
|  | #define DHCPDISCOVER		1 | 
|  | #define DHCPOFFER		2 | 
|  | #define DHCPREQUEST		3 | 
|  | #define DHCPDECLINE		4 | 
|  | #define DHCPACK			5 | 
|  | #define DHCPNAK			6 | 
|  | #define DHCPRELEASE		7 | 
|  | #define DHCPINFORM		8 | 
|  | #define DHCP_MINTYPE DHCPDISCOVER | 
|  | #define DHCP_MAXTYPE DHCPINFORM | 
|  |  | 
|  | /* Message types for DHCPv6, RFC 3315 sec 5.3 */ | 
|  | #define DHCPV6_SOLICIT		1 | 
|  | #define DHCPV6_ADVERTISE	2 | 
|  | #define DHCPV6_REQUEST		3 | 
|  | #define DHCPV6_CONFIRM		4 | 
|  | #define DHCPV6_RENEW		5 | 
|  | #define DHCPV6_REBIND		6 | 
|  | #define DHCPV6_REPLY		7 | 
|  | #define DHCPV6_RELEASE		8 | 
|  | #define DHCPV6_DECLINE		9 | 
|  | #define DHCPV6_RECONFIGURE	10 | 
|  | #define DHCPV6_INFORMATION_REQ	11 | 
|  |  | 
|  | /* | 
|  | * DUID time starts 2000-01-01. | 
|  | */ | 
|  | #define DUID_TIME_EPOCH 946684800 | 
|  |  | 
|  | typedef enum { | 
|  | OPTION_UNKNOWN, | 
|  | OPTION_IP, | 
|  | OPTION_STRING, | 
|  | OPTION_U8, | 
|  | OPTION_U16, | 
|  | OPTION_U32, | 
|  | OPTION_TYPE_MASK = 0x0f, | 
|  | OPTION_LIST = 0x10, | 
|  | } GDHCPOptionType; | 
|  |  | 
|  | typedef struct dhcp_option { | 
|  | GDHCPOptionType type; | 
|  | uint8_t code; | 
|  | } DHCPOption; | 
|  |  | 
|  | /* Length of the option types in binary form */ | 
|  | static const uint8_t dhcp_option_lengths[] = { | 
|  | [OPTION_IP]	= 4, | 
|  | [OPTION_STRING]	= 1, | 
|  | [OPTION_U8]	= 1, | 
|  | [OPTION_U16]	= 2, | 
|  | [OPTION_U32]	= 4, | 
|  | }; | 
|  |  | 
|  | uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code); | 
|  | uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len, | 
|  | int code, uint16_t *option_len, int *option_count); | 
|  | uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len, | 
|  | uint16_t *code, uint16_t *option_len); | 
|  | int dhcp_end_option(uint8_t *optionptr); | 
|  | void dhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt); | 
|  | void dhcpv6_add_binary_option(struct dhcpv6_packet *packet, uint16_t max_len, | 
|  | uint16_t *pkt_len, uint8_t *addopt); | 
|  | void dhcp_add_option_uint8(struct dhcp_packet *packet, | 
|  | uint8_t code, uint8_t data); | 
|  | void dhcp_add_option_uint16(struct dhcp_packet *packet, | 
|  | uint8_t code, uint16_t data); | 
|  | void dhcp_add_option_uint32(struct dhcp_packet *packet, | 
|  | uint8_t code, uint32_t data); | 
|  | GDHCPOptionType dhcp_get_code_type(uint8_t code); | 
|  | GDHCPOptionType dhcpv6_get_code_type(uint16_t code); | 
|  |  | 
|  | uint16_t dhcp_checksum(void *addr, int count); | 
|  |  | 
|  | void dhcp_init_header(struct dhcp_packet *packet, char type); | 
|  | void dhcpv6_init_header(struct dhcpv6_packet *packet, uint8_t type); | 
|  |  | 
|  | int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | 
|  | uint32_t source_ip, int source_port, | 
|  | uint32_t dest_ip, int dest_port, | 
|  | const uint8_t *dest_arp, int ifindex, | 
|  | bool bcast); | 
|  | int dhcpv6_send_packet(int index, struct dhcpv6_packet *dhcp_pkt, int len); | 
|  | int dhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 
|  | uint32_t source_ip, int source_port, | 
|  | uint32_t dest_ip, int dest_port, int fd); | 
|  | int dhcp_l3_socket(int port, const char *interface, int family); | 
|  | int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd); | 
|  | int dhcpv6_recv_l3_packet(struct dhcpv6_packet **packet, unsigned char *buf, | 
|  | int buf_len, int fd); | 
|  | int dhcp_l3_socket_send(int index, int port, int family); | 
|  |  | 
|  | char *get_interface_name(int index); | 
|  | bool interface_is_up(int index); |