"Inital commit to Gerrit"
[profile/ivi/dhcp.git] / packaging / dhcp-4.2.0-UseMulticast.patch
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;