]>
Commit | Line | Data |
---|---|---|
c1e9ba67 MF |
1 | diff -up dhcp-4.3.1b1/server/dhcpv6.c.UseMulticast dhcp-4.3.1b1/server/dhcpv6.c |
2 | --- dhcp-4.3.1b1/server/dhcpv6.c.UseMulticast 2014-07-02 19:58:40.000000000 +0200 | |
3 | +++ dhcp-4.3.1b1/server/dhcpv6.c 2014-07-10 18:20:03.066256219 +0200 | |
4 | @@ -376,6 +376,48 @@ generate_new_server_duid(void) { | |
78ab9b04 MT |
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, | |
c1e9ba67 | 38 | + opt_state, &global_scope, root_group, NULL, NULL); |
78ab9b04 MT |
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 | |
c1e9ba67 MF |
53 | @@ -706,6 +748,12 @@ static const int required_opts[] = { |
54 | D6O_PREFERENCE, | |
55 | 0 | |
56 | }; | |
57 | +static const int required_opts_NAA[] = { | |
58 | + D6O_CLIENTID, | |
59 | + D6O_SERVERID, | |
60 | + D6O_STATUS_CODE, | |
61 | + 0 | |
62 | +}; | |
63 | static const int required_opts_solicit[] = { | |
64 | D6O_CLIENTID, | |
65 | D6O_SERVERID, | |
66 | @@ -1587,6 +1635,56 @@ lease_to_client(struct data_string *repl | |
67 | reply.shared->group, NULL); | |
78ab9b04 MT |
68 | } |
69 | ||
70 | + /* reject unicast message, unless we set unicast option */ | |
71 | + if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) | |
72 | + /* | |
73 | + * RFC3315 section 18.2.1 (Request): | |
74 | + * | |
75 | + * When the server receives a Request message via unicast from a client | |
76 | + * to which the server has not sent a unicast option, the server | |
77 | + * discards the Request message and responds with a Reply message | |
78 | + * containing a Status Code option with the value UseMulticast, a Server | |
79 | + * Identifier option containing the server's DUID, the Client Identifier | |
80 | + * option from the client message, and no other options. | |
81 | + * | |
82 | + * Section 18.2.3 (Renew): | |
83 | + * | |
84 | + * When the server receives a Renew message via unicast from a client to | |
85 | + * which the server has not sent a unicast option, the server discards | |
86 | + * the Renew message and responds with a Reply message containing a | |
87 | + * Status Code option with the value UseMulticast, a Server Identifier | |
88 | + * option containing the server's DUID, the Client Identifier option | |
89 | + * from the client message, and no other options. | |
90 | + */ | |
91 | + { | |
92 | + /* Set the UseMulticast status code. */ | |
93 | + if (!set_status_code(STATUS_UseMulticast, | |
94 | + "Unicast not allowed by server.", | |
95 | + reply.opt_state)) { | |
96 | + log_error("lease_to_client: Unable to set " | |
97 | + "UseMulticast status code."); | |
98 | + goto exit; | |
99 | + } | |
100 | + | |
101 | + /* Rewind the cursor to the start. */ | |
102 | + reply.cursor = REPLY_OPTIONS_INDEX; | |
103 | + | |
104 | + /* | |
105 | + * Produce an reply that includes only: | |
106 | + * | |
107 | + * Status code. | |
108 | + * Server DUID. | |
109 | + * Client DUID. | |
110 | + */ | |
111 | + reply.cursor += store_options6((char *)reply.buf.data + | |
112 | + reply.cursor, | |
113 | + sizeof(reply.buf) - | |
114 | + reply.cursor, | |
115 | + reply.opt_state, reply.packet, | |
116 | + required_opts_NAA, | |
117 | + NULL); | |
c1e9ba67 MF |
118 | + } |
119 | + | |
78ab9b04 MT |
120 | /* |
121 | * RFC3315 section 17.2.2 (Solicit): | |
122 | * | |
c1e9ba67 MF |
123 | @@ -1619,6 +1717,7 @@ lease_to_client(struct data_string *repl |
124 | * Having stored the client's IA's, store any options that | |
125 | * will fit in the remaining space. | |
78ab9b04 | 126 | */ |
c1e9ba67 MF |
127 | + else |
128 | reply.cursor += store_options6((char *)reply.buf.data + reply.cursor, | |
129 | sizeof(reply.buf) - reply.cursor, | |
130 | reply.opt_state, reply.packet, | |
131 | @@ -4748,7 +4847,6 @@ dhcpv6_solicit(struct data_string *reply | |
78ab9b04 MT |
132 | * Very similar to Solicit handling, except the server DUID is required. |
133 | */ | |
134 | ||
135 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
136 | static void | |
137 | dhcpv6_request(struct data_string *reply_ret, struct packet *packet) { | |
138 | struct data_string client_id; | |
c1e9ba67 | 139 | @@ -5078,7 +5176,6 @@ exit: |
78ab9b04 MT |
140 | * except for the error code of when addresses don't match. |
141 | */ | |
142 | ||
143 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
144 | static void | |
145 | dhcpv6_renew(struct data_string *reply, struct packet *packet) { | |
146 | struct data_string client_id; | |
c1e9ba67 | 147 | @@ -5322,18 +5419,60 @@ iterate_over_ia_na(struct data_string *r |
78ab9b04 MT |
148 | goto exit; |
149 | } | |
150 | ||
151 | - snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type); | |
152 | - if (!set_status_code(STATUS_Success, status_msg, opt_state)) { | |
153 | - goto exit; | |
154 | - } | |
155 | + /* reject unicast message, unless we set unicast option */ | |
156 | + if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) { | |
157 | + /* | |
158 | + * RFC3315 section 18.2.6 (Release): | |
159 | + * | |
160 | + * When the server receives a Release message via unicast from a client | |
161 | + * to which the server has not sent a unicast option, the server | |
162 | + * discards the Release message and responds with a Reply message | |
163 | + * containing a Status Code option with value UseMulticast, a Server | |
164 | + * Identifier option containing the server's DUID, the Client Identifier | |
165 | + * option from the client message, and no other options. | |
166 | + * | |
167 | + * Section 18.2.7 (Decline): | |
168 | + * | |
169 | + * When the server receives a Decline message via unicast from a client | |
170 | + * to which the server has not sent a unicast option, the server | |
171 | + * discards the Decline message and responds with a Reply message | |
172 | + * containing a Status Code option with the value UseMulticast, a Server | |
173 | + * Identifier option containing the server's DUID, the Client Identifier | |
174 | + * option from the client message, and no other options. | |
175 | + */ | |
176 | + snprintf(status_msg, sizeof(status_msg), | |
177 | + "%s received unicast.", packet_type); | |
178 | + if (!set_status_code(STATUS_UseMulticast, status_msg, opt_state)) { | |
179 | + goto exit; | |
180 | + } | |
181 | ||
182 | - /* | |
183 | - * Add our options that are not associated with any IA_NA or IA_TA. | |
184 | - */ | |
185 | - reply_ofs += store_options6(reply_data+reply_ofs, | |
186 | - sizeof(reply_data)-reply_ofs, | |
187 | + /* | |
188 | + * Produce an reply that includes only: | |
189 | + * | |
190 | + * Status code. | |
191 | + * Server DUID. | |
192 | + * Client DUID. | |
193 | + */ | |
194 | + reply_ofs += store_options6(reply_data+reply_ofs, | |
195 | + sizeof(reply_data)-reply_ofs, | |
196 | opt_state, packet, | |
197 | - required_opts, NULL); | |
198 | + required_opts_NAA, NULL); | |
199 | + | |
200 | + goto return_reply; | |
201 | + } else { | |
202 | + snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type); | |
203 | + if (!set_status_code(STATUS_Success, status_msg, opt_state)) { | |
204 | + goto exit; | |
205 | + } | |
206 | + | |
207 | + /* | |
208 | + * Add our options that are not associated with any IA_NA or IA_TA. | |
209 | + */ | |
210 | + reply_ofs += store_options6(reply_data+reply_ofs, | |
211 | + sizeof(reply_data)-reply_ofs, | |
212 | + opt_state, packet, | |
213 | + required_opts, NULL); | |
214 | + } | |
215 | ||
216 | /* | |
217 | * Loop through the IA_NA reported by the client, and deal with | |
c1e9ba67 | 218 | @@ -5471,6 +5610,7 @@ iterate_over_ia_na(struct data_string *r |
78ab9b04 MT |
219 | /* |
220 | * Return our reply to the caller. | |
221 | */ | |
222 | +return_reply: | |
223 | reply_ret->len = reply_ofs; | |
224 | reply_ret->buffer = NULL; | |
225 | if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) { | |
c1e9ba67 | 226 | @@ -5516,7 +5656,6 @@ exit: |
78ab9b04 MT |
227 | * we still need to be aware of this possibility. |
228 | */ | |
229 | ||
230 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
231 | /* TODO: IA_TA */ | |
232 | static void | |
233 | dhcpv6_decline(struct data_string *reply, struct packet *packet) { | |
c1e9ba67 | 234 | @@ -5986,7 +6125,6 @@ exit: |
78ab9b04 MT |
235 | * Release means a client is done with the leases. |
236 | */ | |
237 | ||
238 | -/* TODO: reject unicast messages, unless we set unicast option */ | |
239 | static void | |
240 | dhcpv6_release(struct data_string *reply, struct packet *packet) { | |
241 | struct data_string client_id; |