1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
|
/**
* Copyright (C) 2012-2014 Steven Barth <steven@midlink.org>
* Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License v2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _ODHCP6C_H_
#define _ODHCP6C_H_
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <syslog.h>
#ifndef _o_aligned
#define _o_aligned(n) __attribute__((aligned(n)))
#endif /* _o_aligned */
#ifndef _o_fallthrough
#define _o_fallthrough __attribute__((__fallthrough__))
#endif /* _o_fallthrough */
#ifndef _o_packed
#define _o_packed __attribute__((packed))
#endif /* _o_packed */
#ifndef _o_unused
#define _o_unused __attribute__((unused))
#endif /* _o_unused */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
void __iflog(int lvl, const char *fmt, ...);
#define debug(fmt, ...) __iflog(LOG_DEBUG, fmt __VA_OPT__(, ) __VA_ARGS__)
#define info(fmt, ...) __iflog(LOG_INFO, fmt __VA_OPT__(, ) __VA_ARGS__)
#define notice(fmt, ...) __iflog(LOG_NOTICE, fmt __VA_OPT__(, ) __VA_ARGS__)
#define warn(fmt, ...) __iflog(LOG_WARNING, fmt __VA_OPT__(, ) __VA_ARGS__)
#define error(fmt, ...) __iflog(LOG_ERR, fmt __VA_OPT__(, ) __VA_ARGS__)
#define critical(fmt, ...) __iflog(LOG_CRIT, fmt __VA_OPT__(, ) __VA_ARGS__)
#define alert(fmt, ...) __iflog(LOG_ALERT, fmt __VA_OPT__(, ) __VA_ARGS__)
#define emergency(fmt, ...) __iflog(LOG_EMERG, fmt __VA_OPT__(, ) __VA_ARGS__)
#define ND_OPT_RECURSIVE_DNS 25
#define ND_OPT_DNSSL 31
#define DHCPV6_MAX_DELAY 1
#define DHCPV6_IRT_DEFAULT 86400
#define DHCPV6_IRT_MIN 600
#define DHCPV6_RAND_FACTOR 100
#define DHCPV6_SOL_INIT_RT 1
#define DHCPV6_SOL_MAX_RT 120
#define DHCPV6_REQ_INIT_RT 1
#define DHCPV6_REQ_MAX_RT 30
#define DHCPV6_REQ_MAX_RC 10
#define DHCPV6_REN_INIT_RT 10
#define DHCPV6_REN_MAX_RT 600
#define DHCPV6_REB_INIT_RT 10
#define DHCPV6_REB_MAX_RT 600
#define DHCPV6_INF_INIT_RT 1
#define DHCPV6_INF_MAX_RT 3600
#define DHCPV6_REL_INIT_RT 1
#define DHCPV6_REL_MAX_RC 4
#define DHCPV6_DEC_INIT_RT 1
#define DHCPV6_DEC_MAX_RC 4
#define DHCPV6_IFACEID_EUI64 "eui64"
#define DHCPV6_IFACEID_RANDOM "random"
#define RA_MIN_ADV_INTERVAL 3 /* RFC 4861 paragraph 6.2.1 */
/* RFC8910 §2 */
static const uint8_t URN_IETF_CAPT_PORT_UNRESTR[] = "urn:ietf:params:capport:unrestricted";
#define CAPT_PORT_URI_STR "CAPTIVE_PORTAL_URI"
enum dhcvp6_opt {
/* RFC8415(bis) */
DHCPV6_OPT_CLIENTID = 1,
DHCPV6_OPT_SERVERID = 2,
DHCPV6_OPT_IA_NA = 3,
DHCPV6_OPT_IA_TA = 4,
DHCPV6_OPT_IA_ADDR = 5,
DHCPV6_OPT_ORO = 6,
DHCPV6_OPT_PREF = 7,
DHCPV6_OPT_ELAPSED = 8,
DHCPV6_OPT_RELAY_MSG = 9,
DHCPV6_OPT_AUTH = 11,
DHCPV6_OPT_UNICAST = 12,
DHCPV6_OPT_STATUS = 13,
DHCPV6_OPT_RAPID_COMMIT = 14,
DHCPV6_OPT_USER_CLASS = 15,
DHCPV6_OPT_VENDOR_CLASS = 16,
DHCPV6_OPT_INTERFACE_ID = 18,
DHCPV6_OPT_RECONF_MESSAGE = 19,
DHCPV6_OPT_RECONF_ACCEPT = 20,
/* RFC3319 */
DHCPV6_OPT_SIP_SERVER_D = 21,
DHCPV6_OPT_SIP_SERVER_A = 22,
/* RFC3646 */
DHCPV6_OPT_DNS_SERVERS = 23,
DHCPV6_OPT_DNS_DOMAIN = 24,
/* RFC8415(bis) */
DHCPV6_OPT_IA_PD = 25,
DHCPV6_OPT_IA_PREFIX = 26,
/* RFC4075 */
DHCPV6_OPT_SNTP_SERVERS = 31,
/* RFC4242 */
DHCPV6_OPT_INFO_REFRESH = 32,
/* RFC4649 */
DHCPV6_OPT_REMOTE_ID = 37,
/* RFC4580 */
DHCPV6_OPT_SUBSCRIBER_ID = 38,
/* RFC4704 */
DHCPV6_OPT_FQDN = 39,
/* RFC4994 */
DHCPV6_OPT_ERO = 43,
/* RFC5007 */
DHCPV6_OPT_LQ_QUERY = 44,
DHCPV6_OPT_CLIENT_DATA = 45,
DHCPV6_OPT_CLT_TIME = 46,
DHCPV6_OPT_LQ_RELAY_DATA = 47,
DHCPV6_OPT_LQ_CLIENT_LINK = 48,
/* RFC5460 */
DHCPV6_OPT_RELAY_ID = 53,
/* RFC5908 */
DHCPV6_OPT_NTP_SERVER = 56,
/* RFC5970 */
DHCPV6_OPT_CLIENT_ARCH_TYPE = 61,
/* RFC6334 */
DHCPV6_OPT_AFTR_NAME = 64,
/* RFC6422 */
DHCPV6_OPT_RSOO = 66,
/* RFC6603 */
DHCPV6_OPT_PD_EXCLUDE = 67,
/* RFC6607 */
DHCPV6_OPT_VSS = 68,
/* RFC6939 */
DHCPV6_OPT_LINK_LAYER_ADDRESS = 79,
/* RFC6977 */
DHCPV6_OPT_LINK_ADDRESS = 80,
/* RFC7037 */
DHCPV6_OPT_RADIUS = 81,
/* RFC8415(bis) */
DHCPV6_OPT_SOL_MAX_RT = 82,
DHCPV6_OPT_INF_MAX_RT = 83,
/* RFC8415(bis) */
DHCPV6_OPT_DHCPV4_MSG = 87,
/* RFC7598 */
DHCPV6_OPT_S46_RULE = 89,
DHCPV6_OPT_S46_BR = 90, /* & RFC8539 */
DHCPV6_OPT_S46_DMR = 91,
DHCPV6_OPT_S46_V4V6BIND = 92,
DHCPV6_OPT_S46_PORTPARAMS = 93,
DHCPV6_OPT_S46_CONT_MAPE = 94,
DHCPV6_OPT_S46_CONT_MAPT = 95,
DHCPV6_OPT_S46_CONT_LW = 96,
/* RFC7653 */
DHCPV6_OPT_LQ_BASE_TIME = 100,
DHCPV6_OPT_LQ_START_TIME = 101,
DHCPV6_OPT_LQ_END_TIME = 102,
/* RFC8910 */
DHCPV6_OPT_CAPTIVE_PORTAL = 103,
/* RFC7839 */
DHCPV6_OPT_ANI_ATT = 105,
DHCPV6_OPT_ANI_NETWORK_NAME = 106,
DHCPV6_OPT_ANI_AP_NAME = 107,
DHCPV6_OPT_ANI_AP_BSSID = 108,
DHCPV6_OPT_ANI_OPERATOR_ID = 109,
DHCPV6_OPT_ANI_OPERATOR_REALM = 110,
/* RFC8520 */
DHCPV6_OPT_MUD_URL_V6 = 112,
/* RFC8156 */
DHCPV6_OPT_F_BINDING_STATUS = 114,
DHCPV6_OPT_F_CONNECT_FLAGS = 115,
DHCPV6_OPT_F_DNS_REMOVAL_INFO = 116,
DHCPV6_OPT_F_DNS_HOST_NAME = 117,
DHCPV6_OPT_F_DNS_ZONE_NAME = 118,
DHCPV6_OPT_F_DNS_FLAGS = 119,
DHCPV6_OPT_F_EXPIRATION_TIME = 120,
DHCPV6_OPT_F_MAX_UNACKED_BNDUPD = 121,
DHCPV6_OPT_F_MCLT = 122,
DHCPV6_OPT_F_PARTNER_LIFETIME = 123,
DHCPV6_OPT_F_PARTNER_LIFETIME_SENT = 124,
DHCPV6_OPT_F_PARTNER_DOWN_TIME = 125,
DHCPV6_OPT_F_PARTNER_RAW_CLT_TIME = 126,
DHCPV6_OPT_F_PROTOCOL_VERSION = 127,
DHCPV6_OPT_F_KEEPALIVE_TIME = 128,
DHCPV6_OPT_F_RECONFIGURE_DATA = 129,
DHCPV6_OPT_F_RELATIONSHIP_NAME = 130,
DHCPV6_OPT_F_SERVER_FLAGS = 131,
DHCPV6_OPT_F_SERVER_STATE = 132,
DHCPV6_OPT_F_START_TIME_OF_STATE = 133,
DHCPV6_OPT_F_STATE_EXPIRATION_TIME = 134,
/* RFC8357 */
DHCPV6_OPT_RELAY_PORT = 135,
};
enum dhcpv6_opt_npt {
NTP_SRV_ADDR = 1,
NTP_MC_ADDR = 2,
NTP_SRV_FQDN = 3
};
enum dhcpv6_msg {
/* RFC8415(bis) */
DHCPV6_MSG_UNKNOWN = 0,
DHCPV6_MSG_SOLICIT = 1,
DHCPV6_MSG_ADVERT = 2,
DHCPV6_MSG_REQUEST = 3,
DHCPV6_MSG_RENEW = 5,
DHCPV6_MSG_REBIND = 6,
DHCPV6_MSG_REPLY = 7,
DHCPV6_MSG_RELEASE = 8,
DHCPV6_MSG_DECLINE = 9,
DHCPV6_MSG_RECONF = 10,
DHCPV6_MSG_INFO_REQ = 11,
_DHCPV6_MSG_MAX
};
enum dhcpv6_state {
DHCPV6_INIT,
DHCPV6_SOLICIT,
DHCPV6_SOLICIT_PROCESSING,
DHCPV6_ADVERT,
DHCPV6_REQUEST,
DHCPV6_REQUEST_PROCESSING,
DHCPV6_REPLY,
DHCPV6_BOUND,
DHCPV6_BOUND_PROCESSING,
DHCPV6_BOUND_REPLY,
DHCPV6_RECONF,
DHCPV6_RECONF_PROCESSING,
DHCPV6_RECONF_REPLY,
DHCPV6_RENEW,
DHCPV6_RENEW_PROCESSING,
DHCPV6_RENEW_REPLY,
DHCPV6_REBIND,
DHCPV6_REBIND_PROCESSING,
DHCPV6_REBIND_REPLY,
DHCPV6_INFO,
DHCPV6_INFO_PROCESSING,
DHCPV6_INFO_REPLY,
DHCPV6_EXIT,
DHCPV6_RESET
};
enum dhcpv6_status {
/* RFC8415(bis) */
DHCPV6_Success = 0,
DHCPV6_UnspecFail = 1,
DHCPV6_NoAddrsAvail = 2,
DHCPV6_NoBinding = 3,
DHCPV6_NotOnLink = 4,
DHCPV6_UseMulticast = 5,
DHCPV6_NoPrefixAvail = 6,
_DHCPV6_Status_Max
};
enum dhcpv6_config {
DHCPV6_STRICT_OPTIONS = 1,
DHCPV6_CLIENT_FQDN = 2,
DHCPV6_ACCEPT_RECONFIGURE = 4,
DHCPV6_IGNORE_OPT_UNICAST = 8,
};
typedef int(reply_handler)(enum dhcpv6_msg orig, const int rc,
const void *opt, const void *end, const struct sockaddr_in6 *from);
// retransmission strategy
struct dhcpv6_retx {
uint8_t max_delay; // Delay before starting transaction
uint8_t init_timeo;
uint16_t max_timeo;
uint8_t max_rc; // Max Retry Count
char name[8];
reply_handler *handler_reply;
int(*handler_finish)(void);
bool is_retransmit;
uint64_t timeout; // Maximum duration (in seconds) for the entire DHCPv6 transaction. Varies based on the message type
uint8_t rc; // Retry Count
uint64_t start; // Transaction start time (in milliseconds)
uint8_t tr_id[3]; // Transaction ID
int64_t rto; // Retransmission TimeOut
uint64_t round_start; // the (RTT) time when a request was sent (in milliseconds)
uint64_t round_end; // the (RTT) time when a response was expected to arrive (in milliseconds)
int reply_ret; // Reply handler return value
uint64_t delay_msec; // Delay before starting the transaction
};
#define DHCPV6_OPT_HDR_SIZE 4
#define DHCPV6_OPT_HDR_SIZE_U 4U
#define DHCPV6_DUID_MAX_LEN 130 // 2-byte type + 128-byte DUID, RFC8415, §11.1
// DHCPv6 Protocol Headers
struct dhcpv6_header {
uint8_t msg_type;
uint8_t tr_id[3];
} _o_packed;
struct dhcpv6_ia_hdr {
uint16_t type;
uint16_t len;
uint32_t iaid;
uint32_t t1;
uint32_t t2;
} _o_packed;
struct dhcpv6_ia_addr {
uint16_t type;
uint16_t len;
struct in6_addr addr;
uint32_t preferred;
uint32_t valid;
} _o_packed;
struct dhcpv6_ia_prefix {
uint16_t type;
uint16_t len;
uint32_t preferred;
uint32_t valid;
uint8_t prefix;
struct in6_addr addr;
} _o_packed;
struct dhcpv6_duid {
uint16_t type;
uint16_t len;
uint16_t duid_type;
uint8_t data[128];
} _o_packed;
struct dhcpv6_auth {
uint16_t type;
uint16_t len;
uint8_t protocol;
uint8_t algorithm;
uint8_t rdm;
uint64_t replay;
uint8_t data[];
} _o_packed;
struct dhcpv6_auth_reconfigure {
uint8_t reconf_type;
uint8_t key[16];
} _o_packed;
struct dhcpv6_s46_portparams {
uint8_t offset;
uint8_t psid_len;
uint16_t psid;
} _o_packed;
struct dhcpv6_s46_v4v6bind {
struct in_addr ipv4_address;
uint8_t bindprefix6_len;
uint8_t bind_ipv6_prefix[];
} _o_packed;
struct dhcpv6_s46_dmr {
uint8_t dmr_prefix6_len;
uint8_t dmr_ipv6_prefix[];
} _o_packed;
struct dhcpv6_s46_rule {
uint8_t flags;
uint8_t ea_len;
uint8_t prefix4_len;
struct in_addr ipv4_prefix;
uint8_t prefix6_len;
uint8_t ipv6_prefix[];
} _o_packed;
#define dhcpv6_for_each_option(start, end, otype, olen, odata)\
for (uint8_t *_o = (uint8_t*)(start); _o + 4 <= (uint8_t*)(end) &&\
((otype) = _o[0] << 8 | _o[1]) && ((odata) = (void*)&_o[4]) &&\
((olen) = _o[2] << 8 | _o[3]) + (odata) <= (uint8_t*)(end); \
_o += 4 + (_o[2] << 8 | _o[3]))
struct dhcpv6_server_cand {
bool has_noaddravail;
bool wants_reconfigure;
int16_t preference;
uint8_t duid_len;
uint8_t duid[DHCPV6_DUID_MAX_LEN];
struct in6_addr server_addr;
uint32_t sol_max_rt;
uint32_t inf_max_rt;
void *ia_na;
void *ia_pd;
size_t ia_na_len;
size_t ia_pd_len;
};
struct dhcpv6_stats {
uint64_t solicit;
uint64_t advertise;
uint64_t request;
uint64_t confirm;
uint64_t renew;
uint64_t rebind;
uint64_t reply;
uint64_t release;
uint64_t decline;
uint64_t reconfigure;
uint64_t information_request;
uint64_t discarded_packets;
uint64_t transmit_failures;
};
enum odhcp6c_state {
STATE_CLIENT_ID,
STATE_SERVER_ID,
STATE_OUR_FQDN,
STATE_SERVER_CAND,
STATE_SERVER_ADDR,
STATE_ORO,
STATE_DNS,
STATE_SEARCH,
STATE_IA_NA,
STATE_IA_PD,
STATE_IA_PD_INIT,
STATE_CUSTOM_OPTS,
STATE_SNTP_IP,
STATE_NTP_IP,
STATE_NTP_FQDN,
STATE_SIP_IP,
STATE_SIP_FQDN,
STATE_RA_ROUTE,
STATE_RA_PREFIX,
STATE_RA_DNS,
STATE_RA_SEARCH,
STATE_AFTR_NAME,
STATE_OPTS,
STATE_S46_MAPT,
STATE_S46_MAPE,
STATE_S46_LW,
STATE_CAPT_PORT_RA,
STATE_CAPT_PORT_DHCPV6,
STATE_PASSTHRU,
_STATE_MAX
};
struct icmp6_opt {
uint8_t type;
uint8_t len;
uint8_t data[6];
};
enum dhcpv6_mode {
DHCPV6_UNKNOWN = -1,
DHCPV6_STATELESS,
DHCPV6_STATEFUL
};
enum ra_config {
RA_RDNSS_DEFAULT_LIFETIME = 1,
};
enum odhcp6c_ia_mode {
IA_MODE_NONE,
IA_MODE_TRY,
IA_MODE_FORCE,
};
enum odhcp6c_auth_protocol {
AUTH_PROT_NONE = -1,
/* RFC3118 */
AUTH_PROT_TOKEN = 0,
/* RFC8415(bis) */
AUTH_PROT_RKAP = 3,
};
enum odhcp6c_auth_algorithm {
/* RFC3118 */
AUTH_ALG_TOKEN = 0,
/* RFC8415(bis) */
AUTH_ALG_HMACMD5 = 1
};
enum odhcp6c_rkap_type {
/* RFC8415(bis) */
RKAP_TYPE_KEY = 1,
RKAP_TYPE_HMACMD5 = 2,
};
struct odhcp6c_entry {
struct in6_addr router;
uint8_t auxlen;
uint8_t length;
uint8_t ra_flags;
uint8_t exclusion_length;
struct in6_addr target;
int16_t priority;
uint32_t valid;
uint32_t preferred;
uint32_t t1;
uint32_t t2;
uint32_t iaid;
uint8_t auxtarget[];
};
// Include padding after auxtarget to align the next entry
#define odhcp6c_entry_size(entry) \
(sizeof(struct odhcp6c_entry) + (((entry)->auxlen + 3) & ~3))
#define odhcp6c_next_entry(entry) \
((struct odhcp6c_entry *)((uint8_t *)(entry) + odhcp6c_entry_size(entry)))
struct odhcp6c_request_prefix {
uint32_t iaid;
uint8_t length;
struct in6_addr addr;
};
enum odhcp6c_opt_flags {
OPT_U8 = 0,
OPT_IP6,
OPT_STR,
OPT_DNS_STR,
OPT_USER_CLASS,
OPT_MASK_SIZE = 0x0F,
OPT_ARRAY = 0x10,
OPT_INTERNAL = 0x20,
OPT_NO_PASSTHRU = 0x40,
OPT_ORO = 0x80,
OPT_ORO_STATEFUL = 0x100,
OPT_ORO_STATELESS = 0x200,
OPT_ORO_SOLICIT = 0x400
};
struct odhcp6c_opt {
uint16_t code;
uint16_t flags;
const char *str;
};
struct odhcp6c_opt_cfg {
int strict_rfc7550;
};
uint32_t hash_ifname(const char *s);
int init_dhcpv6(const char *ifname);
int dhcpv6_get_ia_mode(void);
int dhcpv6_promote_server_cand(void);
int dhcpv6_send_request(enum dhcpv6_msg type);
int dhcpv6_receive_response(enum dhcpv6_msg type);
enum dhcpv6_state dhcpv6_get_state(void);
void dhcpv6_set_state(enum dhcpv6_state state);
int dhcpv6_get_socket(void);
struct dhcpv6_stats dhcpv6_get_stats(void);
void dhcpv6_reset_stats(void);
int dhcpv6_state_processing(enum dhcpv6_msg type);
int dhcpv6_get_state_timeout(void);
void dhcpv6_set_state_timeout(int timeout);
void dhcpv6_reset_state_timeout(void);
const char *dhcpv6_state_to_str(enum dhcpv6_state state);
int init_rtnetlink(void);
int set_rtnetlink_addr(int ifindex, const struct in6_addr *addr,
uint32_t pref, uint32_t valid);
int ra_get_hoplimit(void);
int ra_get_mtu(void);
int ra_get_reachable(void);
int ra_get_retransmit(void);
void notify_state_change(const char *status, int delay, bool resume);
int script_init(const char *path, const char *ifname);
ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src);
void script_hexlify(char *dst, const uint8_t *src, size_t len);
void script_call(const char *status, int delay, bool resume);
bool odhcp6c_signal_process(void);
uint64_t odhcp6c_get_milli_time(void);
int odhcp6c_random(void *buf, size_t len);
bool odhcp6c_is_bound(void);
bool odhcp6c_addr_in_scope(const struct in6_addr *addr);
// State manipulation
void odhcp6c_clear_state(enum odhcp6c_state state);
int odhcp6c_add_state(enum odhcp6c_state state, const void *data, size_t len);
void odhcp6c_append_state(enum odhcp6c_state state, const void *data, size_t len);
int odhcp6c_insert_state(enum odhcp6c_state state, size_t offset, const void *data, size_t len);
size_t odhcp6c_remove_state(enum odhcp6c_state state, size_t offset, size_t len);
void* odhcp6c_move_state(enum odhcp6c_state state, size_t *len);
void* odhcp6c_get_state(enum odhcp6c_state state, size_t *len);
// Entry manipulation
bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new,
unsigned int holdoff_interval);
void odhcp6c_expire(bool expire_ia_pd);
uint32_t odhcp6c_elapsed(void);
struct odhcp6c_opt *odhcp6c_find_opt(const uint16_t code);
struct odhcp6c_opt *odhcp6c_find_opt_by_name(const char *name);
static inline bool odhcp6c_is_multicast_ether_addr(const uint8_t *addr)
{
return addr[0] & 0x01;
}
static inline bool odhcp6c_is_zero_ether_addr(const uint8_t *addr)
{
return (addr[0] | addr[1] | addr[2] |
addr[3] | addr[4] | addr[5]) == 0;
}
static inline bool odhcp6c_is_valid_ether_addr(const uint8_t *addr)
{
return !odhcp6c_is_multicast_ether_addr(addr) &&
!odhcp6c_is_zero_ether_addr(addr);
}
#endif /* _ODHCP6C_H_ */
|