]>
Commit | Line | Data |
---|---|---|
c1e9ba67 MF |
1 | diff -up dhcp-4.3.0a1/client/dhc6.c.sendDecline dhcp-4.3.0a1/client/dhc6.c |
2 | --- dhcp-4.3.0a1/client/dhc6.c.sendDecline 2013-12-11 01:25:12.000000000 +0100 | |
3 | +++ dhcp-4.3.0a1/client/dhc6.c 2013-12-19 15:56:18.297660118 +0100 | |
4 | @@ -96,6 +96,8 @@ void do_select6(void *input); | |
78ab9b04 MT |
5 | void do_refresh6(void *input); |
6 | static void do_release6(void *input); | |
7 | static void start_bound(struct client_state *client); | |
8 | +static void start_decline6(struct client_state *client); | |
9 | +static void do_decline6(void *input); | |
10 | static void start_informed(struct client_state *client); | |
11 | void informed_handler(struct packet *packet, struct client_state *client); | |
12 | void bound_handler(struct packet *packet, struct client_state *client); | |
c1e9ba67 | 13 | @@ -2017,6 +2019,7 @@ start_release6(struct client_state *clie |
78ab9b04 MT |
14 | cancel_timeout(do_select6, client); |
15 | cancel_timeout(do_refresh6, client); | |
16 | cancel_timeout(do_release6, client); | |
17 | + cancel_timeout(do_decline6, client); | |
18 | client->state = S_STOPPED; | |
19 | ||
20 | /* | |
c1e9ba67 | 21 | @@ -2650,6 +2653,7 @@ dhc6_check_reply(struct client_state *cl |
78ab9b04 MT |
22 | break; |
23 | ||
24 | case S_STOPPED: | |
25 | + case S_DECLINED: | |
26 | action = dhc6_stop_action; | |
27 | break; | |
28 | ||
c1e9ba67 | 29 | @@ -2751,6 +2755,7 @@ dhc6_check_reply(struct client_state *cl |
78ab9b04 MT |
30 | break; |
31 | ||
32 | case S_STOPPED: | |
33 | + case S_DECLINED: | |
34 | /* Nothing critical to do at this stage. */ | |
35 | break; | |
36 | ||
c1e9ba67 | 37 | @@ -3741,17 +3746,23 @@ reply_handler(struct packet *packet, str |
78ab9b04 MT |
38 | cancel_timeout(do_select6, client); |
39 | cancel_timeout(do_refresh6, client); | |
40 | cancel_timeout(do_release6, client); | |
41 | + cancel_timeout(do_decline6, client); | |
42 | ||
43 | /* If this is in response to a Release/Decline, clean up and return. */ | |
44 | - if (client->state == S_STOPPED) { | |
45 | - if (client->active_lease == NULL) | |
46 | - return; | |
47 | + if ((client->state == S_STOPPED) || | |
48 | + (client->state == S_DECLINED)) { | |
49 | + | |
50 | + if (client->active_lease != NULL) { | |
51 | + dhc6_lease_destroy(&client->active_lease, MDL); | |
52 | + client->active_lease = NULL; | |
53 | + /* We should never wait for nothing!? */ | |
54 | + if (stopping_finished()) | |
55 | + exit(0); | |
56 | + } | |
57 | + | |
58 | + if (client->state == S_DECLINED) | |
59 | + start_init6(client); | |
60 | ||
61 | - dhc6_lease_destroy(&client->active_lease, MDL); | |
62 | - client->active_lease = NULL; | |
63 | - /* We should never wait for nothing!? */ | |
64 | - if (stopping_finished()) | |
65 | - exit(0); | |
66 | return; | |
67 | } | |
68 | ||
c1e9ba67 | 69 | @@ -4279,7 +4290,11 @@ start_bound(struct client_state *client) |
78ab9b04 | 70 | dhc6_marshall_values("new_", client, lease, ia, addr); |
c1e9ba67 | 71 | script_write_requested6(client); |
78ab9b04 MT |
72 | |
73 | - script_go(client); | |
74 | + // when script returns 3, DAD failed | |
75 | + if (script_go(client) == 3) { | |
76 | + start_decline6(client); | |
77 | + return; | |
78 | + } | |
79 | } | |
80 | ||
81 | /* XXX: maybe we should loop on the old values instead? */ | |
c1e9ba67 | 82 | @@ -4327,6 +4342,149 @@ start_bound(struct client_state *client) |
78ab9b04 MT |
83 | dhc6_check_times(client); |
84 | } | |
85 | ||
86 | +/* | |
87 | + * Decline addresses. | |
88 | + */ | |
89 | +void | |
90 | +start_decline6(struct client_state *client) | |
91 | +{ | |
92 | + /* Cancel any pending transmissions */ | |
93 | + cancel_timeout(do_confirm6, client); | |
94 | + cancel_timeout(do_select6, client); | |
95 | + cancel_timeout(do_refresh6, client); | |
96 | + cancel_timeout(do_release6, client); | |
97 | + cancel_timeout(do_decline6, client); | |
98 | + client->state = S_DECLINED; | |
99 | + | |
100 | + if (client->active_lease == NULL) | |
101 | + return; | |
102 | + | |
103 | + /* Set timers per RFC3315 section 18.1.7. */ | |
104 | + client->IRT = DEC_TIMEOUT * 100; | |
105 | + client->MRT = 0; | |
106 | + client->MRC = DEC_MAX_RC; | |
107 | + client->MRD = 0; | |
108 | + | |
109 | + dhc6_retrans_init(client); | |
110 | + client->v6_handler = reply_handler; | |
111 | + | |
112 | + client->refresh_type = DHCPV6_DECLINE; | |
113 | + do_decline6(client); | |
114 | +} | |
115 | + | |
116 | +/* | |
117 | + * do_decline6() creates a Decline packet and transmits it. | |
118 | + */ | |
119 | +static void | |
120 | +do_decline6(void *input) | |
121 | +{ | |
122 | + struct client_state *client; | |
123 | + struct data_string ds; | |
124 | + int send_ret; | |
125 | + struct timeval elapsed, tv; | |
126 | + | |
127 | + client = input; | |
128 | + | |
129 | + if ((client->active_lease == NULL) || !active_prefix(client)) | |
130 | + return; | |
131 | + | |
132 | + if ((client->MRC != 0) && (client->txcount > client->MRC)) { | |
133 | + log_info("Max retransmission count exceeded."); | |
134 | + goto decline_done; | |
135 | + } | |
136 | + | |
137 | + /* | |
138 | + * Start_time starts at the first transmission. | |
139 | + */ | |
140 | + if (client->txcount == 0) { | |
141 | + client->start_time.tv_sec = cur_tv.tv_sec; | |
142 | + client->start_time.tv_usec = cur_tv.tv_usec; | |
143 | + } | |
144 | + | |
145 | + /* elapsed = cur - start */ | |
146 | + elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec; | |
147 | + elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec; | |
148 | + if (elapsed.tv_usec < 0) { | |
149 | + elapsed.tv_sec -= 1; | |
150 | + elapsed.tv_usec += 1000000; | |
151 | + } | |
152 | + | |
153 | + memset(&ds, 0, sizeof(ds)); | |
154 | + if (!buffer_allocate(&ds.buffer, 4, MDL)) { | |
155 | + log_error("Unable to allocate memory for Decline."); | |
156 | + goto decline_done; | |
157 | + } | |
158 | + | |
159 | + ds.data = ds.buffer->data; | |
160 | + ds.len = 4; | |
161 | + ds.buffer->data[0] = DHCPV6_DECLINE; | |
162 | + memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3); | |
163 | + | |
164 | + /* Form an elapsed option. */ | |
165 | + /* Maximum value is 65535 1/100s coded as 0xffff. */ | |
166 | + if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) || | |
167 | + ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) { | |
168 | + client->elapsed = 0xffff; | |
169 | + } else { | |
170 | + client->elapsed = elapsed.tv_sec * 100; | |
171 | + client->elapsed += elapsed.tv_usec / 10000; | |
172 | + } | |
173 | + | |
174 | + client->elapsed = htons(client->elapsed); | |
175 | + | |
176 | + log_debug("XMT: Forming Decline."); | |
177 | + make_client6_options(client, &client->sent_options, | |
178 | + client->active_lease, DHCPV6_DECLINE); | |
179 | + dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL, | |
180 | + client->sent_options, &global_scope, | |
181 | + &dhcpv6_universe); | |
182 | + | |
183 | + /* Append IA's (but don't release temporary addresses). */ | |
184 | + if (wanted_ia_na && | |
185 | + dhc6_add_ia_na(client, &ds, client->active_lease, | |
186 | + DHCPV6_DECLINE) != ISC_R_SUCCESS) { | |
187 | + data_string_forget(&ds, MDL); | |
188 | + goto decline_done; | |
189 | + } | |
190 | + if (wanted_ia_pd && | |
191 | + dhc6_add_ia_pd(client, &ds, client->active_lease, | |
192 | + DHCPV6_DECLINE) != ISC_R_SUCCESS) { | |
193 | + data_string_forget(&ds, MDL); | |
194 | + goto decline_done; | |
195 | + } | |
196 | + | |
197 | + /* Transmit and wait. */ | |
198 | + log_info("XMT: Decline on %s, interval %ld0ms.", | |
199 | + client->name ? client->name : client->interface->name, | |
200 | + (long int)client->RT); | |
201 | + | |
202 | + send_ret = send_packet6(client->interface, ds.data, ds.len, | |
203 | + &DHCPv6DestAddr); | |
204 | + if (send_ret != ds.len) { | |
205 | + log_error("dhc6: sendpacket6() sent %d of %d bytes", | |
206 | + send_ret, ds.len); | |
207 | + } | |
208 | + | |
209 | + data_string_forget(&ds, MDL); | |
210 | + | |
211 | + /* Wait RT */ | |
212 | + tv.tv_sec = cur_tv.tv_sec + client->RT / 100; | |
213 | + tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000; | |
214 | + if (tv.tv_usec >= 1000000) { | |
215 | + tv.tv_sec += 1; | |
216 | + tv.tv_usec -= 1000000; | |
217 | + } | |
218 | + add_timeout(&tv, do_decline6, client, NULL, NULL); | |
219 | + dhc6_retrans_advance(client); | |
220 | + return; | |
221 | + | |
222 | +decline_done: | |
223 | + dhc6_lease_destroy(&client->active_lease, MDL); | |
224 | + client->active_lease = NULL; | |
225 | + start_init6(client); | |
226 | + return; | |
227 | +} | |
228 | + | |
229 | /* While bound, ignore packets. In the future we'll want to answer | |
230 | * Reconfigure-Request messages and the like. | |
231 | */ |