]>
Commit | Line | Data |
---|---|---|
78ab9b04 MT |
1 | diff -up dhcp-4.2.0/server/dhcpv6.c.UseMulticast dhcp-4.2.0/server/dhcpv6.c |
2 | --- dhcp-4.2.0/server/dhcpv6.c.UseMulticast 2010-06-01 19:30:00.000000000 +0200 | |
3 | +++ dhcp-4.2.0/server/dhcpv6.c 2010-07-21 16:17:30.000000000 +0200 | |
4 | @@ -346,6 +346,48 @@ generate_new_server_duid(void) { | |
5 | } | |
6 | ||
7 | /* | |
8 | + * Is the D6O_UNICAST option defined in dhcpd.conf ? | |
9 | + */ | |
10 | +static isc_boolean_t unicast_option_defined; | |
11 | + | |
12 | +/* | |
13 | + * Did we already search dhcpd.conf for D6O_UNICAST option ? | |
14 | + * We need to store it here to not parse dhcpd.conf repeatedly. | |
15 | + */ | |
16 | +static isc_boolean_t unicast_option_parsed = ISC_FALSE; | |
17 | + | |
18 | + | |
19 | +/* | |
20 | + * Is the D6O_UNICAST option defined in dhcpd.conf ? | |
21 | + */ | |
22 | +isc_boolean_t | |
23 | +is_unicast_option_defined(void) { | |
24 | + struct option_state *opt_state; | |
25 | + struct option_cache *oc; | |
26 | + | |
27 | + /* | |
28 | + * If we are looking for the unicast option for the first time | |
29 | + */ | |
30 | + if (unicast_option_parsed == ISC_FALSE) { | |
31 | + unicast_option_parsed = ISC_TRUE; | |
32 | + opt_state = NULL; | |
33 | + if (!option_state_allocate(&opt_state, MDL)) { | |
34 | + log_fatal("No memory for option state."); | |
35 | + } | |
36 | + | |
37 | + execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL, | |
38 | + opt_state, &global_scope, root_group, NULL); | |
39 | + | |
40 | + oc = lookup_option(&dhcpv6_universe, opt_state, D6O_UNICAST); | |
41 | + unicast_option_defined = (oc != NULL); | |
42 | + | |
43 | + option_state_dereference(&opt_state, MDL); | |
44 | + } | |
45 | + | |
46 | + return (unicast_option_defined); | |
47 | +} | |
48 | + | |
49 | +/* | |
50 | * Get the client identifier from the packet. | |
51 | */ | |
52 | isc_result_t | |
53 | @@ -1405,6 +1447,56 @@ lease_to_client(struct data_string *repl | |
54 | reply.shared->group); | |
55 | } | |
56 | ||
57 | + /* reject unicast message, unless we set unicast option */ | |
58 | + if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) | |
59 | + /* | |
60 | + * RFC3315 section 18.2.1 (Request): | |
61 | + * | |
62 | + * When the server receives a Request message via unicast from a client | |
63 | + * to which the server has not sent a unicast option, the server | |
64 | + * discards the Request message and responds with a Reply message | |
65 | + * containing a Status Code option with the value UseMulticast, a Server | |
66 | + * Identifier option containing the server's DUID, the Client Identifier | |
67 | + * option from the client message, and no other options. | |
68 | + * | |
69 | + * Section 18.2.3 (Renew): | |
70 | + * | |
71 | + * When the server receives a Renew message via unicast from a client to | |
72 | + * which the server has not sent a unicast option, the server discards | |
73 | + * the Renew message and responds with a Reply message containing a | |
74 | + * Status Code option with the value UseMulticast, a Server Identifier | |
75 | + * option containing the server's DUID, the Client Identifier option | |
76 | + * from the client message, and no other options. | |
77 | + */ | |
78 | + { | |
79 | + /* Set the UseMulticast status code. */ | |
80 | + if (!set_status_code(STATUS_UseMulticast, | |
81 | + "Unicast not allowed by server.", | |
82 | + reply.opt_state)) { | |
83 | + log_error("lease_to_client: Unable to set " | |
84 | + "UseMulticast status code."); | |
85 | + goto exit; | |
86 | + } | |
87 | + | |
88 | + /* Rewind the cursor to the start. */ | |
89 | + reply.cursor = REPLY_OPTIONS_INDEX; | |
90 | + | |
91 | + /* | |
92 | + * Produce an reply that includes only: | |
93 | + * | |
94 | + * Status code. | |
95 | + * Server DUID. | |
96 | + * Client DUID. | |
97 | + */ | |
98 | + reply.cursor += store_options6((char *)reply.buf.data + | |
99 | + reply.cursor, | |
100 | + sizeof(reply.buf) - | |
101 | + reply.cursor, | |
102 | + reply.opt_state, reply.packet, | |
103 | + required_opts_NAA, | |
104 | + NULL); | |
105 | + } else if (no_resources_avail && (reply.ia_count != 0) && | |
106 | + (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT)) | |
107 | /* | |
108 | * RFC3315 section 17.2.2 (Solicit): | |
109 | * | |
110 | @@ -1429,8 +1521,6 @@ lease_to_client(struct data_string *repl | |
111 | * the server. | |
112 | * Sends a Renew/Rebind if the IA is not in the Reply message. | |
113 | */ | |
114 | - if (no_resources_avail && (reply.ia_count != 0) && | |
115 | - (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT)) | |
116 | { | |
117 | /* Set the NoAddrsAvail status code. */ | |
118 | if (!set_status_code(STATUS_NoAddrsAvail, | |
119 | @@ -4128,7 +4218,6 @@ dhcpv6_solicit(struct data_string *reply | |
120 | * Very similar to Solicit handling, except the server DUID is required. | |
121 | */ | |
122 | ||
123 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
124 | static void | |
125 | dhcpv6_request(struct data_string *reply_ret, struct packet *packet) { | |
126 | struct data_string client_id; | |
127 | @@ -4443,7 +4532,6 @@ exit: | |
128 | * except for the error code of when addresses don't match. | |
129 | */ | |
130 | ||
131 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
132 | static void | |
133 | dhcpv6_renew(struct data_string *reply, struct packet *packet) { | |
134 | struct data_string client_id; | |
135 | @@ -4688,18 +4776,60 @@ iterate_over_ia_na(struct data_string *r | |
136 | goto exit; | |
137 | } | |
138 | ||
139 | - snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type); | |
140 | - if (!set_status_code(STATUS_Success, status_msg, opt_state)) { | |
141 | - goto exit; | |
142 | - } | |
143 | + /* reject unicast message, unless we set unicast option */ | |
144 | + if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) { | |
145 | + /* | |
146 | + * RFC3315 section 18.2.6 (Release): | |
147 | + * | |
148 | + * When the server receives a Release message via unicast from a client | |
149 | + * to which the server has not sent a unicast option, the server | |
150 | + * discards the Release message and responds with a Reply message | |
151 | + * containing a Status Code option with value UseMulticast, a Server | |
152 | + * Identifier option containing the server's DUID, the Client Identifier | |
153 | + * option from the client message, and no other options. | |
154 | + * | |
155 | + * Section 18.2.7 (Decline): | |
156 | + * | |
157 | + * When the server receives a Decline message via unicast from a client | |
158 | + * to which the server has not sent a unicast option, the server | |
159 | + * discards the Decline message and responds with a Reply message | |
160 | + * containing a Status Code option with the value UseMulticast, a Server | |
161 | + * Identifier option containing the server's DUID, the Client Identifier | |
162 | + * option from the client message, and no other options. | |
163 | + */ | |
164 | + snprintf(status_msg, sizeof(status_msg), | |
165 | + "%s received unicast.", packet_type); | |
166 | + if (!set_status_code(STATUS_UseMulticast, status_msg, opt_state)) { | |
167 | + goto exit; | |
168 | + } | |
169 | ||
170 | - /* | |
171 | - * Add our options that are not associated with any IA_NA or IA_TA. | |
172 | - */ | |
173 | - reply_ofs += store_options6(reply_data+reply_ofs, | |
174 | - sizeof(reply_data)-reply_ofs, | |
175 | + /* | |
176 | + * Produce an reply that includes only: | |
177 | + * | |
178 | + * Status code. | |
179 | + * Server DUID. | |
180 | + * Client DUID. | |
181 | + */ | |
182 | + reply_ofs += store_options6(reply_data+reply_ofs, | |
183 | + sizeof(reply_data)-reply_ofs, | |
184 | opt_state, packet, | |
185 | - required_opts, NULL); | |
186 | + required_opts_NAA, NULL); | |
187 | + | |
188 | + goto return_reply; | |
189 | + } else { | |
190 | + snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type); | |
191 | + if (!set_status_code(STATUS_Success, status_msg, opt_state)) { | |
192 | + goto exit; | |
193 | + } | |
194 | + | |
195 | + /* | |
196 | + * Add our options that are not associated with any IA_NA or IA_TA. | |
197 | + */ | |
198 | + reply_ofs += store_options6(reply_data+reply_ofs, | |
199 | + sizeof(reply_data)-reply_ofs, | |
200 | + opt_state, packet, | |
201 | + required_opts, NULL); | |
202 | + } | |
203 | ||
204 | /* | |
205 | * Loop through the IA_NA reported by the client, and deal with | |
206 | @@ -4838,6 +4968,7 @@ iterate_over_ia_na(struct data_string *r | |
207 | /* | |
208 | * Return our reply to the caller. | |
209 | */ | |
210 | +return_reply: | |
211 | reply_ret->len = reply_ofs; | |
212 | reply_ret->buffer = NULL; | |
213 | if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) { | |
214 | @@ -4883,7 +5014,6 @@ exit: | |
215 | * we still need to be aware of this possibility. | |
216 | */ | |
217 | ||
218 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
219 | /* TODO: IA_TA */ | |
220 | static void | |
221 | dhcpv6_decline(struct data_string *reply, struct packet *packet) { | |
222 | @@ -5355,7 +5485,6 @@ exit: | |
223 | * Release means a client is done with the leases. | |
224 | */ | |
225 | ||
226 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
227 | static void | |
228 | dhcpv6_release(struct data_string *reply, struct packet *packet) { | |
229 | struct data_string client_id; |