summaryrefslogtreecommitdiffhomepage
path: root/src/dhcpv6.h
blob: 08dac6c7282558b080124b2b923f28677e687f24 (plain)
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
/**
 *   Copyright (C) 2012 Steven Barth <steven@midlink.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2
 *   as published by the Free Software Foundation.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License version 2 for more details.
 *
 */
#pragma once

#include <libubox/ustream.h>
#include "odhcpd.h"

#define ALL_DHCPV6_RELAYS {{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}}}

#define ALL_DHCPV6_SERVERS {{{0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}}}

#define DHCPV6_CLIENT_PORT 546
#define DHCPV6_SERVER_PORT 547

#define DHCPV6_MSG_SOLICIT 1
#define DHCPV6_MSG_ADVERTISE 2
#define DHCPV6_MSG_REQUEST 3
#define DHCPV6_MSG_CONFIRM 4
#define DHCPV6_MSG_RENEW 5
#define DHCPV6_MSG_REBIND 6
#define DHCPV6_MSG_REPLY 7
#define DHCPV6_MSG_RELEASE 8
#define DHCPV6_MSG_DECLINE 9
#define DHCPV6_MSG_RECONFIGURE 10
#define DHCPV6_MSG_INFORMATION_REQUEST 11
#define DHCPV6_MSG_RELAY_FORW 12
#define DHCPV6_MSG_RELAY_REPL 13

#define DHCPV6_OPT_CLIENTID 1
#define DHCPV6_OPT_SERVERID 2
#define DHCPV6_OPT_IA_NA 3
#define DHCPV6_OPT_IA_ADDR 5
#define DHCPV6_OPT_ORO 6
#define DHCPV6_OPT_STATUS 13
#define DHCPV6_OPT_RELAY_MSG 9
#define DHCPV6_OPT_AUTH 11
#define DHCPV6_OPT_USER_CLASS 15
#define DHCPV6_OPT_INTERFACE_ID 18
#define DHCPV6_OPT_RECONF_MSG 19
#define DHCPV6_OPT_RECONF_ACCEPT 20
#define DHCPV6_OPT_DNS_SERVERS 23
#define DHCPV6_OPT_DNS_DOMAIN 24
#define DHCPV6_OPT_IA_PD 25
#define DHCPV6_OPT_IA_PREFIX 26
#define DHCPV6_OPT_INFO_REFRESH 32
#define DHCPV6_OPT_FQDN 39
#define DHCPV6_OPT_SOL_MAX_RT 82
#define DHCPV6_OPT_INF_MAX_RT 83

#define DHCPV6_DUID_VENDOR 2

#define DHCPV6_STATUS_OK 0
#define DHCPV6_STATUS_NOADDRSAVAIL 2
#define DHCPV6_STATUS_NOBINDING 3
#define DHCPV6_STATUS_NOTONLINK 4
#define DHCPV6_STATUS_USEMULTICAST 5
#define DHCPV6_STATUS_NOPREFIXAVAIL 6

// I just remembered I have an old one lying around...
#define DHCPV6_ENT_NO  30462
#define DHCPV6_ENT_TYPE 1


#define DHCPV6_HOP_COUNT_LIMIT 32

#define DHCPV6_REC_TIMEOUT	2000 /* msec */
#define DHCPV6_REC_MAX_RC	8

struct dhcpv6_client_header {
	uint8_t msg_type;
	uint8_t transaction_id[3];
} __attribute__((packed));

struct dhcpv6_relay_header {
	uint8_t msg_type;
	uint8_t hop_count;
	struct in6_addr link_address;
	struct in6_addr peer_address;
	uint8_t options[];
} __attribute__((packed));

struct dhcpv6_relay_forward_envelope {
	uint8_t msg_type;
	uint8_t hop_count;
	struct in6_addr link_address;
	struct in6_addr peer_address;
	uint16_t interface_id_type;
	uint16_t interface_id_len;
	uint32_t interface_id_data;
	uint16_t relay_message_type;
	uint16_t relay_message_len;
} __attribute__((packed));

struct dhcpv6_auth_reconfigure {
	uint16_t type;
	uint16_t len;
	uint8_t protocol;
	uint8_t algorithm;
	uint8_t rdm;
	uint32_t replay[2];
	uint8_t reconf_type;
	uint8_t key[16];
} _packed;

struct dhcpv6_ia_hdr {
	uint16_t type;
	uint16_t len;
	uint32_t iaid;
	uint32_t t1;
	uint32_t t2;
} _packed;

struct dhcpv6_ia_prefix {
	uint16_t type;
	uint16_t len;
	uint32_t preferred;
	uint32_t valid;
	uint8_t prefix;
	struct in6_addr addr;
} _packed;

struct dhcpv6_ia_addr {
	uint16_t type;
	uint16_t len;
	struct in6_addr addr;
	uint32_t preferred;
	uint32_t valid;
} _packed;

struct dhcpv6_assignment {
	struct list_head head;
	struct interface *iface;

	struct sockaddr_in6 peer;
	time_t valid_until;

	struct uloop_timeout reconf_timer;
	bool accept_reconf;
	int reconf_cnt;
	uint8_t key[16];

	char *hostname;
	uint32_t assigned;
	uint32_t iaid;
	uint8_t mac[6];
	uint8_t length; // length == 128 -> IA_NA, length <= 64 -> IA_PD

	struct odhcpd_ipaddr *managed;
	ssize_t managed_size;
	struct ustream_fd managed_sock;

	uint32_t leasetime;
	unsigned int flags;

	uint8_t clid_len;
	uint8_t clid_data[];
};

struct dhcpv6_cer_id {
	uint16_t type;
	uint16_t len;
	uint16_t reserved;
	uint16_t auth_type;
	uint8_t auth[16];
	struct in6_addr addr;
};

typedef void (*dhcpv6_binding_cb_handler_t)(struct in6_addr *addr, int prefix,
						uint32_t pref, uint32_t valid,
						void *arg);

#define dhcpv6_for_each_option(start, end, otype, olen, odata)\
	for (uint8_t *_o = (uint8_t*)(start); _o + 4 <= (end) &&\
		((otype) = _o[0] << 8 | _o[1]) && ((odata) = (void*)&_o[4]) &&\
		((olen) = _o[2] << 8 | _o[3]) + (odata) <= (end); \
		_o += 4 + (_o[2] << 8 | _o[3]))

int dhcpv6_init_ia(struct interface *iface, int socket);
ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface,
		const struct sockaddr_in6 *addr, const void *data, const uint8_t *end);
int dhcpv6_ia_init(void);
int dhcpv6_setup_ia_interface(struct interface *iface, bool enable);
void dhcpv6_enum_ia_addrs(struct interface *iface, struct dhcpv6_assignment *c, time_t now,
				dhcpv6_binding_cb_handler_t func, void *arg);
void dhcpv6_write_statefile(void);