Increase number of DHCP discover attempts for interoperability
[framework/connectivity/connman.git] / gdhcp / common.h
1 /*
2  *
3  *  DHCP client library with GLib integration
4  *
5  *  Copyright (C) 2009-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <netinet/udp.h>
23 #include <netinet/ip.h>
24
25 #include <glib.h>
26
27 #include "gdhcp.h"
28
29 #define dhcp_get_unaligned(ptr)                 \
30 ({                                              \
31         struct __attribute__((packed)) {        \
32                 typeof(*(ptr)) __v;             \
33         } *__p = (void *) (ptr);                \
34         __p->__v;                               \
35 })
36
37 #define dhcp_put_unaligned(val, ptr)            \
38 do {                                            \
39         struct __attribute__((packed)) {        \
40                 typeof(*(ptr)) __v;             \
41         } *__p = (void *) (ptr);                \
42         __p->__v = (val);                       \
43 } while (0)
44
45 #define CLIENT_PORT 68
46 #define SERVER_PORT 67
47
48 #define EXTEND_FOR_BUGGY_SERVERS 80
49
50 static const uint8_t MAC_BCAST_ADDR[ETH_ALEN] __attribute__((aligned(2))) = {
51         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
52 };
53
54 static const uint8_t MAC_ANY_ADDR[ETH_ALEN] __attribute__((aligned(2))) = {
55         0x00, 0x00, 0x00, 0x00, 0x00, 0x00
56 };
57
58 /* DHCP packet */
59 #define DHCP_MAGIC              0x63825363
60 #define DHCP_OPTIONS_BUFSIZE    308
61 #define BOOTREQUEST             1
62 #define BOOTREPLY               2
63
64 #define BROADCAST_FLAG          0x8000
65
66 /* See RFC 2131 */
67 struct dhcp_packet {
68         uint8_t op;
69         uint8_t htype;
70         uint8_t hlen;
71         uint8_t hops;
72         uint32_t xid;
73         uint16_t secs;
74         uint16_t flags;
75         uint32_t ciaddr;
76         uint32_t yiaddr;
77         uint32_t siaddr_nip;
78         uint32_t gateway_nip;
79         uint8_t chaddr[16];
80         uint8_t sname[64];
81         uint8_t file[128];
82         uint32_t cookie;
83         uint8_t options[DHCP_OPTIONS_BUFSIZE + EXTEND_FOR_BUGGY_SERVERS];
84 } __attribute__((packed));
85
86 struct ip_udp_dhcp_packet {
87         struct iphdr ip;
88         struct udphdr udp;
89         struct dhcp_packet data;
90 } __attribute__((packed));
91
92 /* See RFC 2132 */
93 #define DHCP_PADDING            0x00
94 #define DHCP_SUBNET             0x01
95 #define DHCP_ROUTER             0x03
96 #define DHCP_TIME_SERVER        0x04
97 #define DHCP_NAME_SERVER        0x05
98 #define DHCP_DNS_SERVER         0x06
99 #define DHCP_HOST_NAME          0x0c
100 #define DHCP_DOMAIN_NAME        0x0f
101 #define DHCP_NTP_SERVER         0x2a
102 #define DHCP_REQUESTED_IP       0x32
103 #define DHCP_LEASE_TIME         0x33
104 #define DHCP_OPTION_OVERLOAD    0x34
105 #define DHCP_MESSAGE_TYPE       0x35
106 #define DHCP_SERVER_ID          0x36
107 #define DHCP_PARAM_REQ          0x37
108 #define DHCP_ERR_MESSAGE        0x38
109 #define DHCP_MAX_SIZE           0x39
110 #define DHCP_VENDOR             0x3c
111 #define DHCP_CLIENT_ID          0x3d
112 #define DHCP_END                0xff
113
114 #define OPT_CODE                0
115 #define OPT_LEN                 1
116 #define OPT_DATA                2
117 #define OPTION_FIELD            0
118 #define FILE_FIELD              1
119 #define SNAME_FIELD             2
120
121 /* DHCP_MESSAGE_TYPE values */
122 #define DHCPDISCOVER            1
123 #define DHCPOFFER               2
124 #define DHCPREQUEST             3
125 #define DHCPDECLINE             4
126 #define DHCPACK                 5
127 #define DHCPNAK                 6
128 #define DHCPRELEASE             7
129 #define DHCPINFORM              8
130 #define DHCP_MINTYPE DHCPDISCOVER
131 #define DHCP_MAXTYPE DHCPINFORM
132
133 typedef enum {
134         OPTION_UNKNOWN,
135         OPTION_IP,
136         OPTION_STRING,
137         OPTION_U8,
138         OPTION_U16,
139         OPTION_U32,
140         OPTION_TYPE_MASK = 0x0f,
141         OPTION_LIST = 0x10,
142 } GDHCPOptionType;
143
144 typedef struct dhcp_option {
145         GDHCPOptionType type;
146         uint8_t code;
147 } DHCPOption;
148
149 /* Length of the option types in binary form */
150 static const uint8_t dhcp_option_lengths[] = {
151         [OPTION_IP]     = 4,
152         [OPTION_STRING] = 1,
153         [OPTION_U8]     = 1,
154         [OPTION_U16]    = 2,
155         [OPTION_U32]    = 4,
156 };
157
158 uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code);
159 int dhcp_end_option(uint8_t *optionptr);
160 void dhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt);
161 void dhcp_add_simple_option(struct dhcp_packet *packet,
162                                 uint8_t code, uint32_t data);
163 GDHCPOptionType dhcp_get_code_type(uint8_t code);
164
165 uint16_t dhcp_checksum(void *addr, int count);
166
167 void dhcp_init_header(struct dhcp_packet *packet, char type);
168
169 int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
170                         uint32_t source_ip, int source_port,
171                         uint32_t dest_ip, int dest_port,
172                         const uint8_t *dest_arp, int ifindex);
173 int dhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
174                         uint32_t source_ip, int source_port,
175                         uint32_t dest_ip, int dest_port);
176 int dhcp_l3_socket(int port, const char *interface);
177 int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd);
178 char *get_interface_name(int index);
179 gboolean interface_is_up(int index);