xref: /aosp_15_r20/external/toybox/toys/pending/dhcpd.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* dhcpd.c - DHCP server for dynamic network configuration.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Madhur Verma <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2015 Yeongdeok Suh <[email protected]>
6*cf5a6c84SAndroid Build Coastguard Worker  *
7*cf5a6c84SAndroid Build Coastguard Worker  * No Standard
8*cf5a6c84SAndroid Build Coastguard Worker USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker config DHCPD
11*cf5a6c84SAndroid Build Coastguard Worker   bool "dhcpd"
12*cf5a6c84SAndroid Build Coastguard Worker   default n
13*cf5a6c84SAndroid Build Coastguard Worker   help
14*cf5a6c84SAndroid Build Coastguard Worker    usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     -f    Run in foreground
17*cf5a6c84SAndroid Build Coastguard Worker     -i Interface to use
18*cf5a6c84SAndroid Build Coastguard Worker     -S    Log to syslog too
19*cf5a6c84SAndroid Build Coastguard Worker     -P N  Use port N (default ipv4 67, ipv6 547)
20*cf5a6c84SAndroid Build Coastguard Worker     -4, -6    Run as a DHCPv4 or DHCPv6 server
21*cf5a6c84SAndroid Build Coastguard Worker 
22*cf5a6c84SAndroid Build Coastguard Worker config DEBUG_DHCP
23*cf5a6c84SAndroid Build Coastguard Worker   bool "debugging messeges ON/OFF"
24*cf5a6c84SAndroid Build Coastguard Worker   default n
25*cf5a6c84SAndroid Build Coastguard Worker   depends on DHCPD
26*cf5a6c84SAndroid Build Coastguard Worker */
27*cf5a6c84SAndroid Build Coastguard Worker 
28*cf5a6c84SAndroid Build Coastguard Worker /*
29*cf5a6c84SAndroid Build Coastguard Worker  * TODO
30*cf5a6c84SAndroid Build Coastguard Worker  * - Working as an relay agent
31*cf5a6c84SAndroid Build Coastguard Worker  * - Rapid commit option support
32*cf5a6c84SAndroid Build Coastguard Worker  * - Additional packet options (commented on the middle of sources)
33*cf5a6c84SAndroid Build Coastguard Worker  * - Create common modules
34*cf5a6c84SAndroid Build Coastguard Worker  */
35*cf5a6c84SAndroid Build Coastguard Worker 
36*cf5a6c84SAndroid Build Coastguard Worker #define FOR_dhcpd
37*cf5a6c84SAndroid Build Coastguard Worker 
38*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
39*cf5a6c84SAndroid Build Coastguard Worker #include <linux/sockios.h>
40*cf5a6c84SAndroid Build Coastguard Worker #include <linux/if_ether.h>
41*cf5a6c84SAndroid Build Coastguard Worker 
42*cf5a6c84SAndroid Build Coastguard Worker // Todo: headers not in posix
43*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip.h>
44*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip6.h>
45*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/udp.h>
46*cf5a6c84SAndroid Build Coastguard Worker #include <netpacket/packet.h>
47*cf5a6c84SAndroid Build Coastguard Worker 
48*cf5a6c84SAndroid Build Coastguard Worker #if CFG_DEBUG_DHCP==1
49*cf5a6c84SAndroid Build Coastguard Worker # define dbg(fmt, arg...)   printf(fmt, ##arg)
50*cf5a6c84SAndroid Build Coastguard Worker #else
51*cf5a6c84SAndroid Build Coastguard Worker # define dbg(fmt, arg...)
52*cf5a6c84SAndroid Build Coastguard Worker #endif
53*cf5a6c84SAndroid Build Coastguard Worker 
54*cf5a6c84SAndroid Build Coastguard Worker #define LOG_SILENT          0x0
55*cf5a6c84SAndroid Build Coastguard Worker #define LOG_CONSOLE         0x1
56*cf5a6c84SAndroid Build Coastguard Worker #define LOG_SYSTEM          0x2
57*cf5a6c84SAndroid Build Coastguard Worker 
58*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_MAGIC          0x63825363
59*cf5a6c84SAndroid Build Coastguard Worker 
60*cf5a6c84SAndroid Build Coastguard Worker #define DHCPDISCOVER        1
61*cf5a6c84SAndroid Build Coastguard Worker #define DHCPOFFER           2
62*cf5a6c84SAndroid Build Coastguard Worker #define DHCPREQUEST         3
63*cf5a6c84SAndroid Build Coastguard Worker #define DHCPDECLINE         4
64*cf5a6c84SAndroid Build Coastguard Worker #define DHCPACK             5
65*cf5a6c84SAndroid Build Coastguard Worker #define DHCPNAK             6
66*cf5a6c84SAndroid Build Coastguard Worker #define DHCPRELEASE         7
67*cf5a6c84SAndroid Build Coastguard Worker #define DHCPINFORM          8
68*cf5a6c84SAndroid Build Coastguard Worker 
69*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6SOLICIT        1
70*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6ADVERTISE      2   // server -> client
71*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REQUEST        3
72*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6CONFIRM        4
73*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RENEW          5
74*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REBIND         6
75*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REPLY          7   // server -> client
76*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELEASE        8
77*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6DECLINE        9
78*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RECONFIGURE    10  // server -> client
79*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6INFOREQUEST    11
80*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELAYFLOW      12  // relay -> relay/server
81*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELAYREPLY     13  // server/relay -> relay
82*cf5a6c84SAndroid Build Coastguard Worker 
83*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_NUM8           (1<<8)
84*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_NUM16          (1<<9)
85*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_NUM32          DHCP_NUM16 | DHCP_NUM8
86*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_STRING         (1<<10)
87*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_STRLST         (1<<11)
88*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_IP             (1<<12)
89*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_IPLIST         (1<<13)
90*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_IPPLST         (1<<14)
91*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_STCRTS         (1<<15)
92*cf5a6c84SAndroid Build Coastguard Worker 
93*cf5a6c84SAndroid Build Coastguard Worker // DHCP option codes (partial list). See RFC 2132 and
94*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_PADDING                          0x00
95*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_HOST_NAME          DHCP_STRING | 0x0c // either client informs server or server gives name to client
96*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_REQUESTED_IP       DHCP_IP     | 0x32 // sent by client if specific IP is wanted
97*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_LEASE_TIME         DHCP_NUM32  | 0x33
98*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_OPTION_OVERLOAD                  0x34
99*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_MESSAGE_TYPE       DHCP_NUM8   | 0x35
100*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_SERVER_ID          DHCP_IP     | 0x36 // by default server's IP
101*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_PARAM_REQ          DHCP_STRING | 0x37 // list of options client wants
102*cf5a6c84SAndroid Build Coastguard Worker #define DHCP_OPT_END                              0xff
103*cf5a6c84SAndroid Build Coastguard Worker 
104*cf5a6c84SAndroid Build Coastguard Worker // DHCPv6 option codes (partial). See RFC 3315
105*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_CLIENTID      1
106*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_SERVERID      2
107*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_NA         3
108*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_ADDR       5
109*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_ORO           6
110*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_PREFERENCE    7
111*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_ELAPSED_TIME  8
112*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_RELAY_MSG     9
113*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_STATUS_CODE   13
114*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_PD         25
115*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_PREFIX     26
116*cf5a6c84SAndroid Build Coastguard Worker 
117*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_STATUS_SUCCESS        0
118*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_STATUS_NOADDRSAVAIL   2
119*cf5a6c84SAndroid Build Coastguard Worker 
120*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_LLT    1
121*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_EN     2
122*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_LL     3
123*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_UUID   4
124*cf5a6c84SAndroid Build Coastguard Worker 
125*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
126*cf5a6c84SAndroid Build Coastguard Worker   char *i;
127*cf5a6c84SAndroid Build Coastguard Worker   long p;
128*cf5a6c84SAndroid Build Coastguard Worker )
129*cf5a6c84SAndroid Build Coastguard Worker 
130*cf5a6c84SAndroid Build Coastguard Worker struct config_keyword {
131*cf5a6c84SAndroid Build Coastguard Worker   char *keyword;
132*cf5a6c84SAndroid Build Coastguard Worker   int (*handler)(const char *str, void *var);
133*cf5a6c84SAndroid Build Coastguard Worker   void *var;
134*cf5a6c84SAndroid Build Coastguard Worker   char *def;
135*cf5a6c84SAndroid Build Coastguard Worker };
136*cf5a6c84SAndroid Build Coastguard Worker 
137*cf5a6c84SAndroid Build Coastguard Worker typedef struct dhcp_msg_s {
138*cf5a6c84SAndroid Build Coastguard Worker   char op, htype, hlen, hops;
139*cf5a6c84SAndroid Build Coastguard Worker   unsigned xid;
140*cf5a6c84SAndroid Build Coastguard Worker   unsigned short secs, flags;
141*cf5a6c84SAndroid Build Coastguard Worker   unsigned ciaddr, yiaddr, nsiaddr, ngiaddr;
142*cf5a6c84SAndroid Build Coastguard Worker   char chaddr[16], sname[64], file[128];
143*cf5a6c84SAndroid Build Coastguard Worker   unsigned cookie;
144*cf5a6c84SAndroid Build Coastguard Worker   char options[308];
145*cf5a6c84SAndroid Build Coastguard Worker } dhcp_msg_t;
146*cf5a6c84SAndroid Build Coastguard Worker 
147*cf5a6c84SAndroid Build Coastguard Worker typedef struct dhcp6_msg_s {
148*cf5a6c84SAndroid Build Coastguard Worker   char msgtype, transaction_id[3], options[524];
149*cf5a6c84SAndroid Build Coastguard Worker } dhcp6_msg_t;
150*cf5a6c84SAndroid Build Coastguard Worker 
151*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) dhcp_raw_s {
152*cf5a6c84SAndroid Build Coastguard Worker   struct iphdr iph;
153*cf5a6c84SAndroid Build Coastguard Worker   struct udphdr udph;
154*cf5a6c84SAndroid Build Coastguard Worker   dhcp_msg_t dhcp;
155*cf5a6c84SAndroid Build Coastguard Worker } dhcp_raw_t;
156*cf5a6c84SAndroid Build Coastguard Worker 
157*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) dhcp6_raw_s {
158*cf5a6c84SAndroid Build Coastguard Worker   struct ip6_hdr iph;
159*cf5a6c84SAndroid Build Coastguard Worker   struct udphdr udph;
160*cf5a6c84SAndroid Build Coastguard Worker   dhcp6_msg_t dhcp6;
161*cf5a6c84SAndroid Build Coastguard Worker } dhcp6_raw_t;
162*cf5a6c84SAndroid Build Coastguard Worker 
163*cf5a6c84SAndroid Build Coastguard Worker typedef struct static_lease_s {
164*cf5a6c84SAndroid Build Coastguard Worker   struct static_lease_s *next;
165*cf5a6c84SAndroid Build Coastguard Worker   unsigned nip;
166*cf5a6c84SAndroid Build Coastguard Worker   int mac[6];
167*cf5a6c84SAndroid Build Coastguard Worker } static_lease;
168*cf5a6c84SAndroid Build Coastguard Worker 
169*cf5a6c84SAndroid Build Coastguard Worker typedef struct static_lease6_s {
170*cf5a6c84SAndroid Build Coastguard Worker   struct static_lease6_s *next;
171*cf5a6c84SAndroid Build Coastguard Worker   unsigned short duid_len, ia_type;
172*cf5a6c84SAndroid Build Coastguard Worker   unsigned iaid;
173*cf5a6c84SAndroid Build Coastguard Worker   char nip6[16], duid[20];
174*cf5a6c84SAndroid Build Coastguard Worker } static_lease6;
175*cf5a6c84SAndroid Build Coastguard Worker 
176*cf5a6c84SAndroid Build Coastguard Worker typedef struct {
177*cf5a6c84SAndroid Build Coastguard Worker   unsigned expires, lease_nip;
178*cf5a6c84SAndroid Build Coastguard Worker   char lease_mac[6], hostname[20], pad[2];
179*cf5a6c84SAndroid Build Coastguard Worker } dyn_lease;
180*cf5a6c84SAndroid Build Coastguard Worker 
181*cf5a6c84SAndroid Build Coastguard Worker typedef struct {
182*cf5a6c84SAndroid Build Coastguard Worker   unsigned short duid_len, ia_type;
183*cf5a6c84SAndroid Build Coastguard Worker   unsigned expires, iaid;
184*cf5a6c84SAndroid Build Coastguard Worker   char lease_nip6[16], duid[20];
185*cf5a6c84SAndroid Build Coastguard Worker } dyn_lease6;
186*cf5a6c84SAndroid Build Coastguard Worker 
187*cf5a6c84SAndroid Build Coastguard Worker typedef struct option_val_s {
188*cf5a6c84SAndroid Build Coastguard Worker   char *key;
189*cf5a6c84SAndroid Build Coastguard Worker   unsigned short code;
190*cf5a6c84SAndroid Build Coastguard Worker   void *val;
191*cf5a6c84SAndroid Build Coastguard Worker   size_t len;
192*cf5a6c84SAndroid Build Coastguard Worker } option_val_t;
193*cf5a6c84SAndroid Build Coastguard Worker 
194*cf5a6c84SAndroid Build Coastguard Worker struct optval_duid_llt {
195*cf5a6c84SAndroid Build Coastguard Worker   unsigned short type, hwtype;
196*cf5a6c84SAndroid Build Coastguard Worker   unsigned time;
197*cf5a6c84SAndroid Build Coastguard Worker   char lladdr[];
198*cf5a6c84SAndroid Build Coastguard Worker };
199*cf5a6c84SAndroid Build Coastguard Worker 
200*cf5a6c84SAndroid Build Coastguard Worker struct optval_ia_na {
201*cf5a6c84SAndroid Build Coastguard Worker   unsigned iaid, t1, t2;
202*cf5a6c84SAndroid Build Coastguard Worker   char optval[];
203*cf5a6c84SAndroid Build Coastguard Worker };
204*cf5a6c84SAndroid Build Coastguard Worker 
205*cf5a6c84SAndroid Build Coastguard Worker struct optval_ia_addr {
206*cf5a6c84SAndroid Build Coastguard Worker   char ipv6_addr[16];
207*cf5a6c84SAndroid Build Coastguard Worker   unsigned pref_lifetime, valid_lifetime;
208*cf5a6c84SAndroid Build Coastguard Worker };
209*cf5a6c84SAndroid Build Coastguard Worker struct optval_status_code {
210*cf5a6c84SAndroid Build Coastguard Worker   unsigned short status_code;
211*cf5a6c84SAndroid Build Coastguard Worker   char status_msg[];
212*cf5a6c84SAndroid Build Coastguard Worker };
213*cf5a6c84SAndroid Build Coastguard Worker 
214*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((__may_alias__)) server_config_s {
215*cf5a6c84SAndroid Build Coastguard Worker   char *interface;                // interface to use
216*cf5a6c84SAndroid Build Coastguard Worker   int ifindex;
217*cf5a6c84SAndroid Build Coastguard Worker   uint8_t server_nip6[16];
218*cf5a6c84SAndroid Build Coastguard Worker   uint32_t server_nip;
219*cf5a6c84SAndroid Build Coastguard Worker   uint32_t port;
220*cf5a6c84SAndroid Build Coastguard Worker   uint8_t server_mac[6];          // our MAC address (used only for ARP probing)
221*cf5a6c84SAndroid Build Coastguard Worker   void *options[256];             // list of DHCP options loaded from the config file
222*cf5a6c84SAndroid Build Coastguard Worker   /* start,end are in host order: we need to compare start <= ip <= end*/
223*cf5a6c84SAndroid Build Coastguard Worker   uint32_t start_ip;              // start address of leases, in host order
224*cf5a6c84SAndroid Build Coastguard Worker   uint32_t end_ip;                // end of leases, in host order
225*cf5a6c84SAndroid Build Coastguard Worker   uint8_t start_ip6[16];          // start address of leases, in IPv6 mode
226*cf5a6c84SAndroid Build Coastguard Worker   uint8_t end_ip6[16];            // end of leases, in IPv6 mode
227*cf5a6c84SAndroid Build Coastguard Worker   uint32_t max_lease_sec;         // maximum lease time (host order)
228*cf5a6c84SAndroid Build Coastguard Worker   uint32_t min_lease_sec;         // minimum lease time a client can request
229*cf5a6c84SAndroid Build Coastguard Worker   uint32_t max_leases;            // maximum number of leases (including reserved addresses)
230*cf5a6c84SAndroid Build Coastguard Worker   uint32_t auto_time;             // how long should dhcpd wait before writing a config file.
231*cf5a6c84SAndroid Build Coastguard Worker                                   // if this is zero, it will only write one on SIGUSR1
232*cf5a6c84SAndroid Build Coastguard Worker   uint32_t decline_time;          // how long an address is reserved if a client returns a
233*cf5a6c84SAndroid Build Coastguard Worker                                   // decline message
234*cf5a6c84SAndroid Build Coastguard Worker   uint32_t conflict_time;         // how long an arp conflict offender is leased for
235*cf5a6c84SAndroid Build Coastguard Worker   uint32_t offer_time;            // how long an offered address is reserved
236*cf5a6c84SAndroid Build Coastguard Worker   uint32_t siaddr_nip;            // "next server" bootp option
237*cf5a6c84SAndroid Build Coastguard Worker   char *lease_file;
238*cf5a6c84SAndroid Build Coastguard Worker   char *lease6_file;
239*cf5a6c84SAndroid Build Coastguard Worker   char *pidfile;
240*cf5a6c84SAndroid Build Coastguard Worker   char *notify_file;              // what to run whenever leases are written
241*cf5a6c84SAndroid Build Coastguard Worker   char *sname;                    // bootp server name
242*cf5a6c84SAndroid Build Coastguard Worker   char *boot_file;                // bootp boot file option
243*cf5a6c84SAndroid Build Coastguard Worker   uint32_t pref_lifetime;
244*cf5a6c84SAndroid Build Coastguard Worker   uint32_t valid_lifetime;
245*cf5a6c84SAndroid Build Coastguard Worker   uint32_t t1,t2;
246*cf5a6c84SAndroid Build Coastguard Worker   struct static_lease *static_leases; // List of ip/mac pairs to assign static leases
247*cf5a6c84SAndroid Build Coastguard Worker } server_config_t;
248*cf5a6c84SAndroid Build Coastguard Worker 
249*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((__may_alias__)) server_state_s {
250*cf5a6c84SAndroid Build Coastguard Worker   uint8_t client_nip6[16];
251*cf5a6c84SAndroid Build Coastguard Worker   uint32_t client_port;
252*cf5a6c84SAndroid Build Coastguard Worker   uint8_t rqcode;
253*cf5a6c84SAndroid Build Coastguard Worker   int listensock;
254*cf5a6c84SAndroid Build Coastguard Worker   union {
255*cf5a6c84SAndroid Build Coastguard Worker     dhcp_msg_t rcvd_pkt;
256*cf5a6c84SAndroid Build Coastguard Worker     dhcp6_msg_t rcvd_pkt6;
257*cf5a6c84SAndroid Build Coastguard Worker   } rcvd;
258*cf5a6c84SAndroid Build Coastguard Worker   uint8_t* rqopt;
259*cf5a6c84SAndroid Build Coastguard Worker   union {
260*cf5a6c84SAndroid Build Coastguard Worker     dhcp_msg_t send_pkt;
261*cf5a6c84SAndroid Build Coastguard Worker     dhcp6_msg_t send_pkt6;
262*cf5a6c84SAndroid Build Coastguard Worker   } send;
263*cf5a6c84SAndroid Build Coastguard Worker   union {
264*cf5a6c84SAndroid Build Coastguard Worker     static_lease *sleases;
265*cf5a6c84SAndroid Build Coastguard Worker     static_lease6 *sleases6;
266*cf5a6c84SAndroid Build Coastguard Worker   } leases;
267*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *dleases;
268*cf5a6c84SAndroid Build Coastguard Worker } server_state_t;
269*cf5a6c84SAndroid Build Coastguard Worker 
270*cf5a6c84SAndroid Build Coastguard Worker static option_val_t options_list[] = {
271*cf5a6c84SAndroid Build Coastguard Worker     {"lease"          , DHCP_NUM32  | 0x33, NULL, 0},
272*cf5a6c84SAndroid Build Coastguard Worker     {"subnet"         , DHCP_IP     | 0x01, NULL, 0},
273*cf5a6c84SAndroid Build Coastguard Worker     {"broadcast"      , DHCP_IP     | 0x1c, NULL, 0},
274*cf5a6c84SAndroid Build Coastguard Worker     {"router"         , DHCP_IP     | 0x03, NULL, 0},
275*cf5a6c84SAndroid Build Coastguard Worker     {"ipttl"          , DHCP_NUM8   | 0x17, NULL, 0},
276*cf5a6c84SAndroid Build Coastguard Worker     {"mtu"            , DHCP_NUM16  | 0x1a, NULL, 0},
277*cf5a6c84SAndroid Build Coastguard Worker     {"hostname"       , DHCP_STRING | 0x0c, NULL, 0},
278*cf5a6c84SAndroid Build Coastguard Worker     {"domain"         , DHCP_STRING | 0x0f, NULL, 0},
279*cf5a6c84SAndroid Build Coastguard Worker     {"search"         , DHCP_STRLST | 0x77, NULL, 0},
280*cf5a6c84SAndroid Build Coastguard Worker     {"nisdomain"      , DHCP_STRING | 0x28, NULL, 0},
281*cf5a6c84SAndroid Build Coastguard Worker     {"timezone"       , DHCP_NUM32  | 0x02, NULL, 0},
282*cf5a6c84SAndroid Build Coastguard Worker     {"tftp"           , DHCP_STRING | 0x42, NULL, 0},
283*cf5a6c84SAndroid Build Coastguard Worker     {"bootfile"       , DHCP_STRING | 0x43, NULL, 0},
284*cf5a6c84SAndroid Build Coastguard Worker     {"bootsize"       , DHCP_NUM16  | 0x0d, NULL, 0},
285*cf5a6c84SAndroid Build Coastguard Worker     {"rootpath"       , DHCP_STRING | 0x11, NULL, 0},
286*cf5a6c84SAndroid Build Coastguard Worker     {"wpad"           , DHCP_STRING | 0xfc, NULL, 0},
287*cf5a6c84SAndroid Build Coastguard Worker     {"serverid"       , DHCP_IP     | 0x36, NULL, 0},
288*cf5a6c84SAndroid Build Coastguard Worker     {"message"        , DHCP_STRING | 0x38, NULL, 0},
289*cf5a6c84SAndroid Build Coastguard Worker     {"vlanid"         , DHCP_NUM32  | 0x84, NULL, 0},
290*cf5a6c84SAndroid Build Coastguard Worker     {"vlanpriority"   , DHCP_NUM32  | 0x85, NULL, 0},
291*cf5a6c84SAndroid Build Coastguard Worker     {"dns"            , DHCP_IPLIST | 0x06, NULL, 0},
292*cf5a6c84SAndroid Build Coastguard Worker     {"wins"           , DHCP_IPLIST | 0x2c, NULL, 0},
293*cf5a6c84SAndroid Build Coastguard Worker     {"nissrv"         , DHCP_IPLIST | 0x29, NULL, 0},
294*cf5a6c84SAndroid Build Coastguard Worker     {"ntpsrv"         , DHCP_IPLIST | 0x2a, NULL, 0},
295*cf5a6c84SAndroid Build Coastguard Worker     {"lprsrv"         , DHCP_IPLIST | 0x09, NULL, 0},
296*cf5a6c84SAndroid Build Coastguard Worker     {"swapsrv"        , DHCP_IP     | 0x10, NULL, 0},
297*cf5a6c84SAndroid Build Coastguard Worker     {"routes"         , DHCP_STCRTS | 0x21, NULL, 0},
298*cf5a6c84SAndroid Build Coastguard Worker     {"staticroutes"   , DHCP_STCRTS | 0x79, NULL, 0},
299*cf5a6c84SAndroid Build Coastguard Worker     {"msstaticroutes" , DHCP_STCRTS | 0xf9, NULL, 0},
300*cf5a6c84SAndroid Build Coastguard Worker };
301*cf5a6c84SAndroid Build Coastguard Worker 
302*cf5a6c84SAndroid Build Coastguard Worker struct fd_pair { int rd; int wr; };
303*cf5a6c84SAndroid Build Coastguard Worker static server_config_t gconfig;
304*cf5a6c84SAndroid Build Coastguard Worker static server_state_t gstate;
305*cf5a6c84SAndroid Build Coastguard Worker static uint8_t infomode;
306*cf5a6c84SAndroid Build Coastguard Worker static struct fd_pair sigfd;
307*cf5a6c84SAndroid Build Coastguard Worker static int constone = 1;
308*cf5a6c84SAndroid Build Coastguard Worker static sa_family_t addr_version = AF_INET;
309*cf5a6c84SAndroid Build Coastguard Worker 
310*cf5a6c84SAndroid Build Coastguard Worker // calculate options size.
dhcp_opt_size(uint8_t * optionptr)311*cf5a6c84SAndroid Build Coastguard Worker static int dhcp_opt_size(uint8_t *optionptr)
312*cf5a6c84SAndroid Build Coastguard Worker {
313*cf5a6c84SAndroid Build Coastguard Worker   int i = 0;
314*cf5a6c84SAndroid Build Coastguard Worker   for(;optionptr[i] != 0xff; i++)
315*cf5a6c84SAndroid Build Coastguard Worker     if(optionptr[i] != 0x00) i += optionptr[i + 1] + 2 -1;
316*cf5a6c84SAndroid Build Coastguard Worker   return i;
317*cf5a6c84SAndroid Build Coastguard Worker }
318*cf5a6c84SAndroid Build Coastguard Worker 
319*cf5a6c84SAndroid Build Coastguard Worker // calculates checksum for dhcp messeges.
dhcp_checksum(void * addr,int count)320*cf5a6c84SAndroid Build Coastguard Worker static uint16_t dhcp_checksum(void *addr, int count)
321*cf5a6c84SAndroid Build Coastguard Worker {
322*cf5a6c84SAndroid Build Coastguard Worker   int32_t sum = 0;
323*cf5a6c84SAndroid Build Coastguard Worker   uint16_t tmp = 0, *source = (uint16_t *)addr;
324*cf5a6c84SAndroid Build Coastguard Worker 
325*cf5a6c84SAndroid Build Coastguard Worker   while (count > 1)  {
326*cf5a6c84SAndroid Build Coastguard Worker     sum += *source++;
327*cf5a6c84SAndroid Build Coastguard Worker     count -= 2;
328*cf5a6c84SAndroid Build Coastguard Worker   }
329*cf5a6c84SAndroid Build Coastguard Worker   if (count > 0) {
330*cf5a6c84SAndroid Build Coastguard Worker     *(uint8_t*)&tmp = *(uint8_t*)source;
331*cf5a6c84SAndroid Build Coastguard Worker     sum += tmp;
332*cf5a6c84SAndroid Build Coastguard Worker   }
333*cf5a6c84SAndroid Build Coastguard Worker   while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
334*cf5a6c84SAndroid Build Coastguard Worker   return ~sum;
335*cf5a6c84SAndroid Build Coastguard Worker }
336*cf5a6c84SAndroid Build Coastguard Worker 
337*cf5a6c84SAndroid Build Coastguard Worker // gets information of INTERFACE and updates IFINDEX, MAC and IP
get_interface(const char * interface,int * ifindex,void * oip,uint8_t * mac)338*cf5a6c84SAndroid Build Coastguard Worker static int get_interface(const char *interface, int *ifindex, void *oip,
339*cf5a6c84SAndroid Build Coastguard Worker     uint8_t *mac)
340*cf5a6c84SAndroid Build Coastguard Worker {
341*cf5a6c84SAndroid Build Coastguard Worker   struct ifreq req;
342*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in *ip;
343*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6 ip6;
344*cf5a6c84SAndroid Build Coastguard Worker   int fd = xsocket(addr_version, SOCK_RAW, IPPROTO_RAW);
345*cf5a6c84SAndroid Build Coastguard Worker   char ipv6_addr[40] = {0,};
346*cf5a6c84SAndroid Build Coastguard Worker 
347*cf5a6c84SAndroid Build Coastguard Worker   req.ifr_addr.sa_family = addr_version;
348*cf5a6c84SAndroid Build Coastguard Worker   xstrncpy(req.ifr_name, (char *)interface, IFNAMSIZ);
349*cf5a6c84SAndroid Build Coastguard Worker 
350*cf5a6c84SAndroid Build Coastguard Worker   xioctl(fd, SIOCGIFFLAGS, &req);
351*cf5a6c84SAndroid Build Coastguard Worker 
352*cf5a6c84SAndroid Build Coastguard Worker   if (!(req.ifr_flags & IFF_UP)) return -1;
353*cf5a6c84SAndroid Build Coastguard Worker 
354*cf5a6c84SAndroid Build Coastguard Worker   if (addr_version == AF_INET6) {
355*cf5a6c84SAndroid Build Coastguard Worker 
356*cf5a6c84SAndroid Build Coastguard Worker     FILE *fd6 = fopen("/proc/net/if_inet6", "r");
357*cf5a6c84SAndroid Build Coastguard Worker     uint8_t *oip6 = (uint8_t*)oip;
358*cf5a6c84SAndroid Build Coastguard Worker     int i;
359*cf5a6c84SAndroid Build Coastguard Worker 
360*cf5a6c84SAndroid Build Coastguard Worker     while(fgets(toybuf, sizeof(toybuf), fd6)) {
361*cf5a6c84SAndroid Build Coastguard Worker       if (!strstr(toybuf, interface))
362*cf5a6c84SAndroid Build Coastguard Worker         continue;
363*cf5a6c84SAndroid Build Coastguard Worker 
364*cf5a6c84SAndroid Build Coastguard Worker       if (sscanf(toybuf, "%32s \n", ipv6_addr) == 1)
365*cf5a6c84SAndroid Build Coastguard Worker         break;
366*cf5a6c84SAndroid Build Coastguard Worker     }
367*cf5a6c84SAndroid Build Coastguard Worker     fclose(fd6);
368*cf5a6c84SAndroid Build Coastguard Worker 
369*cf5a6c84SAndroid Build Coastguard Worker     if (oip6) {
370*cf5a6c84SAndroid Build Coastguard Worker       char *ptr = ipv6_addr+sizeof(ipv6_addr)-1;
371*cf5a6c84SAndroid Build Coastguard Worker 
372*cf5a6c84SAndroid Build Coastguard Worker       // convert giant hex string into colon-spearated ipv6 address by
373*cf5a6c84SAndroid Build Coastguard Worker       // inserting ':' every 4 characters.
374*cf5a6c84SAndroid Build Coastguard Worker       for (i = 32; i; i--)
375*cf5a6c84SAndroid Build Coastguard Worker         if ((*(ptr--) = ipv6_addr[i])) if (!(i&3)) *(ptr--) = ':';
376*cf5a6c84SAndroid Build Coastguard Worker 
377*cf5a6c84SAndroid Build Coastguard Worker       dbg("ipv6 %s\n", ipv6_addr);
378*cf5a6c84SAndroid Build Coastguard Worker       if(inet_pton(AF_INET6, ipv6_addr, &ip6.sin6_addr) <= 0)
379*cf5a6c84SAndroid Build Coastguard Worker         error_msg("inet : the ipv6 address is not proper");
380*cf5a6c84SAndroid Build Coastguard Worker       else
381*cf5a6c84SAndroid Build Coastguard Worker         memcpy(oip6, ip6.sin6_addr.s6_addr32, sizeof(uint32_t)*4);
382*cf5a6c84SAndroid Build Coastguard Worker     }
383*cf5a6c84SAndroid Build Coastguard Worker   } else {
384*cf5a6c84SAndroid Build Coastguard Worker     uint32_t *oip4 = (uint32_t*)oip;
385*cf5a6c84SAndroid Build Coastguard Worker     if (oip4) {
386*cf5a6c84SAndroid Build Coastguard Worker       xioctl(fd, SIOCGIFADDR, &req);
387*cf5a6c84SAndroid Build Coastguard Worker       ip = (struct sockaddr_in*) &req.ifr_addr;
388*cf5a6c84SAndroid Build Coastguard Worker       dbg("IP %s\n", inet_ntoa(ip->sin_addr));
389*cf5a6c84SAndroid Build Coastguard Worker       *oip4 = ntohl(ip->sin_addr.s_addr);
390*cf5a6c84SAndroid Build Coastguard Worker     }
391*cf5a6c84SAndroid Build Coastguard Worker   }
392*cf5a6c84SAndroid Build Coastguard Worker 
393*cf5a6c84SAndroid Build Coastguard Worker   if (ifindex) {
394*cf5a6c84SAndroid Build Coastguard Worker     xioctl(fd, SIOCGIFINDEX, &req);
395*cf5a6c84SAndroid Build Coastguard Worker     dbg("Adapter index %d\n", req.ifr_ifindex);
396*cf5a6c84SAndroid Build Coastguard Worker     *ifindex = req.ifr_ifindex;
397*cf5a6c84SAndroid Build Coastguard Worker   }
398*cf5a6c84SAndroid Build Coastguard Worker   if (mac) {
399*cf5a6c84SAndroid Build Coastguard Worker     xioctl(fd, SIOCGIFHWADDR, &req);
400*cf5a6c84SAndroid Build Coastguard Worker     memcpy(mac, req.ifr_hwaddr.sa_data, 6);
401*cf5a6c84SAndroid Build Coastguard Worker     dbg("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
402*cf5a6c84SAndroid Build Coastguard Worker   }
403*cf5a6c84SAndroid Build Coastguard Worker 
404*cf5a6c84SAndroid Build Coastguard Worker   close(fd);
405*cf5a6c84SAndroid Build Coastguard Worker   return 0;
406*cf5a6c84SAndroid Build Coastguard Worker }
407*cf5a6c84SAndroid Build Coastguard Worker 
408*cf5a6c84SAndroid Build Coastguard Worker /*
409*cf5a6c84SAndroid Build Coastguard Worker  *logs messeges to syslog or console
410*cf5a6c84SAndroid Build Coastguard Worker  *opening the log is still left with applet.
411*cf5a6c84SAndroid Build Coastguard Worker  *FIXME: move to more relevent lib. probably libc.c
412*cf5a6c84SAndroid Build Coastguard Worker  */
infomsg(uint8_t infomode,char * s,...)413*cf5a6c84SAndroid Build Coastguard Worker static void infomsg(uint8_t infomode, char *s, ...)
414*cf5a6c84SAndroid Build Coastguard Worker {
415*cf5a6c84SAndroid Build Coastguard Worker   int used;
416*cf5a6c84SAndroid Build Coastguard Worker   char *msg;
417*cf5a6c84SAndroid Build Coastguard Worker   va_list p, t;
418*cf5a6c84SAndroid Build Coastguard Worker 
419*cf5a6c84SAndroid Build Coastguard Worker   if (infomode == LOG_SILENT) return;
420*cf5a6c84SAndroid Build Coastguard Worker   va_start(p, s);
421*cf5a6c84SAndroid Build Coastguard Worker   va_copy(t, p);
422*cf5a6c84SAndroid Build Coastguard Worker   used = vsnprintf(NULL, 0, s, t);
423*cf5a6c84SAndroid Build Coastguard Worker   used++;
424*cf5a6c84SAndroid Build Coastguard Worker   va_end(t);
425*cf5a6c84SAndroid Build Coastguard Worker 
426*cf5a6c84SAndroid Build Coastguard Worker   msg = xmalloc(used);
427*cf5a6c84SAndroid Build Coastguard Worker   vsnprintf(msg, used, s, p);
428*cf5a6c84SAndroid Build Coastguard Worker   va_end(p);
429*cf5a6c84SAndroid Build Coastguard Worker 
430*cf5a6c84SAndroid Build Coastguard Worker   if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg);
431*cf5a6c84SAndroid Build Coastguard Worker   if (infomode & LOG_CONSOLE) printf("%s\n", msg);
432*cf5a6c84SAndroid Build Coastguard Worker   free(msg);
433*cf5a6c84SAndroid Build Coastguard Worker }
434*cf5a6c84SAndroid Build Coastguard Worker 
435*cf5a6c84SAndroid Build Coastguard Worker /*
436*cf5a6c84SAndroid Build Coastguard Worker  * Writes self PID in file PATH
437*cf5a6c84SAndroid Build Coastguard Worker  * FIXME: libc implementation only writes in /var/run
438*cf5a6c84SAndroid Build Coastguard Worker  * this is more generic as some implemenation may provide
439*cf5a6c84SAndroid Build Coastguard Worker  * arguments to write in specific file. as dhcpd does.
440*cf5a6c84SAndroid Build Coastguard Worker  */
write_pid(char * path)441*cf5a6c84SAndroid Build Coastguard Worker static void write_pid(char *path)
442*cf5a6c84SAndroid Build Coastguard Worker {
443*cf5a6c84SAndroid Build Coastguard Worker   int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
444*cf5a6c84SAndroid Build Coastguard Worker   if (pidfile > 0) {
445*cf5a6c84SAndroid Build Coastguard Worker     char pidbuf[12];
446*cf5a6c84SAndroid Build Coastguard Worker 
447*cf5a6c84SAndroid Build Coastguard Worker     sprintf(pidbuf, "%u", (unsigned)getpid());
448*cf5a6c84SAndroid Build Coastguard Worker     write(pidfile, pidbuf, strlen(pidbuf));
449*cf5a6c84SAndroid Build Coastguard Worker     close(pidfile);
450*cf5a6c84SAndroid Build Coastguard Worker   }
451*cf5a6c84SAndroid Build Coastguard Worker }
452*cf5a6c84SAndroid Build Coastguard Worker 
453*cf5a6c84SAndroid Build Coastguard Worker // Generic signal handler real handling is done in main funcrion.
signal_handler(int sig)454*cf5a6c84SAndroid Build Coastguard Worker static void signal_handler(int sig)
455*cf5a6c84SAndroid Build Coastguard Worker {
456*cf5a6c84SAndroid Build Coastguard Worker   unsigned char ch = sig;
457*cf5a6c84SAndroid Build Coastguard Worker   if (write(sigfd.wr, &ch, 1) != 1) dbg("can't send signal\n");
458*cf5a6c84SAndroid Build Coastguard Worker }
459*cf5a6c84SAndroid Build Coastguard Worker 
460*cf5a6c84SAndroid Build Coastguard Worker // signal setup for SIGUSR1 SIGTERM
setup_signal()461*cf5a6c84SAndroid Build Coastguard Worker static int setup_signal()
462*cf5a6c84SAndroid Build Coastguard Worker {
463*cf5a6c84SAndroid Build Coastguard Worker   if (pipe((int *)&sigfd) < 0) {
464*cf5a6c84SAndroid Build Coastguard Worker     dbg("signal pipe failed\n");
465*cf5a6c84SAndroid Build Coastguard Worker     return -1;
466*cf5a6c84SAndroid Build Coastguard Worker   }
467*cf5a6c84SAndroid Build Coastguard Worker   fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC);
468*cf5a6c84SAndroid Build Coastguard Worker   fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC);
469*cf5a6c84SAndroid Build Coastguard Worker   int flags = fcntl(sigfd.wr, F_GETFL);
470*cf5a6c84SAndroid Build Coastguard Worker   fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK);
471*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGUSR1, signal_handler);
472*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGTERM, signal_handler);
473*cf5a6c84SAndroid Build Coastguard Worker   return 0;
474*cf5a6c84SAndroid Build Coastguard Worker }
475*cf5a6c84SAndroid Build Coastguard Worker 
476*cf5a6c84SAndroid Build Coastguard Worker // String STR to UINT32 conversion strored in VAR
strtou32(const char * str,void * var)477*cf5a6c84SAndroid Build Coastguard Worker static int strtou32(const char *str, void *var)
478*cf5a6c84SAndroid Build Coastguard Worker {
479*cf5a6c84SAndroid Build Coastguard Worker   char *endptr = NULL;
480*cf5a6c84SAndroid Build Coastguard Worker   int base = 10;
481*cf5a6c84SAndroid Build Coastguard Worker   errno=0;
482*cf5a6c84SAndroid Build Coastguard Worker   *((uint32_t*)(var)) = 0;
483*cf5a6c84SAndroid Build Coastguard Worker   if (str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
484*cf5a6c84SAndroid Build Coastguard Worker     base = 16;
485*cf5a6c84SAndroid Build Coastguard Worker     str+=2;
486*cf5a6c84SAndroid Build Coastguard Worker   }
487*cf5a6c84SAndroid Build Coastguard Worker 
488*cf5a6c84SAndroid Build Coastguard Worker   long ret_val = strtol(str, &endptr, base);
489*cf5a6c84SAndroid Build Coastguard Worker   if (errno) infomsg(infomode, "config : Invalid num %s",str);
490*cf5a6c84SAndroid Build Coastguard Worker   else if (endptr && (*endptr!='\0'||endptr == str))
491*cf5a6c84SAndroid Build Coastguard Worker       infomsg(infomode, "config : Not a valid num %s",str);
492*cf5a6c84SAndroid Build Coastguard Worker   else *((uint32_t*)(var)) = (uint32_t)ret_val;
493*cf5a6c84SAndroid Build Coastguard Worker   return 0;
494*cf5a6c84SAndroid Build Coastguard Worker }
495*cf5a6c84SAndroid Build Coastguard Worker 
496*cf5a6c84SAndroid Build Coastguard Worker // copy string STR in variable VAR
strinvar(const char * str,void * var)497*cf5a6c84SAndroid Build Coastguard Worker static int strinvar(const char *str, void *var)
498*cf5a6c84SAndroid Build Coastguard Worker {
499*cf5a6c84SAndroid Build Coastguard Worker   char **dest = var;
500*cf5a6c84SAndroid Build Coastguard Worker   if (*dest) free(*dest);
501*cf5a6c84SAndroid Build Coastguard Worker   *dest = strdup(str);
502*cf5a6c84SAndroid Build Coastguard Worker   return 0;
503*cf5a6c84SAndroid Build Coastguard Worker }
504*cf5a6c84SAndroid Build Coastguard Worker 
505*cf5a6c84SAndroid Build Coastguard Worker // IP String STR to binary data.
striptovar(const char * str,void * var)506*cf5a6c84SAndroid Build Coastguard Worker static int striptovar(const char *str, void *var)
507*cf5a6c84SAndroid Build Coastguard Worker {
508*cf5a6c84SAndroid Build Coastguard Worker   *((uint32_t*)(var)) = 0;
509*cf5a6c84SAndroid Build Coastguard Worker   if(!str) {
510*cf5a6c84SAndroid Build Coastguard Worker     error_msg("config : NULL address string \n");
511*cf5a6c84SAndroid Build Coastguard Worker     return -1;
512*cf5a6c84SAndroid Build Coastguard Worker   }
513*cf5a6c84SAndroid Build Coastguard Worker   if((inet_pton(AF_INET6, str, var)<=0) && (inet_pton(AF_INET, str, var)<=0)) {
514*cf5a6c84SAndroid Build Coastguard Worker     error_msg("config : wrong address %s \n", str);
515*cf5a6c84SAndroid Build Coastguard Worker     return -1;
516*cf5a6c84SAndroid Build Coastguard Worker   }
517*cf5a6c84SAndroid Build Coastguard Worker   return 0;
518*cf5a6c84SAndroid Build Coastguard Worker }
519*cf5a6c84SAndroid Build Coastguard Worker 
520*cf5a6c84SAndroid Build Coastguard Worker // String to dhcp option conversion
strtoopt(const char * str,void * var)521*cf5a6c84SAndroid Build Coastguard Worker static int strtoopt(const char *str, void *var)
522*cf5a6c84SAndroid Build Coastguard Worker {
523*cf5a6c84SAndroid Build Coastguard Worker   char *option, *valstr, *grp, *tp;
524*cf5a6c84SAndroid Build Coastguard Worker   uint32_t optcode = 0, inf = infomode, convtmp, mask, nip, router;
525*cf5a6c84SAndroid Build Coastguard Worker   uint16_t flag = 0;
526*cf5a6c84SAndroid Build Coastguard Worker   int count, size = ARRAY_LEN(options_list);
527*cf5a6c84SAndroid Build Coastguard Worker 
528*cf5a6c84SAndroid Build Coastguard Worker   if (!*str) return 0;
529*cf5a6c84SAndroid Build Coastguard Worker   if (!(option = strtok((char*)str, " \t="))) return -1;
530*cf5a6c84SAndroid Build Coastguard Worker 
531*cf5a6c84SAndroid Build Coastguard Worker   infomode = LOG_SILENT;
532*cf5a6c84SAndroid Build Coastguard Worker   strtou32(option, (uint32_t*)&optcode);
533*cf5a6c84SAndroid Build Coastguard Worker   infomode = inf;
534*cf5a6c84SAndroid Build Coastguard Worker 
535*cf5a6c84SAndroid Build Coastguard Worker   if (optcode > 0 && optcode < 256) { // raw option
536*cf5a6c84SAndroid Build Coastguard Worker     for (count = 0; count < size; count++) {
537*cf5a6c84SAndroid Build Coastguard Worker       if ((options_list[count].code & 0X00FF) == optcode) {
538*cf5a6c84SAndroid Build Coastguard Worker         flag = (options_list[count].code & 0XFF00);
539*cf5a6c84SAndroid Build Coastguard Worker         break;
540*cf5a6c84SAndroid Build Coastguard Worker       }
541*cf5a6c84SAndroid Build Coastguard Worker     }
542*cf5a6c84SAndroid Build Coastguard Worker   } else { //string option
543*cf5a6c84SAndroid Build Coastguard Worker     for (count = 0; count < size; count++) {
544*cf5a6c84SAndroid Build Coastguard Worker       if (!strncmp(options_list[count].key, option, strlen(options_list[count].key))) {
545*cf5a6c84SAndroid Build Coastguard Worker         flag = (options_list[count].code & 0XFF00);
546*cf5a6c84SAndroid Build Coastguard Worker         optcode = (options_list[count].code & 0X00FF);
547*cf5a6c84SAndroid Build Coastguard Worker         break;
548*cf5a6c84SAndroid Build Coastguard Worker       }
549*cf5a6c84SAndroid Build Coastguard Worker     }
550*cf5a6c84SAndroid Build Coastguard Worker   }
551*cf5a6c84SAndroid Build Coastguard Worker   if (count == size) {
552*cf5a6c84SAndroid Build Coastguard Worker     infomsg(inf, "config : Obsolete OR Unknown Option : %s", option);
553*cf5a6c84SAndroid Build Coastguard Worker     return -1;
554*cf5a6c84SAndroid Build Coastguard Worker   }
555*cf5a6c84SAndroid Build Coastguard Worker 
556*cf5a6c84SAndroid Build Coastguard Worker   if (!flag || !optcode) return -1;
557*cf5a6c84SAndroid Build Coastguard Worker 
558*cf5a6c84SAndroid Build Coastguard Worker   if (!(valstr = strtok(NULL, " \t"))) {
559*cf5a6c84SAndroid Build Coastguard Worker     dbg("config : option %s has no value defined.\n", option);
560*cf5a6c84SAndroid Build Coastguard Worker     return -1;
561*cf5a6c84SAndroid Build Coastguard Worker   }
562*cf5a6c84SAndroid Build Coastguard Worker   dbg(" value : %-20s : ", valstr);
563*cf5a6c84SAndroid Build Coastguard Worker   switch (flag) {
564*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_NUM32:
565*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].len = sizeof(uint32_t);
566*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].val = xmalloc(sizeof(uint32_t));
567*cf5a6c84SAndroid Build Coastguard Worker     strtou32(valstr, &convtmp);
568*cf5a6c84SAndroid Build Coastguard Worker     memcpy(options_list[count].val, &convtmp, sizeof(uint32_t));
569*cf5a6c84SAndroid Build Coastguard Worker     break;
570*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_NUM16:
571*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].len = sizeof(uint16_t);
572*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].val = xmalloc(sizeof(uint16_t));
573*cf5a6c84SAndroid Build Coastguard Worker     strtou32(valstr, &convtmp);
574*cf5a6c84SAndroid Build Coastguard Worker     memcpy(options_list[count].val, &convtmp, sizeof(uint16_t));
575*cf5a6c84SAndroid Build Coastguard Worker     break;
576*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_NUM8:
577*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].len = sizeof(uint8_t);
578*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].val = xmalloc(sizeof(uint8_t));
579*cf5a6c84SAndroid Build Coastguard Worker     strtou32(valstr, &convtmp);
580*cf5a6c84SAndroid Build Coastguard Worker     memcpy(options_list[count].val, &convtmp, sizeof(uint8_t));
581*cf5a6c84SAndroid Build Coastguard Worker     break;
582*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_IP:
583*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].len = sizeof(uint32_t);
584*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].val = xmalloc(sizeof(uint32_t));
585*cf5a6c84SAndroid Build Coastguard Worker     striptovar(valstr, options_list[count].val);
586*cf5a6c84SAndroid Build Coastguard Worker     break;
587*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_STRING:
588*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].len = strlen(valstr);
589*cf5a6c84SAndroid Build Coastguard Worker     options_list[count].val = strdup(valstr);
590*cf5a6c84SAndroid Build Coastguard Worker     break;
591*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_IPLIST:
592*cf5a6c84SAndroid Build Coastguard Worker     while(valstr){
593*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + sizeof(uint32_t));
594*cf5a6c84SAndroid Build Coastguard Worker       striptovar(valstr, ((uint8_t*)options_list[count].val)+options_list[count].len);
595*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].len += sizeof(uint32_t);
596*cf5a6c84SAndroid Build Coastguard Worker       valstr = strtok(NULL," \t");
597*cf5a6c84SAndroid Build Coastguard Worker     }
598*cf5a6c84SAndroid Build Coastguard Worker     break;
599*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_IPPLST:
600*cf5a6c84SAndroid Build Coastguard Worker     break;
601*cf5a6c84SAndroid Build Coastguard Worker   case DHCP_STCRTS:
602*cf5a6c84SAndroid Build Coastguard Worker     /* Option binary format:
603*cf5a6c84SAndroid Build Coastguard Worker      * mask [one byte, 0..32]
604*cf5a6c84SAndroid Build Coastguard Worker      * ip [0..4 bytes depending on mask]
605*cf5a6c84SAndroid Build Coastguard Worker      * router [4 bytes]
606*cf5a6c84SAndroid Build Coastguard Worker      * may be repeated
607*cf5a6c84SAndroid Build Coastguard Worker      * staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
608*cf5a6c84SAndroid Build Coastguard Worker      */
609*cf5a6c84SAndroid Build Coastguard Worker     grp = strtok(valstr, ",");;
610*cf5a6c84SAndroid Build Coastguard Worker     while(grp){
611*cf5a6c84SAndroid Build Coastguard Worker       while(*grp == ' ' || *grp == '\t') grp++;
612*cf5a6c84SAndroid Build Coastguard Worker       tp = strchr(grp, '/');
613*cf5a6c84SAndroid Build Coastguard Worker       if (!tp) error_exit("wrong formatted static route option");
614*cf5a6c84SAndroid Build Coastguard Worker       *tp = '\0';
615*cf5a6c84SAndroid Build Coastguard Worker       mask = strtol(++tp, &tp, 10);
616*cf5a6c84SAndroid Build Coastguard Worker       if (striptovar(grp, (uint8_t*)&nip)<0) error_exit("wrong formatted static route option");
617*cf5a6c84SAndroid Build Coastguard Worker       while(*tp == ' ' || *tp == '\t' || *tp == '-') tp++;
618*cf5a6c84SAndroid Build Coastguard Worker       if (striptovar(tp, (uint8_t*)&router)<0) error_exit("wrong formatted static route option");
619*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + 1 + mask/8 + 4);
620*cf5a6c84SAndroid Build Coastguard Worker       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &mask, 1);
621*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].len += 1;
622*cf5a6c84SAndroid Build Coastguard Worker       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &nip, mask/8);
623*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].len += mask/8;
624*cf5a6c84SAndroid Build Coastguard Worker       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &router, 4);
625*cf5a6c84SAndroid Build Coastguard Worker       options_list[count].len += 4;
626*cf5a6c84SAndroid Build Coastguard Worker       tp = NULL;
627*cf5a6c84SAndroid Build Coastguard Worker       grp = strtok(NULL, ",");
628*cf5a6c84SAndroid Build Coastguard Worker     }
629*cf5a6c84SAndroid Build Coastguard Worker     break;
630*cf5a6c84SAndroid Build Coastguard Worker   }
631*cf5a6c84SAndroid Build Coastguard Worker   return 0;
632*cf5a6c84SAndroid Build Coastguard Worker }
633*cf5a6c84SAndroid Build Coastguard Worker 
634*cf5a6c84SAndroid Build Coastguard Worker // Reads Static leases from STR and updates inner structures.
get_staticlease(const char * str,void * var)635*cf5a6c84SAndroid Build Coastguard Worker static int get_staticlease(const char *str, void *var)
636*cf5a6c84SAndroid Build Coastguard Worker {
637*cf5a6c84SAndroid Build Coastguard Worker   struct static_lease_s *sltmp;
638*cf5a6c84SAndroid Build Coastguard Worker   char *tkmac, *tkip;
639*cf5a6c84SAndroid Build Coastguard Worker   int count;
640*cf5a6c84SAndroid Build Coastguard Worker 
641*cf5a6c84SAndroid Build Coastguard Worker   if (!*str) return 0;
642*cf5a6c84SAndroid Build Coastguard Worker 
643*cf5a6c84SAndroid Build Coastguard Worker   if (!(tkmac = strtok((char*)str, " \t"))) {
644*cf5a6c84SAndroid Build Coastguard Worker     infomsg(infomode, "config : static lease : mac not found");
645*cf5a6c84SAndroid Build Coastguard Worker     return 0;
646*cf5a6c84SAndroid Build Coastguard Worker   }
647*cf5a6c84SAndroid Build Coastguard Worker   if (!(tkip = strtok(NULL, " \t"))) {
648*cf5a6c84SAndroid Build Coastguard Worker     infomsg(infomode, "config : static lease : no ip bind to mac %s", tkmac);
649*cf5a6c84SAndroid Build Coastguard Worker     return 0;
650*cf5a6c84SAndroid Build Coastguard Worker   }
651*cf5a6c84SAndroid Build Coastguard Worker   sltmp = xzalloc(sizeof(struct static_lease_s));
652*cf5a6c84SAndroid Build Coastguard Worker   for (count = 0; count < 6; count++, tkmac++) {
653*cf5a6c84SAndroid Build Coastguard Worker     errno = 0;
654*cf5a6c84SAndroid Build Coastguard Worker     sltmp->mac[count] = strtol(tkmac, &tkmac, 16);
655*cf5a6c84SAndroid Build Coastguard Worker     if (sltmp->mac[count]>255 || sltmp->mac[count]<0 || (*tkmac && *tkmac!=':') || errno) {
656*cf5a6c84SAndroid Build Coastguard Worker       infomsg(infomode, "config : static lease : mac address wrong format");
657*cf5a6c84SAndroid Build Coastguard Worker       free(sltmp);
658*cf5a6c84SAndroid Build Coastguard Worker       return 0;
659*cf5a6c84SAndroid Build Coastguard Worker     }
660*cf5a6c84SAndroid Build Coastguard Worker   }
661*cf5a6c84SAndroid Build Coastguard Worker   striptovar(tkip, &sltmp->nip);
662*cf5a6c84SAndroid Build Coastguard Worker   sltmp->next = gstate.leases.sleases;
663*cf5a6c84SAndroid Build Coastguard Worker   gstate.leases.sleases = sltmp;
664*cf5a6c84SAndroid Build Coastguard Worker 
665*cf5a6c84SAndroid Build Coastguard Worker   return 0;
666*cf5a6c84SAndroid Build Coastguard Worker }
667*cf5a6c84SAndroid Build Coastguard Worker 
668*cf5a6c84SAndroid Build Coastguard Worker static struct config_keyword keywords[] = {
669*cf5a6c84SAndroid Build Coastguard Worker // keyword          handler           variable address                default
670*cf5a6c84SAndroid Build Coastguard Worker   {"start"        , striptovar      , (void*)&gconfig.start_ip     , "192.168.0.20"},
671*cf5a6c84SAndroid Build Coastguard Worker   {"end"          , striptovar      , (void*)&gconfig.end_ip       , "192.168.0.254"},
672*cf5a6c84SAndroid Build Coastguard Worker   {"interface"    , strinvar        , (void*)&gconfig.interface    , "eth0"},
673*cf5a6c84SAndroid Build Coastguard Worker   {"port"         , strtou32        , (void*)&gconfig.port         , "67"},
674*cf5a6c84SAndroid Build Coastguard Worker   {"min_lease"    , strtou32        , (void*)&gconfig.min_lease_sec, "60"},
675*cf5a6c84SAndroid Build Coastguard Worker   {"max_leases"   , strtou32        , (void*)&gconfig.max_leases   , "235"},
676*cf5a6c84SAndroid Build Coastguard Worker   {"auto_time"    , strtou32        , (void*)&gconfig.auto_time    , "7200"},
677*cf5a6c84SAndroid Build Coastguard Worker   {"decline_time" , strtou32        , (void*)&gconfig.decline_time , "3600"},
678*cf5a6c84SAndroid Build Coastguard Worker   {"conflict_time", strtou32        , (void*)&gconfig.conflict_time, "3600"},
679*cf5a6c84SAndroid Build Coastguard Worker   {"offer_time"   , strtou32        , (void*)&gconfig.offer_time   , "60"},
680*cf5a6c84SAndroid Build Coastguard Worker   {"lease_file"   , strinvar        , (void*)&gconfig.lease_file   , "/var/lib/misc/dhcpd.leases"}, //LEASES_FILE
681*cf5a6c84SAndroid Build Coastguard Worker   {"lease6_file"  , strinvar        , (void*)&gconfig.lease6_file  , "/var/lib/misc/dhcpd6.leases"}, //LEASES_FILE
682*cf5a6c84SAndroid Build Coastguard Worker   {"pidfile"      , strinvar        , (void*)&gconfig.pidfile      , "/var/run/dhcpd.pid"}, //DPID_FILE
683*cf5a6c84SAndroid Build Coastguard Worker   {"siaddr"       , striptovar      , (void*)&gconfig.siaddr_nip   , "0.0.0.0"},
684*cf5a6c84SAndroid Build Coastguard Worker   {"option"       , strtoopt        , (void*)&gconfig.options      , ""},
685*cf5a6c84SAndroid Build Coastguard Worker   {"opt"          , strtoopt        , (void*)&gconfig.options      , ""},
686*cf5a6c84SAndroid Build Coastguard Worker   {"notify_file"  , strinvar        , (void*)&gconfig.notify_file  , ""},
687*cf5a6c84SAndroid Build Coastguard Worker   {"sname"        , strinvar        , (void*)&gconfig.sname        , ""},
688*cf5a6c84SAndroid Build Coastguard Worker   {"boot_file"    , strinvar        , (void*)&gconfig.boot_file    , ""},
689*cf5a6c84SAndroid Build Coastguard Worker   {"static_lease" , get_staticlease , (void*)&gconfig.static_leases, ""},
690*cf5a6c84SAndroid Build Coastguard Worker   {"start6"       , striptovar      , (void*)&gconfig.start_ip6    , "2001:620:40b:555::100"},
691*cf5a6c84SAndroid Build Coastguard Worker   {"end6"         , striptovar      , (void*)&gconfig.end_ip6      , "2001:620:40b:555::200"},
692*cf5a6c84SAndroid Build Coastguard Worker   {"preferred_lifetime" , strtou32  , (void*)&gconfig.pref_lifetime, "3600"},
693*cf5a6c84SAndroid Build Coastguard Worker   {"valid_lifetime"     , strtou32  , (void*)&gconfig.valid_lifetime, "7200"},
694*cf5a6c84SAndroid Build Coastguard Worker   {"t1"           , strtou32        , (void*)&gconfig.t1           , "3600"},
695*cf5a6c84SAndroid Build Coastguard Worker   {"t2"           , strtou32        , (void*)&gconfig.t2           , "5400"},
696*cf5a6c84SAndroid Build Coastguard Worker };
697*cf5a6c84SAndroid Build Coastguard Worker 
698*cf5a6c84SAndroid Build Coastguard Worker // Parses the server config file and updates the global server config accordingly.
parse_server_config(char * config_file,struct config_keyword * confkey)699*cf5a6c84SAndroid Build Coastguard Worker static int parse_server_config(char *config_file, struct config_keyword *confkey)
700*cf5a6c84SAndroid Build Coastguard Worker {
701*cf5a6c84SAndroid Build Coastguard Worker   FILE *fs = NULL;
702*cf5a6c84SAndroid Build Coastguard Worker   char *confline_temp = NULL,*confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
703*cf5a6c84SAndroid Build Coastguard Worker   int len, linelen, tcount, count, size = ARRAY_LEN(keywords);
704*cf5a6c84SAndroid Build Coastguard Worker 
705*cf5a6c84SAndroid Build Coastguard Worker   for (count = 0; count < size; count++)
706*cf5a6c84SAndroid Build Coastguard Worker     if (confkey[count].handler)
707*cf5a6c84SAndroid Build Coastguard Worker       confkey[count].handler(confkey[count].def, confkey[count].var);
708*cf5a6c84SAndroid Build Coastguard Worker 
709*cf5a6c84SAndroid Build Coastguard Worker   if (!(fs = fopen(config_file, "r"))) perror_msg("%s", config_file);
710*cf5a6c84SAndroid Build Coastguard Worker   for (len = 0, linelen = 0; fs;) {
711*cf5a6c84SAndroid Build Coastguard Worker     len = getline(&confline_temp, (size_t*) &linelen, fs);
712*cf5a6c84SAndroid Build Coastguard Worker     confline = confline_temp;
713*cf5a6c84SAndroid Build Coastguard Worker     if (len <= 0) break;
714*cf5a6c84SAndroid Build Coastguard Worker     for (; *confline == ' '; confline++, len--);
715*cf5a6c84SAndroid Build Coastguard Worker     if ((confline[0] == '#') || (confline[0] == '\n')) goto free_conf_continue;
716*cf5a6c84SAndroid Build Coastguard Worker     tk = strchr(confline, '#');
717*cf5a6c84SAndroid Build Coastguard Worker     if (tk) {
718*cf5a6c84SAndroid Build Coastguard Worker       for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
719*cf5a6c84SAndroid Build Coastguard Worker       *tk = '\0';
720*cf5a6c84SAndroid Build Coastguard Worker     }
721*cf5a6c84SAndroid Build Coastguard Worker     tk = strchr(confline, '\n');
722*cf5a6c84SAndroid Build Coastguard Worker     if (tk) {
723*cf5a6c84SAndroid Build Coastguard Worker       for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
724*cf5a6c84SAndroid Build Coastguard Worker       *tk = '\0';
725*cf5a6c84SAndroid Build Coastguard Worker     }
726*cf5a6c84SAndroid Build Coastguard Worker     for (tcount=0, tk=strtok(confline, " \t"); tk && (tcount < 2);
727*cf5a6c84SAndroid Build Coastguard Worker         tcount++, tk=strtok(NULL,(tcount==1)?"":" \t")) {
728*cf5a6c84SAndroid Build Coastguard Worker       while ((*tk == '\t') || (*tk == ' ')) tk++;
729*cf5a6c84SAndroid Build Coastguard Worker       tokens[tcount] = xstrdup(tk);
730*cf5a6c84SAndroid Build Coastguard Worker     }
731*cf5a6c84SAndroid Build Coastguard Worker     if (tcount<=1) goto free_tk0_continue;
732*cf5a6c84SAndroid Build Coastguard Worker     for (count = 0; count < size; count++) {
733*cf5a6c84SAndroid Build Coastguard Worker       if (!strcmp(confkey[count].keyword,tokens[0])) {
734*cf5a6c84SAndroid Build Coastguard Worker         dbg("got config : %15s : ", confkey[count].keyword);
735*cf5a6c84SAndroid Build Coastguard Worker         if (confkey[count].handler(tokens[1], confkey[count].var) == 0)
736*cf5a6c84SAndroid Build Coastguard Worker           dbg("%s \n", tokens[1]);
737*cf5a6c84SAndroid Build Coastguard Worker         break;
738*cf5a6c84SAndroid Build Coastguard Worker       }
739*cf5a6c84SAndroid Build Coastguard Worker     }
740*cf5a6c84SAndroid Build Coastguard Worker     if (tokens[1]) { free(tokens[1]); tokens[1] = NULL; }
741*cf5a6c84SAndroid Build Coastguard Worker free_tk0_continue:
742*cf5a6c84SAndroid Build Coastguard Worker     if (tokens[0]) { free(tokens[0]); tokens[0] = NULL; }
743*cf5a6c84SAndroid Build Coastguard Worker free_conf_continue:
744*cf5a6c84SAndroid Build Coastguard Worker     free(confline_temp);
745*cf5a6c84SAndroid Build Coastguard Worker     confline_temp = NULL;
746*cf5a6c84SAndroid Build Coastguard Worker   }
747*cf5a6c84SAndroid Build Coastguard Worker   if (fs) fclose(fs);
748*cf5a6c84SAndroid Build Coastguard Worker   return 0;
749*cf5a6c84SAndroid Build Coastguard Worker }
750*cf5a6c84SAndroid Build Coastguard Worker 
751*cf5a6c84SAndroid Build Coastguard Worker // opens UDP socket for listen ipv6 packets
open_listensock6(void)752*cf5a6c84SAndroid Build Coastguard Worker static int open_listensock6(void)
753*cf5a6c84SAndroid Build Coastguard Worker {
754*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6 addr6;
755*cf5a6c84SAndroid Build Coastguard Worker   struct ipv6_mreq mreq;
756*cf5a6c84SAndroid Build Coastguard Worker 
757*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.listensock > 0) close(gstate.listensock);
758*cf5a6c84SAndroid Build Coastguard Worker 
759*cf5a6c84SAndroid Build Coastguard Worker   dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
760*cf5a6c84SAndroid Build Coastguard Worker 
761*cf5a6c84SAndroid Build Coastguard Worker   gstate.listensock = xsocket(PF_INET6, SOCK_DGRAM, 0);
762*cf5a6c84SAndroid Build Coastguard Worker   setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
763*cf5a6c84SAndroid Build Coastguard Worker   setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_CHECKSUM, &constone, sizeof(constone));
764*cf5a6c84SAndroid Build Coastguard Worker 
765*cf5a6c84SAndroid Build Coastguard Worker   if (setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &constone,
766*cf5a6c84SAndroid Build Coastguard Worker         sizeof(constone)) == -1) {
767*cf5a6c84SAndroid Build Coastguard Worker     error_msg("failed to receive ipv6 packets.\n");
768*cf5a6c84SAndroid Build Coastguard Worker     close(gstate.listensock);
769*cf5a6c84SAndroid Build Coastguard Worker     return -1;
770*cf5a6c84SAndroid Build Coastguard Worker   }
771*cf5a6c84SAndroid Build Coastguard Worker 
772*cf5a6c84SAndroid Build Coastguard Worker   setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, gconfig.interface, strlen(gconfig.interface)+1);
773*cf5a6c84SAndroid Build Coastguard Worker 
774*cf5a6c84SAndroid Build Coastguard Worker   memset(&addr6, 0, sizeof(addr6));
775*cf5a6c84SAndroid Build Coastguard Worker   addr6.sin6_family = AF_INET6;
776*cf5a6c84SAndroid Build Coastguard Worker   addr6.sin6_port = htons(gconfig.port); //SERVER_PORT
777*cf5a6c84SAndroid Build Coastguard Worker   addr6.sin6_scope_id = if_nametoindex(gconfig.interface);
778*cf5a6c84SAndroid Build Coastguard Worker   //Listening for multicast packet
779*cf5a6c84SAndroid Build Coastguard Worker   inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr);
780*cf5a6c84SAndroid Build Coastguard Worker 
781*cf5a6c84SAndroid Build Coastguard Worker   if (bind(gstate.listensock, (struct sockaddr *) &addr6, sizeof(addr6)) == -1) {
782*cf5a6c84SAndroid Build Coastguard Worker     close(gstate.listensock);
783*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("bind failed");
784*cf5a6c84SAndroid Build Coastguard Worker   }
785*cf5a6c84SAndroid Build Coastguard Worker 
786*cf5a6c84SAndroid Build Coastguard Worker   memset(&mreq, 0, sizeof(mreq));
787*cf5a6c84SAndroid Build Coastguard Worker   mreq.ipv6mr_interface = if_nametoindex(gconfig.interface);
788*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&mreq.ipv6mr_multiaddr, &addr6.sin6_addr, sizeof(addr6.sin6_addr));
789*cf5a6c84SAndroid Build Coastguard Worker 
790*cf5a6c84SAndroid Build Coastguard Worker   if(setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) {
791*cf5a6c84SAndroid Build Coastguard Worker     error_msg("failed to join a multicast group.\n");
792*cf5a6c84SAndroid Build Coastguard Worker     close(gstate.listensock);
793*cf5a6c84SAndroid Build Coastguard Worker     return -1;
794*cf5a6c84SAndroid Build Coastguard Worker   }
795*cf5a6c84SAndroid Build Coastguard Worker 
796*cf5a6c84SAndroid Build Coastguard Worker   dbg("OPEN : success\n");
797*cf5a6c84SAndroid Build Coastguard Worker   return 0;
798*cf5a6c84SAndroid Build Coastguard Worker }
799*cf5a6c84SAndroid Build Coastguard Worker 
800*cf5a6c84SAndroid Build Coastguard Worker // opens UDP socket for listen
open_listensock(void)801*cf5a6c84SAndroid Build Coastguard Worker static int open_listensock(void)
802*cf5a6c84SAndroid Build Coastguard Worker {
803*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in addr;
804*cf5a6c84SAndroid Build Coastguard Worker   struct ifreq ifr;
805*cf5a6c84SAndroid Build Coastguard Worker 
806*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.listensock > 0) close(gstate.listensock);
807*cf5a6c84SAndroid Build Coastguard Worker 
808*cf5a6c84SAndroid Build Coastguard Worker   dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
809*cf5a6c84SAndroid Build Coastguard Worker   gstate.listensock = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
810*cf5a6c84SAndroid Build Coastguard Worker   setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
811*cf5a6c84SAndroid Build Coastguard Worker   if (setsockopt(gstate.listensock, SOL_SOCKET, SO_BROADCAST, &constone, sizeof(constone)) == -1) {
812*cf5a6c84SAndroid Build Coastguard Worker     error_msg("failed to receive brodcast packets.\n");
813*cf5a6c84SAndroid Build Coastguard Worker     close(gstate.listensock);
814*cf5a6c84SAndroid Build Coastguard Worker     return -1;
815*cf5a6c84SAndroid Build Coastguard Worker   }
816*cf5a6c84SAndroid Build Coastguard Worker   memset(&ifr, 0, sizeof(ifr));
817*cf5a6c84SAndroid Build Coastguard Worker   xstrncpy(ifr.ifr_name, gconfig.interface, IFNAMSIZ);
818*cf5a6c84SAndroid Build Coastguard Worker   setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
819*cf5a6c84SAndroid Build Coastguard Worker 
820*cf5a6c84SAndroid Build Coastguard Worker   memset(&addr, 0, sizeof(addr));
821*cf5a6c84SAndroid Build Coastguard Worker   addr.sin_family = AF_INET;
822*cf5a6c84SAndroid Build Coastguard Worker   addr.sin_port = htons(gconfig.port); //SERVER_PORT
823*cf5a6c84SAndroid Build Coastguard Worker   addr.sin_addr.s_addr = INADDR_ANY ;
824*cf5a6c84SAndroid Build Coastguard Worker 
825*cf5a6c84SAndroid Build Coastguard Worker   if (bind(gstate.listensock, (struct sockaddr *) &addr, sizeof(addr))) {
826*cf5a6c84SAndroid Build Coastguard Worker     close(gstate.listensock);
827*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("bind failed");
828*cf5a6c84SAndroid Build Coastguard Worker   }
829*cf5a6c84SAndroid Build Coastguard Worker   dbg("OPEN : success\n");
830*cf5a6c84SAndroid Build Coastguard Worker   return 0;
831*cf5a6c84SAndroid Build Coastguard Worker }
832*cf5a6c84SAndroid Build Coastguard Worker 
send_packet6(uint8_t relay,uint8_t * client_lla,uint16_t optlen)833*cf5a6c84SAndroid Build Coastguard Worker static int send_packet6(uint8_t relay, uint8_t *client_lla, uint16_t optlen)
834*cf5a6c84SAndroid Build Coastguard Worker {
835*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_ll dest_sll;
836*cf5a6c84SAndroid Build Coastguard Worker   dhcp6_raw_t packet;
837*cf5a6c84SAndroid Build Coastguard Worker   unsigned padding;
838*cf5a6c84SAndroid Build Coastguard Worker   int fd, result = -1;
839*cf5a6c84SAndroid Build Coastguard Worker 
840*cf5a6c84SAndroid Build Coastguard Worker   memset(&packet, 0, sizeof(dhcp6_raw_t));
841*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&packet.dhcp6, &gstate.send.send_pkt6, sizeof(dhcp6_msg_t));
842*cf5a6c84SAndroid Build Coastguard Worker   padding = sizeof(packet.dhcp6.options) - optlen;
843*cf5a6c84SAndroid Build Coastguard Worker 
844*cf5a6c84SAndroid Build Coastguard Worker   if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6))) < 0) {
845*cf5a6c84SAndroid Build Coastguard Worker     dbg("SEND : ipv6 socket failed\n");
846*cf5a6c84SAndroid Build Coastguard Worker     return -1;
847*cf5a6c84SAndroid Build Coastguard Worker   }
848*cf5a6c84SAndroid Build Coastguard Worker   memset(&dest_sll, 0, sizeof(dest_sll));
849*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_family = AF_PACKET;
850*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_protocol = htons(ETH_P_IPV6);
851*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_ifindex = gconfig.ifindex;
852*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_halen = ETH_ALEN;
853*cf5a6c84SAndroid Build Coastguard Worker   memcpy(dest_sll.sll_addr, client_lla, sizeof(uint8_t)*6);
854*cf5a6c84SAndroid Build Coastguard Worker 
855*cf5a6c84SAndroid Build Coastguard Worker   if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
856*cf5a6c84SAndroid Build Coastguard Worker     dbg("SEND : bind failed\n");
857*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
858*cf5a6c84SAndroid Build Coastguard Worker     return -1;
859*cf5a6c84SAndroid Build Coastguard Worker   }
860*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&packet.iph.ip6_src, &gconfig.server_nip6, sizeof(uint32_t)*4);
861*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&packet.iph.ip6_dst, &gstate.client_nip6, sizeof(uint32_t)*4);
862*cf5a6c84SAndroid Build Coastguard Worker 
863*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.source = htons(gconfig.port); //SERVER_PORT
864*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.dest = gstate.client_port; //CLIENT_PORT
865*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.len = htons(sizeof(dhcp6_raw_t) - sizeof(struct ip6_hdr) - padding);
866*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ntohs(packet.udph.len) + 0x11);
867*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp6_raw_t) - padding);
868*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
869*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = packet.udph.len;
870*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
871*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_hlim = 0x64;
872*cf5a6c84SAndroid Build Coastguard Worker 
873*cf5a6c84SAndroid Build Coastguard Worker   result = sendto(fd, &packet, sizeof(dhcp6_raw_t)-padding,
874*cf5a6c84SAndroid Build Coastguard Worker       0, (struct sockaddr *) &dest_sll, sizeof(dest_sll));
875*cf5a6c84SAndroid Build Coastguard Worker 
876*cf5a6c84SAndroid Build Coastguard Worker   dbg("sendto %d\n", result);
877*cf5a6c84SAndroid Build Coastguard Worker   close(fd);
878*cf5a6c84SAndroid Build Coastguard Worker   if (result < 0) dbg("PACKET send error\n");
879*cf5a6c84SAndroid Build Coastguard Worker   return result;
880*cf5a6c84SAndroid Build Coastguard Worker }
881*cf5a6c84SAndroid Build Coastguard Worker 
882*cf5a6c84SAndroid Build Coastguard Worker // Sends data through raw socket.
send_packet(uint8_t broadcast)883*cf5a6c84SAndroid Build Coastguard Worker static int send_packet(uint8_t broadcast)
884*cf5a6c84SAndroid Build Coastguard Worker {
885*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_ll dest_sll;
886*cf5a6c84SAndroid Build Coastguard Worker   dhcp_raw_t packet;
887*cf5a6c84SAndroid Build Coastguard Worker   unsigned padding;
888*cf5a6c84SAndroid Build Coastguard Worker   int fd, result = -1;
889*cf5a6c84SAndroid Build Coastguard Worker   char bmacaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
890*cf5a6c84SAndroid Build Coastguard Worker 
891*cf5a6c84SAndroid Build Coastguard Worker   memset(&packet, 0, sizeof(dhcp_raw_t));
892*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&packet.dhcp, &gstate.send.send_pkt, sizeof(dhcp_msg_t));
893*cf5a6c84SAndroid Build Coastguard Worker 
894*cf5a6c84SAndroid Build Coastguard Worker   if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
895*cf5a6c84SAndroid Build Coastguard Worker     dbg("SEND : socket failed\n");
896*cf5a6c84SAndroid Build Coastguard Worker     return -1;
897*cf5a6c84SAndroid Build Coastguard Worker   }
898*cf5a6c84SAndroid Build Coastguard Worker   memset(&dest_sll, 0, sizeof(dest_sll));
899*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_family = AF_PACKET;
900*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_protocol = htons(ETH_P_IP);
901*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_ifindex = gconfig.ifindex;
902*cf5a6c84SAndroid Build Coastguard Worker   dest_sll.sll_halen = 6;
903*cf5a6c84SAndroid Build Coastguard Worker   memcpy(dest_sll.sll_addr, (broadcast)?bmacaddr:gstate.rcvd.rcvd_pkt.chaddr , 6);
904*cf5a6c84SAndroid Build Coastguard Worker 
905*cf5a6c84SAndroid Build Coastguard Worker   if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
906*cf5a6c84SAndroid Build Coastguard Worker     dbg("SEND : bind failed\n");
907*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
908*cf5a6c84SAndroid Build Coastguard Worker     return -1;
909*cf5a6c84SAndroid Build Coastguard Worker   }
910*cf5a6c84SAndroid Build Coastguard Worker   padding = 308 - 1 - dhcp_opt_size(gstate.send.send_pkt.options);
911*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.protocol = IPPROTO_UDP;
912*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.saddr = gconfig.server_nip;
913*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.daddr = (broadcast || (gstate.rcvd.rcvd_pkt.ciaddr == 0))?
914*cf5a6c84SAndroid Build Coastguard Worker     INADDR_BROADCAST : gstate.rcvd.rcvd_pkt.ciaddr;
915*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.source = htons(gconfig.port);//SERVER_PORT
916*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.dest = gstate.client_port; //CLIENT_PORT
917*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.len = htons(sizeof(dhcp_raw_t) - sizeof(struct iphdr) - padding);
918*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.tot_len = packet.udph.len;
919*cf5a6c84SAndroid Build Coastguard Worker   packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp_raw_t) - padding);
920*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.tot_len = htons(sizeof(dhcp_raw_t) - padding);
921*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ihl = sizeof(packet.iph) >> 2;
922*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.version = IPVERSION;
923*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.ttl = IPDEFTTL;
924*cf5a6c84SAndroid Build Coastguard Worker   packet.iph.check = dhcp_checksum(&packet.iph, sizeof(packet.iph));
925*cf5a6c84SAndroid Build Coastguard Worker 
926*cf5a6c84SAndroid Build Coastguard Worker   result = sendto(fd, &packet, sizeof(dhcp_raw_t) - padding, 0,
927*cf5a6c84SAndroid Build Coastguard Worker       (struct sockaddr *) &dest_sll, sizeof(dest_sll));
928*cf5a6c84SAndroid Build Coastguard Worker 
929*cf5a6c84SAndroid Build Coastguard Worker   dbg("sendto %d\n", result);
930*cf5a6c84SAndroid Build Coastguard Worker   close(fd);
931*cf5a6c84SAndroid Build Coastguard Worker   if (result < 0) dbg("PACKET send error\n");
932*cf5a6c84SAndroid Build Coastguard Worker   return result;
933*cf5a6c84SAndroid Build Coastguard Worker }
934*cf5a6c84SAndroid Build Coastguard Worker 
read_packet6(void)935*cf5a6c84SAndroid Build Coastguard Worker static int read_packet6(void)
936*cf5a6c84SAndroid Build Coastguard Worker {
937*cf5a6c84SAndroid Build Coastguard Worker   int ret;
938*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6 c_addr;
939*cf5a6c84SAndroid Build Coastguard Worker   socklen_t c_addr_size = sizeof(c_addr);
940*cf5a6c84SAndroid Build Coastguard Worker 
941*cf5a6c84SAndroid Build Coastguard Worker   memset(&gstate.rcvd.rcvd_pkt6, 0, sizeof(dhcp6_msg_t));
942*cf5a6c84SAndroid Build Coastguard Worker   ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt6, sizeof(dhcp6_msg_t),
943*cf5a6c84SAndroid Build Coastguard Worker       0, (struct sockaddr*) &c_addr, &c_addr_size);
944*cf5a6c84SAndroid Build Coastguard Worker   memcpy(gstate.client_nip6, &c_addr.sin6_addr, sizeof(uint32_t)*4);
945*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&gstate.client_port, &c_addr.sin6_port, sizeof(uint32_t));
946*cf5a6c84SAndroid Build Coastguard Worker   if (ret < 0) {
947*cf5a6c84SAndroid Build Coastguard Worker     dbg("Packet read error, ignoring. \n");
948*cf5a6c84SAndroid Build Coastguard Worker     return ret; // returns -1
949*cf5a6c84SAndroid Build Coastguard Worker   }
950*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.rcvd.rcvd_pkt6.msgtype < 1) {
951*cf5a6c84SAndroid Build Coastguard Worker     dbg("Bad message type, igroning. \n");
952*cf5a6c84SAndroid Build Coastguard Worker     return -2;
953*cf5a6c84SAndroid Build Coastguard Worker   }
954*cf5a6c84SAndroid Build Coastguard Worker 
955*cf5a6c84SAndroid Build Coastguard Worker   dbg("Received an ipv6 packet. Size : %d \n", ret);
956*cf5a6c84SAndroid Build Coastguard Worker   return ret;
957*cf5a6c84SAndroid Build Coastguard Worker }
958*cf5a6c84SAndroid Build Coastguard Worker 
959*cf5a6c84SAndroid Build Coastguard Worker // Reads from UDP socket
read_packet(void)960*cf5a6c84SAndroid Build Coastguard Worker static int read_packet(void)
961*cf5a6c84SAndroid Build Coastguard Worker {
962*cf5a6c84SAndroid Build Coastguard Worker   int ret;
963*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in c_addr;
964*cf5a6c84SAndroid Build Coastguard Worker   socklen_t c_addr_size = sizeof(c_addr);
965*cf5a6c84SAndroid Build Coastguard Worker 
966*cf5a6c84SAndroid Build Coastguard Worker   memset(&gstate.rcvd.rcvd_pkt, 0, sizeof(dhcp_msg_t));
967*cf5a6c84SAndroid Build Coastguard Worker   ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t),
968*cf5a6c84SAndroid Build Coastguard Worker       0, (struct sockaddr*) &c_addr, &c_addr_size);
969*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&gstate.client_port, &c_addr.sin_port, sizeof(uint32_t));
970*cf5a6c84SAndroid Build Coastguard Worker   /*ret = read(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t));*/
971*cf5a6c84SAndroid Build Coastguard Worker   if (ret < 0) {
972*cf5a6c84SAndroid Build Coastguard Worker     dbg("Packet read error, ignoring. \n");
973*cf5a6c84SAndroid Build Coastguard Worker     return ret; // returns -1
974*cf5a6c84SAndroid Build Coastguard Worker   }
975*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.rcvd.rcvd_pkt.cookie != htonl(DHCP_MAGIC)) {
976*cf5a6c84SAndroid Build Coastguard Worker     dbg("Packet with bad magic, ignoring. \n");
977*cf5a6c84SAndroid Build Coastguard Worker     return -2;
978*cf5a6c84SAndroid Build Coastguard Worker   }
979*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.rcvd.rcvd_pkt.op != 1) { //BOOTPREQUEST
980*cf5a6c84SAndroid Build Coastguard Worker     dbg("Not a BOOT REQUEST ignoring. \n");
981*cf5a6c84SAndroid Build Coastguard Worker     return -2;
982*cf5a6c84SAndroid Build Coastguard Worker   }
983*cf5a6c84SAndroid Build Coastguard Worker   if (gstate.rcvd.rcvd_pkt.hlen != 6) {
984*cf5a6c84SAndroid Build Coastguard Worker     dbg("hlen != 6 ignoring. \n");
985*cf5a6c84SAndroid Build Coastguard Worker     return -2;
986*cf5a6c84SAndroid Build Coastguard Worker   }
987*cf5a6c84SAndroid Build Coastguard Worker   dbg("Received a packet. Size : %d \n", ret);
988*cf5a6c84SAndroid Build Coastguard Worker   return ret;
989*cf5a6c84SAndroid Build Coastguard Worker }
990*cf5a6c84SAndroid Build Coastguard Worker 
991*cf5a6c84SAndroid Build Coastguard Worker // Preapres a dhcp packet with defaults and configs
prepare_send_pkt(void)992*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* prepare_send_pkt(void)
993*cf5a6c84SAndroid Build Coastguard Worker {
994*cf5a6c84SAndroid Build Coastguard Worker   memset((void*)&gstate.send.send_pkt, 0, sizeof(gstate.send.send_pkt));
995*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.op = 2; //BOOTPREPLY
996*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.htype = 1;
997*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.hlen = 6;
998*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.xid = gstate.rcvd.rcvd_pkt.xid;
999*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.cookie = htonl(DHCP_MAGIC);
1000*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.nsiaddr = gconfig.server_nip;
1001*cf5a6c84SAndroid Build Coastguard Worker   memcpy(gstate.send.send_pkt.chaddr, gstate.rcvd.rcvd_pkt.chaddr, 16);
1002*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt.options[0] = DHCP_OPT_END;
1003*cf5a6c84SAndroid Build Coastguard Worker   return gstate.send.send_pkt.options;
1004*cf5a6c84SAndroid Build Coastguard Worker }
1005*cf5a6c84SAndroid Build Coastguard Worker 
prepare_send_pkt6(uint16_t opt)1006*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* prepare_send_pkt6(uint16_t opt)
1007*cf5a6c84SAndroid Build Coastguard Worker {
1008*cf5a6c84SAndroid Build Coastguard Worker   memset((void*)&gstate.send.send_pkt6, 0, sizeof(gstate.send.send_pkt6));
1009*cf5a6c84SAndroid Build Coastguard Worker   gstate.send.send_pkt6.msgtype = opt;
1010*cf5a6c84SAndroid Build Coastguard Worker   memcpy(gstate.send.send_pkt6.transaction_id, gstate.rcvd.rcvd_pkt6.transaction_id, 3);
1011*cf5a6c84SAndroid Build Coastguard Worker   return gstate.send.send_pkt6.options;
1012*cf5a6c84SAndroid Build Coastguard Worker }
1013*cf5a6c84SAndroid Build Coastguard Worker 
1014*cf5a6c84SAndroid Build Coastguard Worker // Sets a option value in dhcp packet's option field
set_optval(uint8_t * optptr,uint16_t opt,void * var,size_t len)1015*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* set_optval(uint8_t *optptr, uint16_t opt, void *var, size_t len)
1016*cf5a6c84SAndroid Build Coastguard Worker {
1017*cf5a6c84SAndroid Build Coastguard Worker   while (*optptr != DHCP_OPT_END) optptr++;
1018*cf5a6c84SAndroid Build Coastguard Worker   *optptr++ = (uint8_t)(opt & 0x00FF);
1019*cf5a6c84SAndroid Build Coastguard Worker   *optptr++ = (uint8_t) len;
1020*cf5a6c84SAndroid Build Coastguard Worker   memcpy(optptr, var, len);
1021*cf5a6c84SAndroid Build Coastguard Worker   optptr += len;
1022*cf5a6c84SAndroid Build Coastguard Worker   *optptr = DHCP_OPT_END;
1023*cf5a6c84SAndroid Build Coastguard Worker   return optptr;
1024*cf5a6c84SAndroid Build Coastguard Worker }
1025*cf5a6c84SAndroid Build Coastguard Worker 
set_optval6(uint8_t * optptr,uint16_t opt,void * var,size_t len)1026*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* set_optval6(uint8_t *optptr, uint16_t opt, void *var, size_t len)
1027*cf5a6c84SAndroid Build Coastguard Worker {
1028*cf5a6c84SAndroid Build Coastguard Worker   *((uint16_t*)optptr) = htons(opt);
1029*cf5a6c84SAndroid Build Coastguard Worker   *(uint16_t*)(optptr+2) = htons(len);
1030*cf5a6c84SAndroid Build Coastguard Worker   memcpy(optptr+4, var, len);
1031*cf5a6c84SAndroid Build Coastguard Worker   optptr += len+4;
1032*cf5a6c84SAndroid Build Coastguard Worker   return optptr;
1033*cf5a6c84SAndroid Build Coastguard Worker }
1034*cf5a6c84SAndroid Build Coastguard Worker 
1035*cf5a6c84SAndroid Build Coastguard Worker // Gets a option value from dhcp packet's option field
get_optval(uint8_t * optptr,uint16_t opt,void * var)1036*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* get_optval(uint8_t *optptr, uint16_t opt, void *var)
1037*cf5a6c84SAndroid Build Coastguard Worker {
1038*cf5a6c84SAndroid Build Coastguard Worker   size_t len;
1039*cf5a6c84SAndroid Build Coastguard Worker   uint8_t overloaded = 0;
1040*cf5a6c84SAndroid Build Coastguard Worker 
1041*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
1042*cf5a6c84SAndroid Build Coastguard Worker     while (*optptr == DHCP_OPT_PADDING) optptr++;
1043*cf5a6c84SAndroid Build Coastguard Worker     if ((*optptr & 0x00FF) == DHCP_OPT_END) break;
1044*cf5a6c84SAndroid Build Coastguard Worker     if ((*optptr & 0x00FF) == DHCP_OPT_OPTION_OVERLOAD) {
1045*cf5a6c84SAndroid Build Coastguard Worker       overloaded = optptr[2];
1046*cf5a6c84SAndroid Build Coastguard Worker       optptr += optptr[1] + 2;
1047*cf5a6c84SAndroid Build Coastguard Worker     }
1048*cf5a6c84SAndroid Build Coastguard Worker     len = optptr[1];
1049*cf5a6c84SAndroid Build Coastguard Worker     if (*optptr == (opt & 0x00FF))
1050*cf5a6c84SAndroid Build Coastguard Worker       switch (opt & 0xFF00) {
1051*cf5a6c84SAndroid Build Coastguard Worker         case DHCP_NUM32: // FALLTHROUGH
1052*cf5a6c84SAndroid Build Coastguard Worker         case DHCP_IP:
1053*cf5a6c84SAndroid Build Coastguard Worker           memcpy(var, optptr+2, sizeof(uint32_t));
1054*cf5a6c84SAndroid Build Coastguard Worker           optptr += len + 2;
1055*cf5a6c84SAndroid Build Coastguard Worker           return optptr;
1056*cf5a6c84SAndroid Build Coastguard Worker           break;
1057*cf5a6c84SAndroid Build Coastguard Worker         case DHCP_NUM16:
1058*cf5a6c84SAndroid Build Coastguard Worker           memcpy(var, optptr+2, sizeof(uint16_t));
1059*cf5a6c84SAndroid Build Coastguard Worker           optptr += len + 2;
1060*cf5a6c84SAndroid Build Coastguard Worker           return optptr;
1061*cf5a6c84SAndroid Build Coastguard Worker           break;
1062*cf5a6c84SAndroid Build Coastguard Worker         case DHCP_NUM8:
1063*cf5a6c84SAndroid Build Coastguard Worker           memcpy(var, optptr+2, sizeof(uint8_t));
1064*cf5a6c84SAndroid Build Coastguard Worker           optptr += len + 2;
1065*cf5a6c84SAndroid Build Coastguard Worker           return optptr;
1066*cf5a6c84SAndroid Build Coastguard Worker           break;
1067*cf5a6c84SAndroid Build Coastguard Worker         case DHCP_STRING:
1068*cf5a6c84SAndroid Build Coastguard Worker           var = xstrndup((char*) optptr, len);
1069*cf5a6c84SAndroid Build Coastguard Worker           optptr += len + 2;
1070*cf5a6c84SAndroid Build Coastguard Worker           return optptr;
1071*cf5a6c84SAndroid Build Coastguard Worker           break;
1072*cf5a6c84SAndroid Build Coastguard Worker       }
1073*cf5a6c84SAndroid Build Coastguard Worker     optptr += len + 2;
1074*cf5a6c84SAndroid Build Coastguard Worker   }
1075*cf5a6c84SAndroid Build Coastguard Worker   if ((overloaded == 1) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.file, opt, var);
1076*cf5a6c84SAndroid Build Coastguard Worker   if ((overloaded == 2) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.sname, opt, var);
1077*cf5a6c84SAndroid Build Coastguard Worker   return optptr;
1078*cf5a6c84SAndroid Build Coastguard Worker }
1079*cf5a6c84SAndroid Build Coastguard Worker 
get_optval6(uint8_t * optptr,uint16_t opt,uint16_t * datalen,void ** var)1080*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* get_optval6(uint8_t *optptr, uint16_t opt, uint16_t *datalen, void **var)
1081*cf5a6c84SAndroid Build Coastguard Worker {
1082*cf5a6c84SAndroid Build Coastguard Worker   uint16_t optcode;
1083*cf5a6c84SAndroid Build Coastguard Worker   uint16_t len;
1084*cf5a6c84SAndroid Build Coastguard Worker 
1085*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&optcode, optptr, sizeof(uint16_t));
1086*cf5a6c84SAndroid Build Coastguard Worker   memcpy(&len, optptr+2, sizeof(uint16_t));
1087*cf5a6c84SAndroid Build Coastguard Worker   if(!optcode) {
1088*cf5a6c84SAndroid Build Coastguard Worker     dbg("Option %d is not exist.\n", opt);
1089*cf5a6c84SAndroid Build Coastguard Worker     return optptr;
1090*cf5a6c84SAndroid Build Coastguard Worker   }
1091*cf5a6c84SAndroid Build Coastguard Worker   optcode = ntohs(optcode);
1092*cf5a6c84SAndroid Build Coastguard Worker   len = ntohs(len);
1093*cf5a6c84SAndroid Build Coastguard Worker 
1094*cf5a6c84SAndroid Build Coastguard Worker   if (opt == optcode) {
1095*cf5a6c84SAndroid Build Coastguard Worker     *var = xmalloc(len);
1096*cf5a6c84SAndroid Build Coastguard Worker     memcpy(*var, optptr+4, len);
1097*cf5a6c84SAndroid Build Coastguard Worker     optptr = optptr + len + 4;
1098*cf5a6c84SAndroid Build Coastguard Worker     memcpy(datalen, &len, sizeof(uint16_t));
1099*cf5a6c84SAndroid Build Coastguard Worker   }
1100*cf5a6c84SAndroid Build Coastguard Worker   else {
1101*cf5a6c84SAndroid Build Coastguard Worker     optptr = get_optval6(optptr+len+4, opt, datalen, var);
1102*cf5a6c84SAndroid Build Coastguard Worker   }
1103*cf5a6c84SAndroid Build Coastguard Worker 
1104*cf5a6c84SAndroid Build Coastguard Worker   return optptr;
1105*cf5a6c84SAndroid Build Coastguard Worker }
1106*cf5a6c84SAndroid Build Coastguard Worker 
1107*cf5a6c84SAndroid Build Coastguard Worker // Retrives Requested Parameter list from dhcp req packet.
get_reqparam(uint8_t ** list)1108*cf5a6c84SAndroid Build Coastguard Worker static uint8_t get_reqparam(uint8_t **list)
1109*cf5a6c84SAndroid Build Coastguard Worker {
1110*cf5a6c84SAndroid Build Coastguard Worker   uint8_t len, *optptr;
1111*cf5a6c84SAndroid Build Coastguard Worker   if(*list) free(*list);
1112*cf5a6c84SAndroid Build Coastguard Worker   for (optptr = gstate.rcvd.rcvd_pkt.options;
1113*cf5a6c84SAndroid Build Coastguard Worker       *optptr && *optptr!=((DHCP_OPT_PARAM_REQ) & 0x00FF); optptr+=optptr[1]+2);
1114*cf5a6c84SAndroid Build Coastguard Worker   len = *++optptr;
1115*cf5a6c84SAndroid Build Coastguard Worker   *list = xzalloc(len+1);
1116*cf5a6c84SAndroid Build Coastguard Worker   memcpy(*list, ++optptr, len);
1117*cf5a6c84SAndroid Build Coastguard Worker   return len;
1118*cf5a6c84SAndroid Build Coastguard Worker }
1119*cf5a6c84SAndroid Build Coastguard Worker 
1120*cf5a6c84SAndroid Build Coastguard Worker // Sets values of req param in dhcp offer packet.
set_reqparam(uint8_t * optptr,uint8_t * list)1121*cf5a6c84SAndroid Build Coastguard Worker static uint8_t* set_reqparam(uint8_t *optptr, uint8_t *list)
1122*cf5a6c84SAndroid Build Coastguard Worker {
1123*cf5a6c84SAndroid Build Coastguard Worker   uint8_t reqcode;
1124*cf5a6c84SAndroid Build Coastguard Worker   int count, size = ARRAY_LEN(options_list);
1125*cf5a6c84SAndroid Build Coastguard Worker 
1126*cf5a6c84SAndroid Build Coastguard Worker   while (*list) {
1127*cf5a6c84SAndroid Build Coastguard Worker     reqcode = *list++;
1128*cf5a6c84SAndroid Build Coastguard Worker     for (count = 0; count < size; count++) {
1129*cf5a6c84SAndroid Build Coastguard Worker       if ((options_list[count].code & 0X00FF)==reqcode) {
1130*cf5a6c84SAndroid Build Coastguard Worker         if (!(options_list[count].len) || !(options_list[count].val)) break;
1131*cf5a6c84SAndroid Build Coastguard Worker         for (; *optptr && *optptr!=DHCP_OPT_END; optptr+=optptr[1]+2);
1132*cf5a6c84SAndroid Build Coastguard Worker         *optptr++ = (uint8_t) (options_list[count].code & 0x00FF);
1133*cf5a6c84SAndroid Build Coastguard Worker         *optptr++ = (uint8_t) options_list[count].len;
1134*cf5a6c84SAndroid Build Coastguard Worker         memcpy(optptr, options_list[count].val, options_list[count].len);
1135*cf5a6c84SAndroid Build Coastguard Worker         optptr += options_list[count].len;
1136*cf5a6c84SAndroid Build Coastguard Worker         *optptr = DHCP_OPT_END;
1137*cf5a6c84SAndroid Build Coastguard Worker         break;
1138*cf5a6c84SAndroid Build Coastguard Worker       }
1139*cf5a6c84SAndroid Build Coastguard Worker     }
1140*cf5a6c84SAndroid Build Coastguard Worker   }
1141*cf5a6c84SAndroid Build Coastguard Worker   return optptr;
1142*cf5a6c84SAndroid Build Coastguard Worker }
1143*cf5a6c84SAndroid Build Coastguard Worker 
run_notify(char ** argv)1144*cf5a6c84SAndroid Build Coastguard Worker static void run_notify(char **argv)
1145*cf5a6c84SAndroid Build Coastguard Worker {
1146*cf5a6c84SAndroid Build Coastguard Worker   struct stat sts;
1147*cf5a6c84SAndroid Build Coastguard Worker   volatile int error = 0;
1148*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
1149*cf5a6c84SAndroid Build Coastguard Worker 
1150*cf5a6c84SAndroid Build Coastguard Worker   if (stat(argv[0], &sts) == -1 && errno == ENOENT) {
1151*cf5a6c84SAndroid Build Coastguard Worker     infomsg(infomode, "notify file: %s : not exist.", argv[0]);
1152*cf5a6c84SAndroid Build Coastguard Worker     return;
1153*cf5a6c84SAndroid Build Coastguard Worker   }
1154*cf5a6c84SAndroid Build Coastguard Worker   fflush(NULL);
1155*cf5a6c84SAndroid Build Coastguard Worker 
1156*cf5a6c84SAndroid Build Coastguard Worker   pid = vfork();
1157*cf5a6c84SAndroid Build Coastguard Worker   if (pid < 0) {
1158*cf5a6c84SAndroid Build Coastguard Worker     dbg("Fork failed.\n");
1159*cf5a6c84SAndroid Build Coastguard Worker     return;
1160*cf5a6c84SAndroid Build Coastguard Worker   }
1161*cf5a6c84SAndroid Build Coastguard Worker   if (!pid) {
1162*cf5a6c84SAndroid Build Coastguard Worker     execvp(argv[0], argv);
1163*cf5a6c84SAndroid Build Coastguard Worker     error = errno;
1164*cf5a6c84SAndroid Build Coastguard Worker     _exit(111);
1165*cf5a6c84SAndroid Build Coastguard Worker   }
1166*cf5a6c84SAndroid Build Coastguard Worker   if (error) {
1167*cf5a6c84SAndroid Build Coastguard Worker     waitpid(pid, NULL, 0);
1168*cf5a6c84SAndroid Build Coastguard Worker     errno = error;
1169*cf5a6c84SAndroid Build Coastguard Worker   }
1170*cf5a6c84SAndroid Build Coastguard Worker   dbg("script complete.\n");
1171*cf5a6c84SAndroid Build Coastguard Worker }
1172*cf5a6c84SAndroid Build Coastguard Worker 
write_leasefile(void)1173*cf5a6c84SAndroid Build Coastguard Worker static void write_leasefile(void)
1174*cf5a6c84SAndroid Build Coastguard Worker {
1175*cf5a6c84SAndroid Build Coastguard Worker   int fd;
1176*cf5a6c84SAndroid Build Coastguard Worker   uint32_t curr, tmp_time;
1177*cf5a6c84SAndroid Build Coastguard Worker   int64_t timestamp;
1178*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases;
1179*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease *dls;
1180*cf5a6c84SAndroid Build Coastguard Worker 
1181*cf5a6c84SAndroid Build Coastguard Worker   if ((fd = open(gconfig.lease_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
1182*cf5a6c84SAndroid Build Coastguard Worker     perror_msg("can't open %s ", gconfig.lease_file);
1183*cf5a6c84SAndroid Build Coastguard Worker   } else {
1184*cf5a6c84SAndroid Build Coastguard Worker     curr = timestamp = time(NULL);
1185*cf5a6c84SAndroid Build Coastguard Worker     timestamp = SWAP_BE64(timestamp);
1186*cf5a6c84SAndroid Build Coastguard Worker     writeall(fd, &timestamp, sizeof(timestamp));
1187*cf5a6c84SAndroid Build Coastguard Worker 
1188*cf5a6c84SAndroid Build Coastguard Worker     while (listdls) {
1189*cf5a6c84SAndroid Build Coastguard Worker       dls = (dyn_lease*)listdls->arg;
1190*cf5a6c84SAndroid Build Coastguard Worker       tmp_time = dls->expires;
1191*cf5a6c84SAndroid Build Coastguard Worker       dls->expires -= curr;
1192*cf5a6c84SAndroid Build Coastguard Worker       if ((int32_t) dls->expires < 0) goto skip;
1193*cf5a6c84SAndroid Build Coastguard Worker       dls->expires = htonl(dls->expires);
1194*cf5a6c84SAndroid Build Coastguard Worker       writeall(fd, dls, sizeof(dyn_lease));
1195*cf5a6c84SAndroid Build Coastguard Worker skip:
1196*cf5a6c84SAndroid Build Coastguard Worker       dls->expires = tmp_time;
1197*cf5a6c84SAndroid Build Coastguard Worker       listdls = listdls->next;
1198*cf5a6c84SAndroid Build Coastguard Worker     }
1199*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
1200*cf5a6c84SAndroid Build Coastguard Worker     if (gconfig.notify_file) {
1201*cf5a6c84SAndroid Build Coastguard Worker       char *argv[3];
1202*cf5a6c84SAndroid Build Coastguard Worker       argv[0] = gconfig.notify_file;
1203*cf5a6c84SAndroid Build Coastguard Worker       argv[1] = gconfig.lease_file;
1204*cf5a6c84SAndroid Build Coastguard Worker       argv[2] = NULL;
1205*cf5a6c84SAndroid Build Coastguard Worker       run_notify(argv);
1206*cf5a6c84SAndroid Build Coastguard Worker     }
1207*cf5a6c84SAndroid Build Coastguard Worker   }
1208*cf5a6c84SAndroid Build Coastguard Worker }
1209*cf5a6c84SAndroid Build Coastguard Worker 
write_lease6file(void)1210*cf5a6c84SAndroid Build Coastguard Worker static void write_lease6file(void)
1211*cf5a6c84SAndroid Build Coastguard Worker {
1212*cf5a6c84SAndroid Build Coastguard Worker   int fd;
1213*cf5a6c84SAndroid Build Coastguard Worker   uint32_t curr, tmp_time;
1214*cf5a6c84SAndroid Build Coastguard Worker   int64_t timestamp;
1215*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases;
1216*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease6 *dls6;
1217*cf5a6c84SAndroid Build Coastguard Worker 
1218*cf5a6c84SAndroid Build Coastguard Worker   if ((fd = open(gconfig.lease6_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
1219*cf5a6c84SAndroid Build Coastguard Worker     perror_msg("can't open %s ", gconfig.lease6_file);
1220*cf5a6c84SAndroid Build Coastguard Worker   } else {
1221*cf5a6c84SAndroid Build Coastguard Worker     curr = timestamp = time(NULL);
1222*cf5a6c84SAndroid Build Coastguard Worker     timestamp = SWAP_BE64(timestamp);
1223*cf5a6c84SAndroid Build Coastguard Worker     writeall(fd, &timestamp, sizeof(timestamp));
1224*cf5a6c84SAndroid Build Coastguard Worker 
1225*cf5a6c84SAndroid Build Coastguard Worker     while (listdls) {
1226*cf5a6c84SAndroid Build Coastguard Worker       dls6 = (dyn_lease6*)listdls->arg;
1227*cf5a6c84SAndroid Build Coastguard Worker       tmp_time = dls6->expires;
1228*cf5a6c84SAndroid Build Coastguard Worker       dls6->expires -= curr;
1229*cf5a6c84SAndroid Build Coastguard Worker       if ((int32_t) dls6->expires < 0) goto skip;
1230*cf5a6c84SAndroid Build Coastguard Worker       dls6->expires = htonl(dls6->expires);
1231*cf5a6c84SAndroid Build Coastguard Worker       writeall(fd, dls6, sizeof(dyn_lease6));
1232*cf5a6c84SAndroid Build Coastguard Worker skip:
1233*cf5a6c84SAndroid Build Coastguard Worker       dls6->expires = tmp_time;
1234*cf5a6c84SAndroid Build Coastguard Worker       listdls = listdls->next;
1235*cf5a6c84SAndroid Build Coastguard Worker     }
1236*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
1237*cf5a6c84SAndroid Build Coastguard Worker     if (gconfig.notify_file) {
1238*cf5a6c84SAndroid Build Coastguard Worker       char *argv[3];
1239*cf5a6c84SAndroid Build Coastguard Worker       argv[0] = gconfig.notify_file;
1240*cf5a6c84SAndroid Build Coastguard Worker       argv[1] = gconfig.lease6_file;
1241*cf5a6c84SAndroid Build Coastguard Worker       argv[2] = NULL;
1242*cf5a6c84SAndroid Build Coastguard Worker       run_notify(argv);
1243*cf5a6c84SAndroid Build Coastguard Worker     }
1244*cf5a6c84SAndroid Build Coastguard Worker   }
1245*cf5a6c84SAndroid Build Coastguard Worker }
1246*cf5a6c84SAndroid Build Coastguard Worker 
1247*cf5a6c84SAndroid Build Coastguard Worker // Update max lease time from options.
set_maxlease(void)1248*cf5a6c84SAndroid Build Coastguard Worker static void set_maxlease(void)
1249*cf5a6c84SAndroid Build Coastguard Worker {
1250*cf5a6c84SAndroid Build Coastguard Worker   int count, size = ARRAY_LEN(options_list);
1251*cf5a6c84SAndroid Build Coastguard Worker   for (count = 0; count < size; count++)
1252*cf5a6c84SAndroid Build Coastguard Worker     if (options_list[count].val && options_list[count].code == (DHCP_OPT_LEASE_TIME)) {
1253*cf5a6c84SAndroid Build Coastguard Worker       gconfig.max_lease_sec = *((uint32_t*)options_list[count].val);
1254*cf5a6c84SAndroid Build Coastguard Worker       break;
1255*cf5a6c84SAndroid Build Coastguard Worker     }
1256*cf5a6c84SAndroid Build Coastguard Worker   if (!gconfig.max_lease_sec) gconfig.max_lease_sec = (60*60*24*10);// DEFAULT_LEASE_TIME;
1257*cf5a6c84SAndroid Build Coastguard Worker }
1258*cf5a6c84SAndroid Build Coastguard Worker 
1259*cf5a6c84SAndroid Build Coastguard Worker // Returns lease time for client.
get_lease(uint32_t req_exp)1260*cf5a6c84SAndroid Build Coastguard Worker static uint32_t get_lease(uint32_t req_exp)
1261*cf5a6c84SAndroid Build Coastguard Worker {
1262*cf5a6c84SAndroid Build Coastguard Worker   uint32_t now = time(NULL);
1263*cf5a6c84SAndroid Build Coastguard Worker   req_exp = req_exp - now;
1264*cf5a6c84SAndroid Build Coastguard Worker   if(addr_version == AF_INET6) {
1265*cf5a6c84SAndroid Build Coastguard Worker     if ((req_exp <= 0) || req_exp > gconfig.pref_lifetime ||
1266*cf5a6c84SAndroid Build Coastguard Worker         req_exp > gconfig.valid_lifetime) {
1267*cf5a6c84SAndroid Build Coastguard Worker       if ((gconfig.pref_lifetime > gconfig.valid_lifetime)) {
1268*cf5a6c84SAndroid Build Coastguard Worker         error_msg("The valid lifetime must be greater than the preferred lifetime, \
1269*cf5a6c84SAndroid Build Coastguard Worker             setting to valid lifetime %u", gconfig.valid_lifetime);
1270*cf5a6c84SAndroid Build Coastguard Worker         return gconfig.valid_lifetime;
1271*cf5a6c84SAndroid Build Coastguard Worker       }
1272*cf5a6c84SAndroid Build Coastguard Worker       return gconfig.pref_lifetime;
1273*cf5a6c84SAndroid Build Coastguard Worker     }
1274*cf5a6c84SAndroid Build Coastguard Worker   } else {
1275*cf5a6c84SAndroid Build Coastguard Worker     if ((req_exp <= 0) || (req_exp > gconfig.max_lease_sec))
1276*cf5a6c84SAndroid Build Coastguard Worker       return gconfig.max_lease_sec;
1277*cf5a6c84SAndroid Build Coastguard Worker 
1278*cf5a6c84SAndroid Build Coastguard Worker     if (req_exp < gconfig.min_lease_sec)
1279*cf5a6c84SAndroid Build Coastguard Worker       return gconfig.min_lease_sec;
1280*cf5a6c84SAndroid Build Coastguard Worker   }
1281*cf5a6c84SAndroid Build Coastguard Worker 
1282*cf5a6c84SAndroid Build Coastguard Worker   return req_exp;
1283*cf5a6c84SAndroid Build Coastguard Worker }
1284*cf5a6c84SAndroid Build Coastguard Worker 
verifyip6_in_lease(uint8_t * nip6,uint8_t * duid,uint16_t ia_type,uint32_t iaid)1285*cf5a6c84SAndroid Build Coastguard Worker static int verifyip6_in_lease(uint8_t *nip6, uint8_t *duid, uint16_t ia_type, uint32_t iaid)
1286*cf5a6c84SAndroid Build Coastguard Worker {
1287*cf5a6c84SAndroid Build Coastguard Worker   static_lease6 *sls6;
1288*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls;
1289*cf5a6c84SAndroid Build Coastguard Worker 
1290*cf5a6c84SAndroid Build Coastguard Worker   for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
1291*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease6*) listdls->arg)->lease_nip6, nip6, sizeof(uint32_t)*4))
1292*cf5a6c84SAndroid Build Coastguard Worker       return -1;
1293*cf5a6c84SAndroid Build Coastguard Worker 
1294*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)
1295*cf5a6c84SAndroid Build Coastguard Worker         && ((dyn_lease6*) listdls->arg)->ia_type == ia_type)
1296*cf5a6c84SAndroid Build Coastguard Worker       return -1;
1297*cf5a6c84SAndroid Build Coastguard Worker   }
1298*cf5a6c84SAndroid Build Coastguard Worker   for (sls6 = gstate.leases.sleases6; sls6; sls6 = sls6->next)
1299*cf5a6c84SAndroid Build Coastguard Worker     if (memcmp(sls6->nip6, nip6, sizeof(uint32_t)*4)==0) return -2;
1300*cf5a6c84SAndroid Build Coastguard Worker 
1301*cf5a6c84SAndroid Build Coastguard Worker   if (memcmp(nip6, gconfig.start_ip6, sizeof(uint32_t)*4) < 0 ||
1302*cf5a6c84SAndroid Build Coastguard Worker       memcmp(nip6, gconfig.end_ip6, sizeof(uint32_t)*4) > 0)
1303*cf5a6c84SAndroid Build Coastguard Worker     return -3;
1304*cf5a6c84SAndroid Build Coastguard Worker 
1305*cf5a6c84SAndroid Build Coastguard Worker   return 0;
1306*cf5a6c84SAndroid Build Coastguard Worker }
1307*cf5a6c84SAndroid Build Coastguard Worker 
1308*cf5a6c84SAndroid Build Coastguard Worker // Verify ip NIP in current leases ( assigned or not)
verifyip_in_lease(uint32_t nip,uint8_t mac[6])1309*cf5a6c84SAndroid Build Coastguard Worker static int verifyip_in_lease(uint32_t nip, uint8_t mac[6])
1310*cf5a6c84SAndroid Build Coastguard Worker {
1311*cf5a6c84SAndroid Build Coastguard Worker   static_lease *sls;
1312*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls;
1313*cf5a6c84SAndroid Build Coastguard Worker 
1314*cf5a6c84SAndroid Build Coastguard Worker   for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
1315*cf5a6c84SAndroid Build Coastguard Worker     if (((dyn_lease*) listdls->arg)->lease_nip == nip) {
1316*cf5a6c84SAndroid Build Coastguard Worker       if (((int32_t)(((dyn_lease*) listdls->arg)->expires) - time(NULL)) < 0)
1317*cf5a6c84SAndroid Build Coastguard Worker         return 0;
1318*cf5a6c84SAndroid Build Coastguard Worker       return -1;
1319*cf5a6c84SAndroid Build Coastguard Worker     }
1320*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) return -1;
1321*cf5a6c84SAndroid Build Coastguard Worker   }
1322*cf5a6c84SAndroid Build Coastguard Worker   for (sls = gstate.leases.sleases; sls; sls = sls->next)
1323*cf5a6c84SAndroid Build Coastguard Worker     if (sls->nip == nip) return -2;
1324*cf5a6c84SAndroid Build Coastguard Worker 
1325*cf5a6c84SAndroid Build Coastguard Worker   if ((ntohl(nip) < gconfig.start_ip) || (ntohl(nip) > gconfig.end_ip))
1326*cf5a6c84SAndroid Build Coastguard Worker     return -3;
1327*cf5a6c84SAndroid Build Coastguard Worker 
1328*cf5a6c84SAndroid Build Coastguard Worker   return 0;
1329*cf5a6c84SAndroid Build Coastguard Worker }
1330*cf5a6c84SAndroid Build Coastguard Worker 
1331*cf5a6c84SAndroid Build Coastguard Worker // add ip assigned_nip to dynamic lease.
addip_to_lease(uint32_t assigned_nip,uint8_t mac[6],uint32_t * req_exp,char * hostname,uint8_t update)1332*cf5a6c84SAndroid Build Coastguard Worker static int addip_to_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname, uint8_t update)
1333*cf5a6c84SAndroid Build Coastguard Worker {
1334*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease *dls;
1335*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases;
1336*cf5a6c84SAndroid Build Coastguard Worker   uint32_t now = time(NULL);
1337*cf5a6c84SAndroid Build Coastguard Worker 
1338*cf5a6c84SAndroid Build Coastguard Worker   while (listdls) {
1339*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
1340*cf5a6c84SAndroid Build Coastguard Worker       if (update) *req_exp = get_lease(*req_exp + ((dyn_lease*) listdls->arg)->expires);
1341*cf5a6c84SAndroid Build Coastguard Worker       ((dyn_lease*) listdls->arg)->expires = *req_exp + now;
1342*cf5a6c84SAndroid Build Coastguard Worker       return 0;
1343*cf5a6c84SAndroid Build Coastguard Worker     }
1344*cf5a6c84SAndroid Build Coastguard Worker     listdls = listdls->next;
1345*cf5a6c84SAndroid Build Coastguard Worker   }
1346*cf5a6c84SAndroid Build Coastguard Worker 
1347*cf5a6c84SAndroid Build Coastguard Worker   dls = xzalloc(sizeof(dyn_lease));
1348*cf5a6c84SAndroid Build Coastguard Worker   memcpy(dls->lease_mac, mac, 6);
1349*cf5a6c84SAndroid Build Coastguard Worker   dls->lease_nip = assigned_nip;
1350*cf5a6c84SAndroid Build Coastguard Worker   if (hostname) memcpy(dls->hostname, hostname, 20);
1351*cf5a6c84SAndroid Build Coastguard Worker 
1352*cf5a6c84SAndroid Build Coastguard Worker   if (update) *req_exp = get_lease(*req_exp + now);
1353*cf5a6c84SAndroid Build Coastguard Worker   dls->expires = *req_exp + now;
1354*cf5a6c84SAndroid Build Coastguard Worker 
1355*cf5a6c84SAndroid Build Coastguard Worker   listdls = xzalloc(sizeof(struct arg_list));
1356*cf5a6c84SAndroid Build Coastguard Worker   listdls->next = gstate.dleases;
1357*cf5a6c84SAndroid Build Coastguard Worker   listdls->arg = (char*)dls;
1358*cf5a6c84SAndroid Build Coastguard Worker   gstate.dleases = listdls;
1359*cf5a6c84SAndroid Build Coastguard Worker 
1360*cf5a6c84SAndroid Build Coastguard Worker   return 0;
1361*cf5a6c84SAndroid Build Coastguard Worker }
1362*cf5a6c84SAndroid Build Coastguard Worker 
addip6_to_lease(uint8_t * assigned_nip,uint8_t * duid,uint16_t duid_len,uint16_t ia_type,uint32_t iaid,uint32_t * lifetime,uint8_t update)1363*cf5a6c84SAndroid Build Coastguard Worker static int addip6_to_lease(uint8_t *assigned_nip, uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime, uint8_t update)
1364*cf5a6c84SAndroid Build Coastguard Worker {
1365*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease6 *dls6;
1366*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases;
1367*cf5a6c84SAndroid Build Coastguard Worker   uint32_t now = time(NULL);
1368*cf5a6c84SAndroid Build Coastguard Worker 
1369*cf5a6c84SAndroid Build Coastguard Worker   while (listdls) {
1370*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)) {
1371*cf5a6c84SAndroid Build Coastguard Worker       if (update) *lifetime = get_lease(*lifetime + ((dyn_lease6*) listdls->arg)->expires);
1372*cf5a6c84SAndroid Build Coastguard Worker       ((dyn_lease6*) listdls->arg)->expires = *lifetime + now;
1373*cf5a6c84SAndroid Build Coastguard Worker       return 0;
1374*cf5a6c84SAndroid Build Coastguard Worker     }
1375*cf5a6c84SAndroid Build Coastguard Worker     listdls = listdls->next;
1376*cf5a6c84SAndroid Build Coastguard Worker   }
1377*cf5a6c84SAndroid Build Coastguard Worker 
1378*cf5a6c84SAndroid Build Coastguard Worker   dls6 = xzalloc(sizeof(dyn_lease6));
1379*cf5a6c84SAndroid Build Coastguard Worker   dls6->duid_len = duid_len;
1380*cf5a6c84SAndroid Build Coastguard Worker   memcpy(dls6->duid, duid, duid_len);
1381*cf5a6c84SAndroid Build Coastguard Worker   dls6->ia_type = ia_type;
1382*cf5a6c84SAndroid Build Coastguard Worker   dls6->iaid = iaid;
1383*cf5a6c84SAndroid Build Coastguard Worker   memcpy(dls6->lease_nip6, assigned_nip, sizeof(uint32_t)*4);
1384*cf5a6c84SAndroid Build Coastguard Worker 
1385*cf5a6c84SAndroid Build Coastguard Worker   if (update) *lifetime = get_lease(*lifetime + now);
1386*cf5a6c84SAndroid Build Coastguard Worker   dls6->expires = *lifetime + now;
1387*cf5a6c84SAndroid Build Coastguard Worker 
1388*cf5a6c84SAndroid Build Coastguard Worker   listdls = xzalloc(sizeof(struct arg_list));
1389*cf5a6c84SAndroid Build Coastguard Worker   listdls->next = gstate.dleases;
1390*cf5a6c84SAndroid Build Coastguard Worker   listdls->arg = (char*)dls6;
1391*cf5a6c84SAndroid Build Coastguard Worker   gstate.dleases = listdls;
1392*cf5a6c84SAndroid Build Coastguard Worker 
1393*cf5a6c84SAndroid Build Coastguard Worker   return 0;
1394*cf5a6c84SAndroid Build Coastguard Worker }
1395*cf5a6c84SAndroid Build Coastguard Worker 
1396*cf5a6c84SAndroid Build Coastguard Worker // delete ip assigned_nip from dynamic lease.
delip_from_lease(uint32_t assigned_nip,uint8_t mac[6],uint32_t del_time)1397*cf5a6c84SAndroid Build Coastguard Worker static int delip_from_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t del_time)
1398*cf5a6c84SAndroid Build Coastguard Worker {
1399*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases;
1400*cf5a6c84SAndroid Build Coastguard Worker 
1401*cf5a6c84SAndroid Build Coastguard Worker   while (listdls) {
1402*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
1403*cf5a6c84SAndroid Build Coastguard Worker       ((dyn_lease*) listdls->arg)->expires = del_time + time(NULL);
1404*cf5a6c84SAndroid Build Coastguard Worker       return 0;
1405*cf5a6c84SAndroid Build Coastguard Worker     }
1406*cf5a6c84SAndroid Build Coastguard Worker     listdls = listdls->next;
1407*cf5a6c84SAndroid Build Coastguard Worker   }
1408*cf5a6c84SAndroid Build Coastguard Worker   return -1;
1409*cf5a6c84SAndroid Build Coastguard Worker }
1410*cf5a6c84SAndroid Build Coastguard Worker 
1411*cf5a6c84SAndroid Build Coastguard Worker // returns a IP from static, dynamic leases or free ip pool, 0 otherwise.
getip_from_pool(uint32_t req_nip,uint8_t mac[6],uint32_t * req_exp,char * hostname)1412*cf5a6c84SAndroid Build Coastguard Worker static uint32_t getip_from_pool(uint32_t req_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname)
1413*cf5a6c84SAndroid Build Coastguard Worker {
1414*cf5a6c84SAndroid Build Coastguard Worker   uint32_t nip = 0;
1415*cf5a6c84SAndroid Build Coastguard Worker   static_lease *sls = gstate.leases.sleases;
1416*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls = gstate.dleases, *tmp = NULL;
1417*cf5a6c84SAndroid Build Coastguard Worker 
1418*cf5a6c84SAndroid Build Coastguard Worker   if (req_nip && (!verifyip_in_lease(req_nip, mac))) nip = req_nip;
1419*cf5a6c84SAndroid Build Coastguard Worker 
1420*cf5a6c84SAndroid Build Coastguard Worker   if (!nip) {
1421*cf5a6c84SAndroid Build Coastguard Worker     while (listdls) {
1422*cf5a6c84SAndroid Build Coastguard Worker       if (!memcmp(((dyn_lease*)listdls->arg)->lease_mac, mac, 6)) {
1423*cf5a6c84SAndroid Build Coastguard Worker         nip = ((dyn_lease*)listdls->arg)->lease_nip;
1424*cf5a6c84SAndroid Build Coastguard Worker         if (tmp) tmp->next = listdls->next;
1425*cf5a6c84SAndroid Build Coastguard Worker         else gstate.dleases = listdls->next;
1426*cf5a6c84SAndroid Build Coastguard Worker         free(listdls->arg);
1427*cf5a6c84SAndroid Build Coastguard Worker         free(listdls);
1428*cf5a6c84SAndroid Build Coastguard Worker         if (verifyip_in_lease(nip, mac) < 0) nip = 0;
1429*cf5a6c84SAndroid Build Coastguard Worker         break;
1430*cf5a6c84SAndroid Build Coastguard Worker       }
1431*cf5a6c84SAndroid Build Coastguard Worker       tmp = listdls;
1432*cf5a6c84SAndroid Build Coastguard Worker       listdls = listdls->next;
1433*cf5a6c84SAndroid Build Coastguard Worker     }
1434*cf5a6c84SAndroid Build Coastguard Worker   }
1435*cf5a6c84SAndroid Build Coastguard Worker   if (!nip) {
1436*cf5a6c84SAndroid Build Coastguard Worker     while (sls) {
1437*cf5a6c84SAndroid Build Coastguard Worker       if (memcmp(sls->mac, mac, 6) == 0) {
1438*cf5a6c84SAndroid Build Coastguard Worker         nip = sls->nip;
1439*cf5a6c84SAndroid Build Coastguard Worker         break;
1440*cf5a6c84SAndroid Build Coastguard Worker       }
1441*cf5a6c84SAndroid Build Coastguard Worker       sls = sls->next;
1442*cf5a6c84SAndroid Build Coastguard Worker     }
1443*cf5a6c84SAndroid Build Coastguard Worker   }
1444*cf5a6c84SAndroid Build Coastguard Worker   if (!nip) {
1445*cf5a6c84SAndroid Build Coastguard Worker     for (nip = htonl(gconfig.start_ip); ntohl(nip) <= gconfig.end_ip; ) {
1446*cf5a6c84SAndroid Build Coastguard Worker       if (!verifyip_in_lease(nip, mac)) break;
1447*cf5a6c84SAndroid Build Coastguard Worker       nip = ntohl(nip);
1448*cf5a6c84SAndroid Build Coastguard Worker       nip = htonl(++nip);
1449*cf5a6c84SAndroid Build Coastguard Worker     }
1450*cf5a6c84SAndroid Build Coastguard Worker     if (ntohl(nip) > gconfig.end_ip) {
1451*cf5a6c84SAndroid Build Coastguard Worker       nip = 0;
1452*cf5a6c84SAndroid Build Coastguard Worker       infomsg(infomode, "can't find free IP in IP Pool.");
1453*cf5a6c84SAndroid Build Coastguard Worker     }
1454*cf5a6c84SAndroid Build Coastguard Worker   }
1455*cf5a6c84SAndroid Build Coastguard Worker   if (nip) addip_to_lease(nip, mac, req_exp, hostname, 1);
1456*cf5a6c84SAndroid Build Coastguard Worker   return nip;
1457*cf5a6c84SAndroid Build Coastguard Worker }
1458*cf5a6c84SAndroid Build Coastguard Worker 
getip6_from_pool(uint8_t * duid,uint16_t duid_len,uint16_t ia_type,uint32_t iaid,uint32_t * lifetime)1459*cf5a6c84SAndroid Build Coastguard Worker static uint8_t *getip6_from_pool(uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime)
1460*cf5a6c84SAndroid Build Coastguard Worker {
1461*cf5a6c84SAndroid Build Coastguard Worker   static uint8_t nip6[16] = {0, };
1462*cf5a6c84SAndroid Build Coastguard Worker   static_lease6 *sls6 = gstate.leases.sleases6;
1463*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *listdls6 = gstate.dleases, *tmp = NULL;
1464*cf5a6c84SAndroid Build Coastguard Worker 
1465*cf5a6c84SAndroid Build Coastguard Worker   while(listdls6) {
1466*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(((dyn_lease6*)listdls6->arg)->duid, duid, duid_len)) {
1467*cf5a6c84SAndroid Build Coastguard Worker       memcpy(nip6, ((dyn_lease6*)listdls6->arg)->lease_nip6, sizeof(nip6));
1468*cf5a6c84SAndroid Build Coastguard Worker       if(tmp) tmp->next = listdls6->next;
1469*cf5a6c84SAndroid Build Coastguard Worker       else gstate.dleases = listdls6->next;
1470*cf5a6c84SAndroid Build Coastguard Worker       free(listdls6->arg);
1471*cf5a6c84SAndroid Build Coastguard Worker       free(listdls6);
1472*cf5a6c84SAndroid Build Coastguard Worker 
1473*cf5a6c84SAndroid Build Coastguard Worker       if(verifyip6_in_lease(nip6, duid, ia_type, iaid) < 0)
1474*cf5a6c84SAndroid Build Coastguard Worker         memset(nip6, 0, sizeof(nip6));
1475*cf5a6c84SAndroid Build Coastguard Worker       break;
1476*cf5a6c84SAndroid Build Coastguard Worker     }
1477*cf5a6c84SAndroid Build Coastguard Worker     tmp = listdls6;
1478*cf5a6c84SAndroid Build Coastguard Worker     listdls6 = listdls6->next;
1479*cf5a6c84SAndroid Build Coastguard Worker   }
1480*cf5a6c84SAndroid Build Coastguard Worker 
1481*cf5a6c84SAndroid Build Coastguard Worker   if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
1482*cf5a6c84SAndroid Build Coastguard Worker     while(sls6) {
1483*cf5a6c84SAndroid Build Coastguard Worker       if(!memcmp(sls6->duid, duid, 6)) {
1484*cf5a6c84SAndroid Build Coastguard Worker         memcpy(nip6, sls6->nip6, sizeof(nip6));
1485*cf5a6c84SAndroid Build Coastguard Worker         break;
1486*cf5a6c84SAndroid Build Coastguard Worker       }
1487*cf5a6c84SAndroid Build Coastguard Worker       sls6 = sls6->next;
1488*cf5a6c84SAndroid Build Coastguard Worker     }
1489*cf5a6c84SAndroid Build Coastguard Worker   }
1490*cf5a6c84SAndroid Build Coastguard Worker 
1491*cf5a6c84SAndroid Build Coastguard Worker   if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
1492*cf5a6c84SAndroid Build Coastguard Worker     memcpy(nip6, gconfig.start_ip6, sizeof(nip6));
1493*cf5a6c84SAndroid Build Coastguard Worker     while(memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) < 0) {
1494*cf5a6c84SAndroid Build Coastguard Worker       if(!verifyip6_in_lease(nip6, duid, ia_type, iaid)) break;
1495*cf5a6c84SAndroid Build Coastguard Worker       int i=sizeof(nip6);
1496*cf5a6c84SAndroid Build Coastguard Worker       while(i--) {
1497*cf5a6c84SAndroid Build Coastguard Worker         ++nip6[i];
1498*cf5a6c84SAndroid Build Coastguard Worker         if (!nip6[i]) {
1499*cf5a6c84SAndroid Build Coastguard Worker           if(i==(sizeof(nip6)-1)) ++nip6[i];
1500*cf5a6c84SAndroid Build Coastguard Worker           ++nip6[i-1];
1501*cf5a6c84SAndroid Build Coastguard Worker         } else
1502*cf5a6c84SAndroid Build Coastguard Worker           break;
1503*cf5a6c84SAndroid Build Coastguard Worker       }
1504*cf5a6c84SAndroid Build Coastguard Worker     }
1505*cf5a6c84SAndroid Build Coastguard Worker 
1506*cf5a6c84SAndroid Build Coastguard Worker     if (memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) > 0) {
1507*cf5a6c84SAndroid Build Coastguard Worker       memset(nip6, 0, sizeof(nip6));
1508*cf5a6c84SAndroid Build Coastguard Worker       infomsg(infomode, "can't find free IP in IPv6 Pool.");
1509*cf5a6c84SAndroid Build Coastguard Worker     }
1510*cf5a6c84SAndroid Build Coastguard Worker   }
1511*cf5a6c84SAndroid Build Coastguard Worker 
1512*cf5a6c84SAndroid Build Coastguard Worker   if(memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
1513*cf5a6c84SAndroid Build Coastguard Worker     addip6_to_lease(nip6, duid, duid_len, ia_type, iaid, lifetime, 1);
1514*cf5a6c84SAndroid Build Coastguard Worker     infomsg(infomode, "Assigned IPv6 %02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X",
1515*cf5a6c84SAndroid Build Coastguard Worker         nip6[0], nip6[1], nip6[2], nip6[3], nip6[4], nip6[5], nip6[6], nip6[7], nip6[8],
1516*cf5a6c84SAndroid Build Coastguard Worker         nip6[9], nip6[10], nip6[11], nip6[12], nip6[13], nip6[14], nip6[15]);
1517*cf5a6c84SAndroid Build Coastguard Worker   }
1518*cf5a6c84SAndroid Build Coastguard Worker   return nip6;
1519*cf5a6c84SAndroid Build Coastguard Worker }
1520*cf5a6c84SAndroid Build Coastguard Worker 
read_leasefile(void)1521*cf5a6c84SAndroid Build Coastguard Worker static void read_leasefile(void)
1522*cf5a6c84SAndroid Build Coastguard Worker {
1523*cf5a6c84SAndroid Build Coastguard Worker   uint32_t passed, ip;
1524*cf5a6c84SAndroid Build Coastguard Worker   int32_t tmp_time;
1525*cf5a6c84SAndroid Build Coastguard Worker   int64_t timestamp;
1526*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease *dls;
1527*cf5a6c84SAndroid Build Coastguard Worker   int fd = open(gconfig.lease_file, O_RDONLY);
1528*cf5a6c84SAndroid Build Coastguard Worker 
1529*cf5a6c84SAndroid Build Coastguard Worker   dls = xzalloc(sizeof(dyn_lease));
1530*cf5a6c84SAndroid Build Coastguard Worker 
1531*cf5a6c84SAndroid Build Coastguard Worker   if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
1532*cf5a6c84SAndroid Build Coastguard Worker     goto lease_error_exit;
1533*cf5a6c84SAndroid Build Coastguard Worker 
1534*cf5a6c84SAndroid Build Coastguard Worker   timestamp = SWAP_BE64(timestamp);
1535*cf5a6c84SAndroid Build Coastguard Worker   passed = time(NULL) - timestamp;
1536*cf5a6c84SAndroid Build Coastguard Worker   if ((uint64_t)passed > 12 * 60 * 60) goto lease_error_exit;
1537*cf5a6c84SAndroid Build Coastguard Worker 
1538*cf5a6c84SAndroid Build Coastguard Worker   while (read(fd, dls, sizeof(dyn_lease)) == sizeof(dyn_lease)) {
1539*cf5a6c84SAndroid Build Coastguard Worker     ip = ntohl(dls->lease_nip);
1540*cf5a6c84SAndroid Build Coastguard Worker     if (ip >= gconfig.start_ip && ip <= gconfig.end_ip) {
1541*cf5a6c84SAndroid Build Coastguard Worker       tmp_time = ntohl(dls->expires) - passed;
1542*cf5a6c84SAndroid Build Coastguard Worker       if (tmp_time < 0) continue;
1543*cf5a6c84SAndroid Build Coastguard Worker       addip_to_lease(dls->lease_nip, dls->lease_mac,
1544*cf5a6c84SAndroid Build Coastguard Worker           (uint32_t*)&tmp_time, dls->hostname, 0);
1545*cf5a6c84SAndroid Build Coastguard Worker     }
1546*cf5a6c84SAndroid Build Coastguard Worker   }
1547*cf5a6c84SAndroid Build Coastguard Worker lease_error_exit:
1548*cf5a6c84SAndroid Build Coastguard Worker   free(dls);
1549*cf5a6c84SAndroid Build Coastguard Worker   close(fd);
1550*cf5a6c84SAndroid Build Coastguard Worker }
1551*cf5a6c84SAndroid Build Coastguard Worker 
read_lease6file(void)1552*cf5a6c84SAndroid Build Coastguard Worker static void read_lease6file(void)
1553*cf5a6c84SAndroid Build Coastguard Worker {
1554*cf5a6c84SAndroid Build Coastguard Worker   uint32_t passed;
1555*cf5a6c84SAndroid Build Coastguard Worker   uint32_t tmp_time;
1556*cf5a6c84SAndroid Build Coastguard Worker   int64_t timestamp;
1557*cf5a6c84SAndroid Build Coastguard Worker   dyn_lease6 *dls6;
1558*cf5a6c84SAndroid Build Coastguard Worker   int fd = open(gconfig.lease6_file, O_RDONLY);
1559*cf5a6c84SAndroid Build Coastguard Worker 
1560*cf5a6c84SAndroid Build Coastguard Worker   dls6 = xzalloc(sizeof(dyn_lease6));
1561*cf5a6c84SAndroid Build Coastguard Worker 
1562*cf5a6c84SAndroid Build Coastguard Worker   if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
1563*cf5a6c84SAndroid Build Coastguard Worker     goto lease6_error_exit;
1564*cf5a6c84SAndroid Build Coastguard Worker 
1565*cf5a6c84SAndroid Build Coastguard Worker   timestamp = SWAP_BE64(timestamp);
1566*cf5a6c84SAndroid Build Coastguard Worker   passed = time(NULL) - timestamp;
1567*cf5a6c84SAndroid Build Coastguard Worker   if ((uint64_t)passed > 12 * 60 * 60) goto lease6_error_exit;
1568*cf5a6c84SAndroid Build Coastguard Worker 
1569*cf5a6c84SAndroid Build Coastguard Worker   while (read(fd, dls6, sizeof(dyn_lease6)) == sizeof(dyn_lease6)) {
1570*cf5a6c84SAndroid Build Coastguard Worker     if (memcmp(dls6->lease_nip6, gconfig.start_ip6, sizeof(uint32_t)*4) > 0 &&
1571*cf5a6c84SAndroid Build Coastguard Worker         memcmp(dls6->lease_nip6, gconfig.end_ip6, sizeof(uint32_t)*4) < 0) {
1572*cf5a6c84SAndroid Build Coastguard Worker       tmp_time = ntohl(dls6->expires) - passed;
1573*cf5a6c84SAndroid Build Coastguard Worker       if (tmp_time < 0U) continue;
1574*cf5a6c84SAndroid Build Coastguard Worker       addip6_to_lease(dls6->lease_nip6, dls6->duid, dls6->duid_len, dls6->ia_type, dls6->iaid,
1575*cf5a6c84SAndroid Build Coastguard Worker           (uint32_t*)&tmp_time, 0);
1576*cf5a6c84SAndroid Build Coastguard Worker     }
1577*cf5a6c84SAndroid Build Coastguard Worker   }
1578*cf5a6c84SAndroid Build Coastguard Worker 
1579*cf5a6c84SAndroid Build Coastguard Worker lease6_error_exit:
1580*cf5a6c84SAndroid Build Coastguard Worker   free(dls6);
1581*cf5a6c84SAndroid Build Coastguard Worker   close(fd);
1582*cf5a6c84SAndroid Build Coastguard Worker }
1583*cf5a6c84SAndroid Build Coastguard Worker 
dhcpd_main(void)1584*cf5a6c84SAndroid Build Coastguard Worker void dhcpd_main(void)
1585*cf5a6c84SAndroid Build Coastguard Worker {
1586*cf5a6c84SAndroid Build Coastguard Worker   struct timeval tv;
1587*cf5a6c84SAndroid Build Coastguard Worker   int retval, i;
1588*cf5a6c84SAndroid Build Coastguard Worker   char *optptr, msgtype = 0, *hstname = 0, transactionid[3] = {0};
1589*cf5a6c84SAndroid Build Coastguard Worker   unsigned short optlen = 0;
1590*cf5a6c84SAndroid Build Coastguard Worker   unsigned waited = 0, serverid = 0, requested_nip = 0, reqested_lease = 0,
1591*cf5a6c84SAndroid Build Coastguard Worker            ip_pool_size = 0;
1592*cf5a6c84SAndroid Build Coastguard Worker   fd_set rfds;
1593*cf5a6c84SAndroid Build Coastguard Worker 
1594*cf5a6c84SAndroid Build Coastguard Worker   infomode = LOG_CONSOLE;
1595*cf5a6c84SAndroid Build Coastguard Worker   if (!FLAG(f)) {
1596*cf5a6c84SAndroid Build Coastguard Worker     daemon(0, 0);
1597*cf5a6c84SAndroid Build Coastguard Worker     infomode = LOG_SILENT;
1598*cf5a6c84SAndroid Build Coastguard Worker   }
1599*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(S)) {
1600*cf5a6c84SAndroid Build Coastguard Worker     openlog("UDHCPD :", LOG_PID, LOG_DAEMON);
1601*cf5a6c84SAndroid Build Coastguard Worker     infomode |= LOG_SYSTEM;
1602*cf5a6c84SAndroid Build Coastguard Worker   }
1603*cf5a6c84SAndroid Build Coastguard Worker   setlinebuf(stdout);
1604*cf5a6c84SAndroid Build Coastguard Worker   //DHCPD_CONF_FILE
1605*cf5a6c84SAndroid Build Coastguard Worker   parse_server_config((toys.optc==1) ? *toys.optargs: "/etc/dhcpd.conf",
1606*cf5a6c84SAndroid Build Coastguard Worker     keywords);
1607*cf5a6c84SAndroid Build Coastguard Worker   infomsg(infomode, "toybox dhcpd started");
1608*cf5a6c84SAndroid Build Coastguard Worker 
1609*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(6)) {
1610*cf5a6c84SAndroid Build Coastguard Worker     addr_version = AF_INET6;
1611*cf5a6c84SAndroid Build Coastguard Worker     gconfig.t1 = ntohl(gconfig.t1);
1612*cf5a6c84SAndroid Build Coastguard Worker     gconfig.t2 = ntohl(gconfig.t2);
1613*cf5a6c84SAndroid Build Coastguard Worker     gconfig.pref_lifetime = ntohl(gconfig.pref_lifetime);
1614*cf5a6c84SAndroid Build Coastguard Worker     gconfig.valid_lifetime = ntohl(gconfig.valid_lifetime);
1615*cf5a6c84SAndroid Build Coastguard Worker     gconfig.port = 547;
1616*cf5a6c84SAndroid Build Coastguard Worker     for(i=0; i<4; i++)
1617*cf5a6c84SAndroid Build Coastguard Worker       ip_pool_size += (gconfig.end_ip6[i]-gconfig.start_ip6[i])<<((3-i)*8);
1618*cf5a6c84SAndroid Build Coastguard Worker   } else {
1619*cf5a6c84SAndroid Build Coastguard Worker     gconfig.start_ip = ntohl(gconfig.start_ip);
1620*cf5a6c84SAndroid Build Coastguard Worker     gconfig.end_ip = ntohl(gconfig.end_ip);
1621*cf5a6c84SAndroid Build Coastguard Worker     ip_pool_size = gconfig.end_ip - gconfig.start_ip + 1;
1622*cf5a6c84SAndroid Build Coastguard Worker   }
1623*cf5a6c84SAndroid Build Coastguard Worker 
1624*cf5a6c84SAndroid Build Coastguard Worker   if (gconfig.max_leases > ip_pool_size) {
1625*cf5a6c84SAndroid Build Coastguard Worker     error_msg("max_leases=%u is too big, setting to %u",
1626*cf5a6c84SAndroid Build Coastguard Worker         (unsigned) gconfig.max_leases, ip_pool_size);
1627*cf5a6c84SAndroid Build Coastguard Worker     gconfig.max_leases = ip_pool_size;
1628*cf5a6c84SAndroid Build Coastguard Worker   }
1629*cf5a6c84SAndroid Build Coastguard Worker   write_pid(gconfig.pidfile);
1630*cf5a6c84SAndroid Build Coastguard Worker   set_maxlease();
1631*cf5a6c84SAndroid Build Coastguard Worker   if (TT.i) gconfig.interface = TT.i;
1632*cf5a6c84SAndroid Build Coastguard Worker   if (TT.p) gconfig.port = TT.p;
1633*cf5a6c84SAndroid Build Coastguard Worker   (addr_version==AF_INET6) ? read_lease6file() : read_leasefile();
1634*cf5a6c84SAndroid Build Coastguard Worker 
1635*cf5a6c84SAndroid Build Coastguard Worker   if (get_interface(gconfig.interface, &gconfig.ifindex,
1636*cf5a6c84SAndroid Build Coastguard Worker         (addr_version==AF_INET6)? (void*)gconfig.server_nip6 :
1637*cf5a6c84SAndroid Build Coastguard Worker         (void*)&gconfig.server_nip, gconfig.server_mac) < 0)
1638*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("Failed to get interface %s", gconfig.interface);
1639*cf5a6c84SAndroid Build Coastguard Worker   setup_signal();
1640*cf5a6c84SAndroid Build Coastguard Worker   if (addr_version==AF_INET6) open_listensock6();
1641*cf5a6c84SAndroid Build Coastguard Worker   else {
1642*cf5a6c84SAndroid Build Coastguard Worker     gconfig.server_nip = htonl(gconfig.server_nip);
1643*cf5a6c84SAndroid Build Coastguard Worker     open_listensock();
1644*cf5a6c84SAndroid Build Coastguard Worker   }
1645*cf5a6c84SAndroid Build Coastguard Worker 
1646*cf5a6c84SAndroid Build Coastguard Worker   fcntl(gstate.listensock, F_SETFD, FD_CLOEXEC);
1647*cf5a6c84SAndroid Build Coastguard Worker 
1648*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
1649*cf5a6c84SAndroid Build Coastguard Worker     uint32_t timestmp = time(NULL);
1650*cf5a6c84SAndroid Build Coastguard Worker     FD_ZERO(&rfds);
1651*cf5a6c84SAndroid Build Coastguard Worker     FD_SET(gstate.listensock, &rfds);
1652*cf5a6c84SAndroid Build Coastguard Worker     FD_SET(sigfd.rd, &rfds);
1653*cf5a6c84SAndroid Build Coastguard Worker     tv.tv_sec = gconfig.auto_time - waited;
1654*cf5a6c84SAndroid Build Coastguard Worker     tv.tv_usec = 0;
1655*cf5a6c84SAndroid Build Coastguard Worker     retval = 0;
1656*cf5a6c84SAndroid Build Coastguard Worker     serverid = 0;
1657*cf5a6c84SAndroid Build Coastguard Worker     msgtype = 0;
1658*cf5a6c84SAndroid Build Coastguard Worker 
1659*cf5a6c84SAndroid Build Coastguard Worker     int maxfd = (sigfd.rd > gstate.listensock)? sigfd.rd : gstate.listensock;
1660*cf5a6c84SAndroid Build Coastguard Worker     dbg("select waiting ....\n");
1661*cf5a6c84SAndroid Build Coastguard Worker     retval = select(maxfd + 1, &rfds, NULL, NULL, (gconfig.auto_time?&tv:NULL));
1662*cf5a6c84SAndroid Build Coastguard Worker     if (retval < 0) {
1663*cf5a6c84SAndroid Build Coastguard Worker       if (errno == EINTR) {
1664*cf5a6c84SAndroid Build Coastguard Worker         waited += (unsigned) time(NULL) - timestmp;
1665*cf5a6c84SAndroid Build Coastguard Worker         continue;
1666*cf5a6c84SAndroid Build Coastguard Worker       }
1667*cf5a6c84SAndroid Build Coastguard Worker       dbg("Error in select wait again...\n");
1668*cf5a6c84SAndroid Build Coastguard Worker       continue;
1669*cf5a6c84SAndroid Build Coastguard Worker     }
1670*cf5a6c84SAndroid Build Coastguard Worker     if (!retval) { // Timed out
1671*cf5a6c84SAndroid Build Coastguard Worker       dbg("select wait Timed Out...\n");
1672*cf5a6c84SAndroid Build Coastguard Worker       waited = 0;
1673*cf5a6c84SAndroid Build Coastguard Worker       (addr_version == AF_INET6)? write_lease6file() : write_leasefile();
1674*cf5a6c84SAndroid Build Coastguard Worker       if (get_interface(gconfig.interface, &gconfig.ifindex,
1675*cf5a6c84SAndroid Build Coastguard Worker             (addr_version==AF_INET6)? (void*)gconfig.server_nip6 :
1676*cf5a6c84SAndroid Build Coastguard Worker             (void*)&gconfig.server_nip, gconfig.server_mac)<0)
1677*cf5a6c84SAndroid Build Coastguard Worker         perror_exit("Failed to get interface %s", gconfig.interface);
1678*cf5a6c84SAndroid Build Coastguard Worker       if(addr_version != AF_INET6) {
1679*cf5a6c84SAndroid Build Coastguard Worker         gconfig.server_nip = htonl(gconfig.server_nip);
1680*cf5a6c84SAndroid Build Coastguard Worker       }
1681*cf5a6c84SAndroid Build Coastguard Worker       continue;
1682*cf5a6c84SAndroid Build Coastguard Worker     }
1683*cf5a6c84SAndroid Build Coastguard Worker     if (FD_ISSET(sigfd.rd, &rfds)) { // Some Activity on RDFDs : is signal
1684*cf5a6c84SAndroid Build Coastguard Worker       unsigned char sig;
1685*cf5a6c84SAndroid Build Coastguard Worker       if (read(sigfd.rd, &sig, 1) != 1) {
1686*cf5a6c84SAndroid Build Coastguard Worker         dbg("signal read failed.\n");
1687*cf5a6c84SAndroid Build Coastguard Worker         continue;
1688*cf5a6c84SAndroid Build Coastguard Worker       }
1689*cf5a6c84SAndroid Build Coastguard Worker       switch (sig) {
1690*cf5a6c84SAndroid Build Coastguard Worker         case SIGUSR1:
1691*cf5a6c84SAndroid Build Coastguard Worker           infomsg(infomode, "Received SIGUSR1");
1692*cf5a6c84SAndroid Build Coastguard Worker           (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
1693*cf5a6c84SAndroid Build Coastguard Worker           continue;
1694*cf5a6c84SAndroid Build Coastguard Worker         case SIGTERM:
1695*cf5a6c84SAndroid Build Coastguard Worker           infomsg(infomode, "received sigterm");
1696*cf5a6c84SAndroid Build Coastguard Worker           (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
1697*cf5a6c84SAndroid Build Coastguard Worker           unlink(gconfig.pidfile);
1698*cf5a6c84SAndroid Build Coastguard Worker           exit(0);
1699*cf5a6c84SAndroid Build Coastguard Worker           break;
1700*cf5a6c84SAndroid Build Coastguard Worker         default: break;
1701*cf5a6c84SAndroid Build Coastguard Worker       }
1702*cf5a6c84SAndroid Build Coastguard Worker     }
1703*cf5a6c84SAndroid Build Coastguard Worker     if (FD_ISSET(gstate.listensock, &rfds)) { // Some Activity on RDFDs : is socket
1704*cf5a6c84SAndroid Build Coastguard Worker       dbg("select listen sock read\n");
1705*cf5a6c84SAndroid Build Coastguard Worker       if(addr_version==AF_INET6) {
1706*cf5a6c84SAndroid Build Coastguard Worker         void *client_duid, *server_duid, *client_ia_na, *server_ia_na,
1707*cf5a6c84SAndroid Build Coastguard Worker              *client_ia_pd;
1708*cf5a6c84SAndroid Build Coastguard Worker         uint8_t client_lla[6] = {0,};
1709*cf5a6c84SAndroid Build Coastguard Worker         uint16_t client_duid_len = 0, server_duid_len = 0, server_ia_na_len = 0,
1710*cf5a6c84SAndroid Build Coastguard Worker                  client_ia_na_len = 0, client_ia_pd_len = 0;
1711*cf5a6c84SAndroid Build Coastguard Worker 
1712*cf5a6c84SAndroid Build Coastguard Worker         if(read_packet6() < 0) {
1713*cf5a6c84SAndroid Build Coastguard Worker           open_listensock6();
1714*cf5a6c84SAndroid Build Coastguard Worker           continue;
1715*cf5a6c84SAndroid Build Coastguard Worker         }
1716*cf5a6c84SAndroid Build Coastguard Worker         waited += time(NULL) - timestmp;
1717*cf5a6c84SAndroid Build Coastguard Worker 
1718*cf5a6c84SAndroid Build Coastguard Worker         memcpy(&gstate.rqcode, &gstate.rcvd.rcvd_pkt6.msgtype, sizeof(uint8_t));
1719*cf5a6c84SAndroid Build Coastguard Worker         memcpy(&transactionid, &gstate.rcvd.rcvd_pkt6.transaction_id,
1720*cf5a6c84SAndroid Build Coastguard Worker             sizeof(transactionid));
1721*cf5a6c84SAndroid Build Coastguard Worker 
1722*cf5a6c84SAndroid Build Coastguard Worker         if (!gstate.rqcode || gstate.rqcode < DHCP6SOLICIT ||
1723*cf5a6c84SAndroid Build Coastguard Worker             gstate.rqcode > DHCP6RELAYREPLY) {
1724*cf5a6c84SAndroid Build Coastguard Worker           dbg("no or bad message type option, ignoring packet.\n");
1725*cf5a6c84SAndroid Build Coastguard Worker           continue;
1726*cf5a6c84SAndroid Build Coastguard Worker         }
1727*cf5a6c84SAndroid Build Coastguard Worker         if (memcmp(gstate.rcvd.rcvd_pkt6.transaction_id, transactionid, 3)) {
1728*cf5a6c84SAndroid Build Coastguard Worker           dbg("no or bad transaction id, ignoring packet.\n");
1729*cf5a6c84SAndroid Build Coastguard Worker           continue;
1730*cf5a6c84SAndroid Build Coastguard Worker         }
1731*cf5a6c84SAndroid Build Coastguard Worker 
1732*cf5a6c84SAndroid Build Coastguard Worker         waited += time(NULL) - timestmp;
1733*cf5a6c84SAndroid Build Coastguard Worker         switch (gstate.rqcode) {
1734*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6SOLICIT:
1735*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type: DHCP6SOLICIT\n");
1736*cf5a6c84SAndroid Build Coastguard Worker             optptr = prepare_send_pkt6(DHCP6ADVERTISE);
1737*cf5a6c84SAndroid Build Coastguard Worker             optlen = 0;
1738*cf5a6c84SAndroid Build Coastguard Worker 
1739*cf5a6c84SAndroid Build Coastguard Worker             //TODO policy check
1740*cf5a6c84SAndroid Build Coastguard Worker             //TODO Receive: ORO check (e.g. DNS)
1741*cf5a6c84SAndroid Build Coastguard Worker 
1742*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Client Identifier (DUID)
1743*cf5a6c84SAndroid Build Coastguard Worker             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1744*cf5a6c84SAndroid Build Coastguard Worker                 DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
1745*cf5a6c84SAndroid Build Coastguard Worker 
1746*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Identity Association for Non-temporary Address
1747*cf5a6c84SAndroid Build Coastguard Worker             if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1748*cf5a6c84SAndroid Build Coastguard Worker                   DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
1749*cf5a6c84SAndroid Build Coastguard Worker               uint16_t ia_addr_len = sizeof(struct optval_ia_addr);
1750*cf5a6c84SAndroid Build Coastguard Worker               void *ia_addr, *status_code;
1751*cf5a6c84SAndroid Build Coastguard Worker               char *status_code_msg;
1752*cf5a6c84SAndroid Build Coastguard Worker               uint16_t status_code_len = 0;
1753*cf5a6c84SAndroid Build Coastguard Worker               server_ia_na_len = sizeof(struct optval_ia_na);
1754*cf5a6c84SAndroid Build Coastguard Worker 
1755*cf5a6c84SAndroid Build Coastguard Worker               //IA Address
1756*cf5a6c84SAndroid Build Coastguard Worker               ia_addr = xzalloc(ia_addr_len);
1757*cf5a6c84SAndroid Build Coastguard Worker               struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
1758*cf5a6c84SAndroid Build Coastguard Worker               (*ia_addr_p).pref_lifetime = gconfig.pref_lifetime;
1759*cf5a6c84SAndroid Build Coastguard Worker               (*ia_addr_p).valid_lifetime = gconfig.valid_lifetime;
1760*cf5a6c84SAndroid Build Coastguard Worker               memcpy(&(*ia_addr_p).ipv6_addr,
1761*cf5a6c84SAndroid Build Coastguard Worker                   getip6_from_pool(client_duid, client_duid_len,
1762*cf5a6c84SAndroid Build Coastguard Worker                     DHCP6_OPT_IA_NA, (*(struct optval_ia_na*) client_ia_na).iaid,
1763*cf5a6c84SAndroid Build Coastguard Worker                     &(*ia_addr_p).pref_lifetime), sizeof(uint32_t)*4);
1764*cf5a6c84SAndroid Build Coastguard Worker               server_ia_na_len += (ia_addr_len+4);
1765*cf5a6c84SAndroid Build Coastguard Worker 
1766*cf5a6c84SAndroid Build Coastguard Worker               //Status Code
1767*cf5a6c84SAndroid Build Coastguard Worker               if(memcmp((*ia_addr_p).ipv6_addr, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
1768*cf5a6c84SAndroid Build Coastguard Worker                 status_code_msg = xstrdup("Assigned an address.");
1769*cf5a6c84SAndroid Build Coastguard Worker                 status_code_len = strlen(status_code_msg)+1;
1770*cf5a6c84SAndroid Build Coastguard Worker                 status_code = xzalloc(status_code_len);
1771*cf5a6c84SAndroid Build Coastguard Worker                 struct optval_status_code *status_code_p =
1772*cf5a6c84SAndroid Build Coastguard Worker                   (struct optval_status_code*)status_code;
1773*cf5a6c84SAndroid Build Coastguard Worker                 (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
1774*cf5a6c84SAndroid Build Coastguard Worker                 memcpy((*status_code_p).status_msg, status_code_msg,
1775*cf5a6c84SAndroid Build Coastguard Worker                     status_code_len);
1776*cf5a6c84SAndroid Build Coastguard Worker                 server_ia_na_len += (status_code_len+4);
1777*cf5a6c84SAndroid Build Coastguard Worker                 free(status_code_msg);
1778*cf5a6c84SAndroid Build Coastguard Worker               } else {
1779*cf5a6c84SAndroid Build Coastguard Worker                 status_code_msg = xstrdup("There's no available address.");
1780*cf5a6c84SAndroid Build Coastguard Worker                 status_code_len = strlen(status_code_msg)+1;
1781*cf5a6c84SAndroid Build Coastguard Worker                 status_code = xzalloc(status_code_len);
1782*cf5a6c84SAndroid Build Coastguard Worker                 struct optval_status_code *status_code_p =
1783*cf5a6c84SAndroid Build Coastguard Worker                   (struct optval_status_code*)status_code;
1784*cf5a6c84SAndroid Build Coastguard Worker                 (*status_code_p).status_code = htons(DHCP6_STATUS_NOADDRSAVAIL);
1785*cf5a6c84SAndroid Build Coastguard Worker                 memcpy((*status_code_p).status_msg, status_code_msg,
1786*cf5a6c84SAndroid Build Coastguard Worker                     status_code_len);
1787*cf5a6c84SAndroid Build Coastguard Worker                 server_ia_na_len += (status_code_len+4);
1788*cf5a6c84SAndroid Build Coastguard Worker                 server_ia_na_len -= (ia_addr_len+4);
1789*cf5a6c84SAndroid Build Coastguard Worker                 ia_addr_len = 0;
1790*cf5a6c84SAndroid Build Coastguard Worker                 free(ia_addr);
1791*cf5a6c84SAndroid Build Coastguard Worker                 free(status_code_msg);
1792*cf5a6c84SAndroid Build Coastguard Worker                 //TODO send failed status code
1793*cf5a6c84SAndroid Build Coastguard Worker                 break;
1794*cf5a6c84SAndroid Build Coastguard Worker               }
1795*cf5a6c84SAndroid Build Coastguard Worker 
1796*cf5a6c84SAndroid Build Coastguard Worker               //combine options
1797*cf5a6c84SAndroid Build Coastguard Worker               server_ia_na = xzalloc(server_ia_na_len);
1798*cf5a6c84SAndroid Build Coastguard Worker               struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
1799*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
1800*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).t1 = gconfig.t1;
1801*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).t2 = gconfig.t2;
1802*cf5a6c84SAndroid Build Coastguard Worker 
1803*cf5a6c84SAndroid Build Coastguard Worker               uint8_t* ia_na_optptr = (*ia_na_p).optval;
1804*cf5a6c84SAndroid Build Coastguard Worker               if(ia_addr_len) {
1805*cf5a6c84SAndroid Build Coastguard Worker                 set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR, ia_addr, ia_addr_len);
1806*cf5a6c84SAndroid Build Coastguard Worker                 ia_na_optptr += (ia_addr_len + 4);
1807*cf5a6c84SAndroid Build Coastguard Worker                 free(ia_addr);
1808*cf5a6c84SAndroid Build Coastguard Worker               }
1809*cf5a6c84SAndroid Build Coastguard Worker               if(status_code_len) {
1810*cf5a6c84SAndroid Build Coastguard Worker                 set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE, status_code,
1811*cf5a6c84SAndroid Build Coastguard Worker                     status_code_len);
1812*cf5a6c84SAndroid Build Coastguard Worker                 ia_na_optptr += (status_code_len);
1813*cf5a6c84SAndroid Build Coastguard Worker                 free(status_code);
1814*cf5a6c84SAndroid Build Coastguard Worker               }
1815*cf5a6c84SAndroid Build Coastguard Worker 
1816*cf5a6c84SAndroid Build Coastguard Worker               //Response: Identity Association for Non-temporary Address
1817*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval6(optptr, DHCP6_OPT_IA_NA, server_ia_na,
1818*cf5a6c84SAndroid Build Coastguard Worker                   server_ia_na_len);
1819*cf5a6c84SAndroid Build Coastguard Worker               optlen += (server_ia_na_len + 4);
1820*cf5a6c84SAndroid Build Coastguard Worker               free(client_ia_na);free(server_ia_na);
1821*cf5a6c84SAndroid Build Coastguard Worker             }
1822*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Identity Association for Prefix Delegation
1823*cf5a6c84SAndroid Build Coastguard Worker             else if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1824*cf5a6c84SAndroid Build Coastguard Worker                   DHCP6_OPT_IA_PD, &client_ia_pd_len, &client_ia_pd)) {
1825*cf5a6c84SAndroid Build Coastguard Worker 
1826*cf5a6c84SAndroid Build Coastguard Worker               //TODO
1827*cf5a6c84SAndroid Build Coastguard Worker               //Response: Identity Association for Prefix Delegation
1828*cf5a6c84SAndroid Build Coastguard Worker             }
1829*cf5a6c84SAndroid Build Coastguard Worker 
1830*cf5a6c84SAndroid Build Coastguard Worker             //DUID type: link-layer address plus time
1831*cf5a6c84SAndroid Build Coastguard Worker             if(ntohs((*(struct optval_duid_llt*)client_duid).type) ==
1832*cf5a6c84SAndroid Build Coastguard Worker                 DHCP6_DUID_LLT) {
1833*cf5a6c84SAndroid Build Coastguard Worker               server_duid_len = 8+sizeof(gconfig.server_mac);
1834*cf5a6c84SAndroid Build Coastguard Worker               server_duid = xzalloc(server_duid_len);
1835*cf5a6c84SAndroid Build Coastguard Worker               struct optval_duid_llt *server_duid_p =
1836*cf5a6c84SAndroid Build Coastguard Worker                 (struct optval_duid_llt*)server_duid;
1837*cf5a6c84SAndroid Build Coastguard Worker               (*server_duid_p).type = htons(1);
1838*cf5a6c84SAndroid Build Coastguard Worker               (*server_duid_p).hwtype = htons(1);
1839*cf5a6c84SAndroid Build Coastguard Worker               (*server_duid_p).time = htonl((uint32_t)
1840*cf5a6c84SAndroid Build Coastguard Worker                   (time(NULL) - 946684800) & 0xffffffff);
1841*cf5a6c84SAndroid Build Coastguard Worker               memcpy((*server_duid_p).lladdr, gconfig.server_mac,
1842*cf5a6c84SAndroid Build Coastguard Worker                   sizeof(gconfig.server_mac));
1843*cf5a6c84SAndroid Build Coastguard Worker               memcpy(&client_lla, (*(struct optval_duid_llt*)client_duid).lladdr,
1844*cf5a6c84SAndroid Build Coastguard Worker                   sizeof(client_lla));
1845*cf5a6c84SAndroid Build Coastguard Worker 
1846*cf5a6c84SAndroid Build Coastguard Worker               //Response: Server Identifier (DUID)
1847*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval6(optptr, DHCP6_OPT_SERVERID, server_duid,
1848*cf5a6c84SAndroid Build Coastguard Worker                   server_duid_len);
1849*cf5a6c84SAndroid Build Coastguard Worker               optlen += (server_duid_len + 4);
1850*cf5a6c84SAndroid Build Coastguard Worker               //Response: Client Identifier
1851*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
1852*cf5a6c84SAndroid Build Coastguard Worker                   client_duid_len);
1853*cf5a6c84SAndroid Build Coastguard Worker               optlen += (client_duid_len + 4);
1854*cf5a6c84SAndroid Build Coastguard Worker               free(client_duid);free(server_duid);
1855*cf5a6c84SAndroid Build Coastguard Worker             }
1856*cf5a6c84SAndroid Build Coastguard Worker 
1857*cf5a6c84SAndroid Build Coastguard Worker             send_packet6(0, client_lla, optlen);
1858*cf5a6c84SAndroid Build Coastguard Worker             write_lease6file();
1859*cf5a6c84SAndroid Build Coastguard Worker             break;
1860*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6REQUEST:
1861*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type: DHCP6REQUEST\n");
1862*cf5a6c84SAndroid Build Coastguard Worker             optptr = prepare_send_pkt6(DHCP6REPLY);
1863*cf5a6c84SAndroid Build Coastguard Worker             optlen = 0;
1864*cf5a6c84SAndroid Build Coastguard Worker 
1865*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Client Identifier (DUID)
1866*cf5a6c84SAndroid Build Coastguard Worker             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1867*cf5a6c84SAndroid Build Coastguard Worker                 DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
1868*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
1869*cf5a6c84SAndroid Build Coastguard Worker                 client_duid_len);
1870*cf5a6c84SAndroid Build Coastguard Worker             optlen += (client_duid_len + 4);
1871*cf5a6c84SAndroid Build Coastguard Worker             memcpy(client_lla, (*(struct optval_duid_llt*)client_duid).lladdr,
1872*cf5a6c84SAndroid Build Coastguard Worker                 sizeof(client_lla));
1873*cf5a6c84SAndroid Build Coastguard Worker 
1874*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Identity Association for Non-temporary Address
1875*cf5a6c84SAndroid Build Coastguard Worker             if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1876*cf5a6c84SAndroid Build Coastguard Worker                   DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
1877*cf5a6c84SAndroid Build Coastguard Worker               uint16_t ia_addr_len = 0, status_code_len = 0;
1878*cf5a6c84SAndroid Build Coastguard Worker               void *ia_addr, *status_code;
1879*cf5a6c84SAndroid Build Coastguard Worker               uint16_t server_ia_na_len = sizeof(struct optval_ia_na);
1880*cf5a6c84SAndroid Build Coastguard Worker               char *status_code_msg;
1881*cf5a6c84SAndroid Build Coastguard Worker 
1882*cf5a6c84SAndroid Build Coastguard Worker               //Check IA Address
1883*cf5a6c84SAndroid Build Coastguard Worker               get_optval6((uint8_t*)(*(struct optval_ia_na*)client_ia_na).optval,
1884*cf5a6c84SAndroid Build Coastguard Worker                   DHCP6_OPT_IA_ADDR, &ia_addr_len, &ia_addr);
1885*cf5a6c84SAndroid Build Coastguard Worker               struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
1886*cf5a6c84SAndroid Build Coastguard Worker               if(verifyip6_in_lease((*ia_addr_p).ipv6_addr, client_duid,
1887*cf5a6c84SAndroid Build Coastguard Worker                     DHCP6_OPT_IA_NA, (*(struct optval_ia_na*)client_ia_na).iaid)
1888*cf5a6c84SAndroid Build Coastguard Worker                   == -1) {
1889*cf5a6c84SAndroid Build Coastguard Worker                 server_ia_na_len += (ia_addr_len + 4);
1890*cf5a6c84SAndroid Build Coastguard Worker                 //Add Status Code
1891*cf5a6c84SAndroid Build Coastguard Worker                 status_code_msg = xstrdup("Assigned an address.");
1892*cf5a6c84SAndroid Build Coastguard Worker                 status_code_len = strlen(status_code_msg) + 1;
1893*cf5a6c84SAndroid Build Coastguard Worker                 status_code = xzalloc(status_code_len);
1894*cf5a6c84SAndroid Build Coastguard Worker                 struct optval_status_code *status_code_p =
1895*cf5a6c84SAndroid Build Coastguard Worker                   (struct optval_status_code*)status_code;
1896*cf5a6c84SAndroid Build Coastguard Worker                 (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
1897*cf5a6c84SAndroid Build Coastguard Worker                 memcpy((*status_code_p).status_msg, status_code_msg,
1898*cf5a6c84SAndroid Build Coastguard Worker                     status_code_len);
1899*cf5a6c84SAndroid Build Coastguard Worker                 server_ia_na_len += (status_code_len+4);
1900*cf5a6c84SAndroid Build Coastguard Worker               } else {
1901*cf5a6c84SAndroid Build Coastguard Worker                 //TODO send failed status code
1902*cf5a6c84SAndroid Build Coastguard Worker                 break;
1903*cf5a6c84SAndroid Build Coastguard Worker               }
1904*cf5a6c84SAndroid Build Coastguard Worker 
1905*cf5a6c84SAndroid Build Coastguard Worker               //combine options
1906*cf5a6c84SAndroid Build Coastguard Worker               server_ia_na = xzalloc(server_ia_na_len);
1907*cf5a6c84SAndroid Build Coastguard Worker               struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
1908*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
1909*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).t1 = gconfig.t1;
1910*cf5a6c84SAndroid Build Coastguard Worker               (*ia_na_p).t2 = gconfig.t2;
1911*cf5a6c84SAndroid Build Coastguard Worker 
1912*cf5a6c84SAndroid Build Coastguard Worker               uint8_t* ia_na_optptr = (*ia_na_p).optval;
1913*cf5a6c84SAndroid Build Coastguard Worker               ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR,
1914*cf5a6c84SAndroid Build Coastguard Worker                   ia_addr, ia_addr_len);
1915*cf5a6c84SAndroid Build Coastguard Worker               free(ia_addr);
1916*cf5a6c84SAndroid Build Coastguard Worker 
1917*cf5a6c84SAndroid Build Coastguard Worker               if(status_code_len) {
1918*cf5a6c84SAndroid Build Coastguard Worker                 ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE,
1919*cf5a6c84SAndroid Build Coastguard Worker                     status_code, status_code_len);
1920*cf5a6c84SAndroid Build Coastguard Worker                 free(status_code);
1921*cf5a6c84SAndroid Build Coastguard Worker               }
1922*cf5a6c84SAndroid Build Coastguard Worker 
1923*cf5a6c84SAndroid Build Coastguard Worker               //Response: Identity Association for Non-temporary Address
1924*cf5a6c84SAndroid Build Coastguard Worker               //(Status Code added)
1925*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval6(optptr, DHCP6_OPT_IA_NA,
1926*cf5a6c84SAndroid Build Coastguard Worker                   server_ia_na, server_ia_na_len);
1927*cf5a6c84SAndroid Build Coastguard Worker               optlen += (server_ia_na_len + 4);
1928*cf5a6c84SAndroid Build Coastguard Worker               free(client_ia_na);free(server_ia_na);
1929*cf5a6c84SAndroid Build Coastguard Worker             }
1930*cf5a6c84SAndroid Build Coastguard Worker 
1931*cf5a6c84SAndroid Build Coastguard Worker             //Receive: Server Identifier (DUID)
1932*cf5a6c84SAndroid Build Coastguard Worker             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1933*cf5a6c84SAndroid Build Coastguard Worker                 DHCP6_OPT_SERVERID, &server_duid_len, &server_duid);
1934*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval6(optptr, DHCP6_OPT_SERVERID,
1935*cf5a6c84SAndroid Build Coastguard Worker                 server_duid, server_duid_len);
1936*cf5a6c84SAndroid Build Coastguard Worker             optlen += (server_duid_len + 4);
1937*cf5a6c84SAndroid Build Coastguard Worker 
1938*cf5a6c84SAndroid Build Coastguard Worker             free(client_duid); free(server_duid);
1939*cf5a6c84SAndroid Build Coastguard Worker 
1940*cf5a6c84SAndroid Build Coastguard Worker             send_packet6(0, client_lla, optlen);
1941*cf5a6c84SAndroid Build Coastguard Worker             write_lease6file();
1942*cf5a6c84SAndroid Build Coastguard Worker             break;
1943*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6DECLINE:  //TODO
1944*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6RENEW:    //TODO
1945*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6REBIND:   //TODO
1946*cf5a6c84SAndroid Build Coastguard Worker           case DHCP6RELEASE:
1947*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type: DHCP6RELEASE\n");
1948*cf5a6c84SAndroid Build Coastguard Worker             optptr = prepare_send_pkt6(DHCP6REPLY);
1949*cf5a6c84SAndroid Build Coastguard Worker             break;
1950*cf5a6c84SAndroid Build Coastguard Worker           default:
1951*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type : %u\n", gstate.rqcode);
1952*cf5a6c84SAndroid Build Coastguard Worker             break;
1953*cf5a6c84SAndroid Build Coastguard Worker         }
1954*cf5a6c84SAndroid Build Coastguard Worker 
1955*cf5a6c84SAndroid Build Coastguard Worker       } else {
1956*cf5a6c84SAndroid Build Coastguard Worker         if(read_packet() < 0) {
1957*cf5a6c84SAndroid Build Coastguard Worker           open_listensock();
1958*cf5a6c84SAndroid Build Coastguard Worker           continue;
1959*cf5a6c84SAndroid Build Coastguard Worker         }
1960*cf5a6c84SAndroid Build Coastguard Worker         waited += time(NULL) - timestmp;
1961*cf5a6c84SAndroid Build Coastguard Worker 
1962*cf5a6c84SAndroid Build Coastguard Worker         get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.options,
1963*cf5a6c84SAndroid Build Coastguard Worker             DHCP_OPT_MESSAGE_TYPE, &gstate.rqcode);
1964*cf5a6c84SAndroid Build Coastguard Worker         if (gstate.rqcode == 0 || gstate.rqcode < DHCPDISCOVER
1965*cf5a6c84SAndroid Build Coastguard Worker             || gstate.rqcode > DHCPINFORM) {
1966*cf5a6c84SAndroid Build Coastguard Worker           dbg("no or bad message type option, ignoring packet.\n");
1967*cf5a6c84SAndroid Build Coastguard Worker           continue;
1968*cf5a6c84SAndroid Build Coastguard Worker         }
1969*cf5a6c84SAndroid Build Coastguard Worker         get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
1970*cf5a6c84SAndroid Build Coastguard Worker             DHCP_OPT_SERVER_ID, &serverid);
1971*cf5a6c84SAndroid Build Coastguard Worker         if (serverid && (serverid != gconfig.server_nip)) {
1972*cf5a6c84SAndroid Build Coastguard Worker           dbg("server ID doesn't match, ignoring packet.\n");
1973*cf5a6c84SAndroid Build Coastguard Worker           continue;
1974*cf5a6c84SAndroid Build Coastguard Worker         }
1975*cf5a6c84SAndroid Build Coastguard Worker 
1976*cf5a6c84SAndroid Build Coastguard Worker         waited += time(NULL) - timestmp;
1977*cf5a6c84SAndroid Build Coastguard Worker         switch (gstate.rqcode) {
1978*cf5a6c84SAndroid Build Coastguard Worker           case DHCPDISCOVER:
1979*cf5a6c84SAndroid Build Coastguard Worker             msgtype = DHCPOFFER;
1980*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type : DHCPDISCOVER\n");
1981*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
1982*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_REQUESTED_IP, &requested_nip);
1983*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
1984*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_HOST_NAME, &hstname);
1985*cf5a6c84SAndroid Build Coastguard Worker             reqested_lease = gconfig.offer_time;
1986*cf5a6c84SAndroid Build Coastguard Worker             get_reqparam(&gstate.rqopt);
1987*cf5a6c84SAndroid Build Coastguard Worker             optptr = prepare_send_pkt();
1988*cf5a6c84SAndroid Build Coastguard Worker             gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
1989*cf5a6c84SAndroid Build Coastguard Worker                 gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
1990*cf5a6c84SAndroid Build Coastguard Worker             if(!gstate.send.send_pkt.yiaddr){
1991*cf5a6c84SAndroid Build Coastguard Worker               msgtype = DHCPNAK;
1992*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
1993*cf5a6c84SAndroid Build Coastguard Worker               send_packet(1);
1994*cf5a6c84SAndroid Build Coastguard Worker               break;
1995*cf5a6c84SAndroid Build Coastguard Worker             }
1996*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
1997*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_LEASE_TIME, &reqested_lease);
1998*cf5a6c84SAndroid Build Coastguard Worker             reqested_lease = htonl(get_lease(reqested_lease + time(NULL)));
1999*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2000*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
2001*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
2002*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_reqparam(optptr, gstate.rqopt);
2003*cf5a6c84SAndroid Build Coastguard Worker             send_packet(1);
2004*cf5a6c84SAndroid Build Coastguard Worker             break;
2005*cf5a6c84SAndroid Build Coastguard Worker           case DHCPREQUEST:
2006*cf5a6c84SAndroid Build Coastguard Worker             msgtype = DHCPACK;
2007*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type : DHCPREQUEST\n");
2008*cf5a6c84SAndroid Build Coastguard Worker             optptr = prepare_send_pkt();
2009*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2010*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_REQUESTED_IP, &requested_nip);
2011*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2012*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_LEASE_TIME, &reqested_lease);
2013*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2014*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_HOST_NAME, &hstname);
2015*cf5a6c84SAndroid Build Coastguard Worker             gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
2016*cf5a6c84SAndroid Build Coastguard Worker                 gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
2017*cf5a6c84SAndroid Build Coastguard Worker             if (!serverid) reqested_lease = gconfig.max_lease_sec;
2018*cf5a6c84SAndroid Build Coastguard Worker             if (!gstate.send.send_pkt.yiaddr) {
2019*cf5a6c84SAndroid Build Coastguard Worker               msgtype = DHCPNAK;
2020*cf5a6c84SAndroid Build Coastguard Worker               optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2021*cf5a6c84SAndroid Build Coastguard Worker               send_packet(1);
2022*cf5a6c84SAndroid Build Coastguard Worker               break;
2023*cf5a6c84SAndroid Build Coastguard Worker             }
2024*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2025*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
2026*cf5a6c84SAndroid Build Coastguard Worker             reqested_lease = htonl(reqested_lease);
2027*cf5a6c84SAndroid Build Coastguard Worker             optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
2028*cf5a6c84SAndroid Build Coastguard Worker             send_packet(1);
2029*cf5a6c84SAndroid Build Coastguard Worker             write_leasefile();
2030*cf5a6c84SAndroid Build Coastguard Worker             break;
2031*cf5a6c84SAndroid Build Coastguard Worker           case DHCPDECLINE:// FALL THROUGH
2032*cf5a6c84SAndroid Build Coastguard Worker           case DHCPRELEASE:
2033*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type : DHCPDECLINE or DHCPRELEASE \n");
2034*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2035*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_SERVER_ID, &serverid);
2036*cf5a6c84SAndroid Build Coastguard Worker             if (serverid != gconfig.server_nip) break;
2037*cf5a6c84SAndroid Build Coastguard Worker             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2038*cf5a6c84SAndroid Build Coastguard Worker                 DHCP_OPT_REQUESTED_IP, &requested_nip);
2039*cf5a6c84SAndroid Build Coastguard Worker             delip_from_lease(requested_nip, gstate.rcvd.rcvd_pkt.chaddr,
2040*cf5a6c84SAndroid Build Coastguard Worker                 (gstate.rqcode==DHCPRELEASE)?0:gconfig.decline_time);
2041*cf5a6c84SAndroid Build Coastguard Worker             break;
2042*cf5a6c84SAndroid Build Coastguard Worker           default:
2043*cf5a6c84SAndroid Build Coastguard Worker             dbg("Message Type : %u\n", gstate.rqcode);
2044*cf5a6c84SAndroid Build Coastguard Worker             break;
2045*cf5a6c84SAndroid Build Coastguard Worker         }
2046*cf5a6c84SAndroid Build Coastguard Worker       }
2047*cf5a6c84SAndroid Build Coastguard Worker     }
2048*cf5a6c84SAndroid Build Coastguard Worker   }
2049*cf5a6c84SAndroid Build Coastguard Worker }
2050