]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dhcp-4.2.2-rfc3442-classless-static-routes.patch
firewall: add more pscan matches and filter INVALID conntrack packages.
[ipfire-2.x.git] / src / patches / dhcp-4.2.2-rfc3442-classless-static-routes.patch
CommitLineData
78ab9b04
MT
1diff -up dhcp-4.2.2b1/client/clparse.c.rfc3442 dhcp-4.2.2b1/client/clparse.c
2--- dhcp-4.2.2b1/client/clparse.c.rfc3442 2011-07-01 14:22:38.031534508 +0200
3+++ dhcp-4.2.2b1/client/clparse.c 2011-07-01 14:22:38.128532940 +0200
4@@ -37,7 +37,7 @@
5
6 struct client_config top_level_config;
7
8-#define NUM_DEFAULT_REQUESTED_OPTS 14
9+#define NUM_DEFAULT_REQUESTED_OPTS 15
10 struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
11
12 static void parse_client_default_duid(struct parse *cfile);
13@@ -82,7 +82,11 @@ isc_result_t read_client_conf ()
14 dhcp_universe.code_hash, &code, 0, MDL);
15
16 /* 4 */
17- code = DHO_ROUTERS;
18+ /* The Classless Static Routes option code MUST appear in the parameter
19+ * request list prior to both the Router option code and the Static
20+ * Routes option code, if present. (RFC3442)
21+ */
22+ code = DHO_CLASSLESS_STATIC_ROUTES;
23 option_code_hash_lookup(&default_requested_options[3],
24 dhcp_universe.code_hash, &code, 0, MDL);
25
26@@ -136,6 +140,11 @@ isc_result_t read_client_conf ()
27 option_code_hash_lookup(&default_requested_options[13],
28 dhcp_universe.code_hash, &code, 0, MDL);
29
30+ /* 15 */
31+ code = DHO_ROUTERS;
32+ option_code_hash_lookup(&default_requested_options[14],
33+ dhcp_universe.code_hash, &code, 0, MDL);
34+
35 for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
36 if (default_requested_options[code] == NULL)
37 log_fatal("Unable to find option definition for "
38diff -up dhcp-4.2.2b1/common/dhcp-options.5.rfc3442 dhcp-4.2.2b1/common/dhcp-options.5
39--- dhcp-4.2.2b1/common/dhcp-options.5.rfc3442 2011-07-01 14:22:38.020534686 +0200
40+++ dhcp-4.2.2b1/common/dhcp-options.5 2011-07-01 14:22:38.129532924 +0200
41@@ -115,6 +115,26 @@ hexadecimal, separated by colons. For
42 or
43 option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f;
44 .fi
45+.PP
46+The
47+.B destination-descriptor
48+describe the IP subnet number and subnet mask
49+of a particular destination using a compact encoding. This encoding
50+consists of one octet describing the width of the subnet mask,
51+followed by all the significant octets of the subnet number.
52+The following table contains some examples of how various subnet
53+number/mask combinations can be encoded:
54+.nf
55+.sp 1
56+Subnet number Subnet mask Destination descriptor
57+0 0 0
58+10.0.0.0 255.0.0.0 8.10
59+10.0.0.0 255.255.255.0 24.10.0.0
60+10.17.0.0 255.255.0.0 16.10.17
61+10.27.129.0 255.255.255.0 24.10.27.129
62+10.229.0.128 255.255.255.128 25.10.229.0.128
63+10.198.122.47 255.255.255.255 32.10.198.122.47
64+.fi
65 .SH SETTING OPTION VALUES USING EXPRESSIONS
66 Sometimes it's helpful to be able to set the value of a DHCP option
67 based on some value that the client has sent. To do this, you can
68@@ -931,6 +951,29 @@ dhclient-script will create routes:
69 .RE
70 .PP
71 .nf
72+.B option \fBclassless-static-routes\fR \fIdestination-descriptor ip-address\fR
73+ [\fB,\fR \fIdestination-descriptor ip-address\fR...]\fB;\fR
74+.fi
75+.RS 0.25i
76+.PP
77+This option (see RFC3442) specifies a list of classless static routes
78+that the client should install in its routing cache.
79+.PP
80+This option can contain one or more static routes, each of which
81+consists of a destination descriptor and the IP address of the router
82+that should be used to reach that destination.
83+.PP
84+Many clients may not implement the Classless Static Routes option.
85+DHCP server administrators should therefore configure their DHCP
86+servers to send both a Router option and a Classless Static Routes
87+option, and should specify the default router(s) both in the Router
88+option and in the Classless Static Routes option.
89+.PP
90+If the DHCP server returns both a Classless Static Routes option and
91+a Router option, the DHCP client ignores the Router option.
92+.RE
93+.PP
94+.nf
95 .B option \fBstreettalk-directory-assistance-server\fR \fIip-address\fR
96 [\fB,\fR \fIip-address\fR...]\fB;\fR
97 .fi
98diff -up dhcp-4.2.2b1/common/inet.c.rfc3442 dhcp-4.2.2b1/common/inet.c
99--- dhcp-4.2.2b1/common/inet.c.rfc3442 2011-05-11 02:47:22.000000000 +0200
100+++ dhcp-4.2.2b1/common/inet.c 2011-07-01 14:22:38.130532908 +0200
101@@ -528,6 +528,60 @@ free_iaddrcidrnetlist(struct iaddrcidrne
102 return ISC_R_SUCCESS;
103 }
104
105+static const char *
106+inet_ntopdd(const unsigned char *src, unsigned srclen, char *dst, size_t size)
107+{
108+ char tmp[sizeof("32.255.255.255.255")];
109+ int len;
110+
111+ switch (srclen) {
112+ case 2:
113+ len = sprintf (tmp, "%u.%u", src[0], src[1]);
114+ break;
115+ case 3:
116+ len = sprintf (tmp, "%u.%u.%u", src[0], src[1], src[2]);
117+ break;
118+ case 4:
119+ len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
120+ break;
121+ case 5:
122+ len = sprintf (tmp, "%u.%u.%u.%u.%u", src[0], src[1], src[2], src[3], src[4]);
123+ break;
124+ default:
125+ return NULL;
126+ }
127+ if (len < 0)
128+ return NULL;
129+
130+ if (len > size) {
131+ errno = ENOSPC;
132+ return NULL;
133+ }
134+
135+ return strcpy (dst, tmp);
136+}
137+
138+/* pdestdesc() turns an iaddr structure into a printable dest. descriptor */
139+const char *
140+pdestdesc(const struct iaddr addr) {
141+ static char pbuf[sizeof("255.255.255.255.255")];
142+
143+ if (addr.len == 0) {
144+ return "<null destination descriptor>";
145+ }
146+ if (addr.len == 1) {
147+ return "0";
148+ }
149+ if ((addr.len >= 2) && (addr.len <= 5)) {
150+ return inet_ntopdd(addr.iabuf, addr.len, pbuf, sizeof(pbuf));
151+ }
152+
153+ log_fatal("pdestdesc():%s:%d: Invalid destination descriptor length %d.",
154+ MDL, addr.len);
155+ /* quell compiler warnings */
156+ return NULL;
157+}
158+
159 /* piaddr() turns an iaddr structure into a printable address. */
160 /* XXX: should use a const pointer rather than passing the structure */
161 const char *
162diff -up dhcp-4.2.2b1/common/options.c.rfc3442 dhcp-4.2.2b1/common/options.c
163--- dhcp-4.2.2b1/common/options.c.rfc3442 2011-03-24 22:57:13.000000000 +0100
164+++ dhcp-4.2.2b1/common/options.c 2011-07-01 14:22:38.132532876 +0200
165@@ -706,7 +706,11 @@ cons_options(struct packet *inpacket, st
166 * packet.
167 */
168 priority_list[priority_len++] = DHO_SUBNET_MASK;
169- priority_list[priority_len++] = DHO_ROUTERS;
170+ if (lookup_option(&dhcp_universe, cfg_options,
171+ DHO_CLASSLESS_STATIC_ROUTES))
172+ priority_list[priority_len++] = DHO_CLASSLESS_STATIC_ROUTES;
173+ else
174+ priority_list[priority_len++] = DHO_ROUTERS;
175 priority_list[priority_len++] = DHO_DOMAIN_NAME_SERVERS;
176 priority_list[priority_len++] = DHO_HOST_NAME;
177 priority_list[priority_len++] = DHO_FQDN;
178@@ -1683,6 +1687,7 @@ const char *pretty_print_option (option,
179 const unsigned char *dp = data;
180 char comma;
181 unsigned long tval;
182+ unsigned int octets = 0;
183
184 if (emit_commas)
185 comma = ',';
186@@ -1691,6 +1696,7 @@ const char *pretty_print_option (option,
187
188 memset (enumbuf, 0, sizeof enumbuf);
189
190+ if (option->format[0] != 'R') { /* see explanation lower */
191 /* Figure out the size of the data. */
192 for (l = i = 0; option -> format [i]; i++, l++) {
193 if (l >= sizeof(fmtbuf) - 1)
194@@ -1840,6 +1846,33 @@ const char *pretty_print_option (option,
195 if (numhunk < 0)
196 numhunk = 1;
197
198+ } else { /* option->format[i] == 'R') */
199+ /* R (destination descriptor) has variable length.
200+ * We can find it only in classless static route option,
201+ * so we are for sure parsing classless static route option now.
202+ * We go through whole the option to check whether there are no
203+ * missing/extra bytes.
204+ * I didn't find out how to improve the existing code and that's the
205+ * reason for this separate 'else' where I do my own checkings.
206+ * I know it's little bit unsystematic, but it works.
207+ */
208+ numhunk = 0;
209+ numelem = 2; /* RI */
210+ fmtbuf[0]='R'; fmtbuf[1]='I'; fmtbuf[2]=0;
211+ for (i =0; i < len; i = i + octets + 5) {
212+ if (data[i] > 32) { /* subnet mask width */
213+ log_error ("wrong subnet mask width in destination descriptor");
214+ break;
215+ }
216+ numhunk++;
217+ octets = ((data[i]+7) / 8);
218+ }
219+ if (i != len) {
220+ log_error ("classless static routes option has wrong size or "
221+ "there's some garbage in format");
222+ }
223+ }
224+
225 /* Cycle through the array (or hunk) printing the data. */
226 for (i = 0; i < numhunk; i++) {
227 for (j = 0; j < numelem; j++) {
228@@ -1978,6 +2011,20 @@ const char *pretty_print_option (option,
229 strcpy(op, piaddr(iaddr));
230 dp += 4;
231 break;
232+
233+ case 'R':
234+ if (dp[0] <= 32)
235+ iaddr.len = (((dp[0]+7)/8)+1);
236+ else {
237+ log_error ("wrong subnet mask width in destination descriptor");
238+ return "<error>";
239+ }
240+
241+ memcpy(iaddr.iabuf, dp, iaddr.len);
242+ strcpy(op, pdestdesc(iaddr));
243+ dp += iaddr.len;
244+ break;
245+
246 case '6':
247 iaddr.len = 16;
248 memcpy(iaddr.iabuf, dp, 16);
249diff -up dhcp-4.2.2b1/common/parse.c.rfc3442 dhcp-4.2.2b1/common/parse.c
250--- dhcp-4.2.2b1/common/parse.c.rfc3442 2011-07-01 14:22:38.097533441 +0200
251+++ dhcp-4.2.2b1/common/parse.c 2011-07-01 14:22:38.135532828 +0200
252@@ -341,6 +341,39 @@ int parse_ip_addr (cfile, addr)
253 }
254
255 /*
256+ * destination-descriptor :== NUMBER DOT NUMBER |
257+ * NUMBER DOT NUMBER DOT NUMBER |
258+ * NUMBER DOT NUMBER DOT NUMBER DOT NUMBER |
259+ * NUMBER DOT NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
260+ */
261+
262+int parse_destination_descriptor (cfile, addr)
263+ struct parse *cfile;
264+ struct iaddr *addr;
265+{
266+ unsigned int mask_width, dest_dest_len;
267+ addr -> len = 0;
268+ if (parse_numeric_aggregate (cfile, addr -> iabuf,
269+ &addr -> len, DOT, 10, 8)) {
270+ mask_width = (unsigned int)addr->iabuf[0];
271+ dest_dest_len = (((mask_width+7)/8)+1);
272+ if (mask_width > 32) {
273+ parse_warn (cfile,
274+ "subnet mask width (%u) greater than 32.", mask_width);
275+ }
276+ else if (dest_dest_len != addr->len) {
277+ parse_warn (cfile,
278+ "destination descriptor with subnet mask width %u "
279+ "should have %u octets, but has %u octets.",
280+ mask_width, dest_dest_len, addr->len);
281+ }
282+
283+ return 1;
284+ }
285+ return 0;
286+}
287+
288+/*
289 * Return true if every character in the string is hexadecimal.
290 */
291 static int
292@@ -700,8 +733,10 @@ unsigned char *parse_numeric_aggregate (
293 if (count) {
294 token = peek_token (&val, (unsigned *)0, cfile);
295 if (token != separator) {
296- if (!*max)
297+ if (!*max) {
298+ *max = count;
299 break;
300+ }
301 if (token != RBRACE && token != LBRACE)
302 token = next_token (&val,
303 (unsigned *)0,
304@@ -1624,6 +1659,9 @@ int parse_option_code_definition (cfile,
305 case IP_ADDRESS:
306 type = 'I';
307 break;
308+ case DESTINATION_DESCRIPTOR:
309+ type = 'R';
310+ break;
311 case IP6_ADDRESS:
312 type = '6';
313 break;
314@@ -5288,6 +5326,15 @@ int parse_option_token (rv, cfile, fmt,
315 }
316 break;
317
318+ case 'R': /* destination descriptor */
319+ if (!parse_destination_descriptor (cfile, &addr)) {
320+ return 0;
321+ }
322+ if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1, MDL)) {
323+ return 0;
324+ }
325+ break;
326+
327 case '6': /* IPv6 address. */
328 if (!parse_ip6_addr(cfile, &addr)) {
329 return 0;
330@@ -5548,6 +5595,13 @@ int parse_option_decl (oc, cfile)
331 goto exit;
332 len = ip_addr.len;
333 dp = ip_addr.iabuf;
334+ goto alloc;
335+
336+ case 'R': /* destination descriptor */
337+ if (!parse_destination_descriptor (cfile, &ip_addr))
338+ goto exit;
339+ len = ip_addr.len;
340+ dp = ip_addr.iabuf;
341
342 alloc:
343 if (hunkix + len > sizeof hunkbuf) {
344diff -up dhcp-4.2.2b1/common/tables.c.rfc3442 dhcp-4.2.2b1/common/tables.c
345--- dhcp-4.2.2b1/common/tables.c.rfc3442 2011-07-01 14:22:38.087533601 +0200
346+++ dhcp-4.2.2b1/common/tables.c 2011-07-01 14:22:38.137532796 +0200
347@@ -51,6 +51,7 @@ HASH_FUNCTIONS (option_code, const unsig
348 Format codes:
349
350 I - IPv4 address
351+ R - destination descriptor (RFC3442)
352 6 - IPv6 address
353 l - 32-bit signed integer
354 L - 32-bit unsigned integer
355@@ -208,6 +209,7 @@ static struct option dhcp_options[] = {
356 { "default-url", "t", &dhcp_universe, 114, 1 },
357 { "subnet-selection", "I", &dhcp_universe, 118, 1 },
358 { "domain-search", "D", &dhcp_universe, 119, 1 },
359+ { "classless-static-routes", "RIA", &dhcp_universe, 121, 1 },
360 { "vivco", "Evendor-class.", &dhcp_universe, 124, 1 },
361 { "vivso", "Evendor.", &dhcp_universe, 125, 1 },
362 #if 0
363diff -up dhcp-4.2.2b1/includes/dhcpd.h.rfc3442 dhcp-4.2.2b1/includes/dhcpd.h
364--- dhcp-4.2.2b1/includes/dhcpd.h.rfc3442 2011-07-01 14:22:38.000000000 +0200
365+++ dhcp-4.2.2b1/includes/dhcpd.h 2011-07-01 14:24:19.999810333 +0200
366@@ -2662,6 +2662,7 @@ isc_result_t range2cidr(struct iaddrcidr
367 const struct iaddr *lo, const struct iaddr *hi);
368 isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result);
369 const char *piaddr (struct iaddr);
370+const char *pdestdesc (struct iaddr);
371 char *piaddrmask(struct iaddr *, struct iaddr *);
372 char *piaddrcidr(const struct iaddr *, unsigned int);
373 u_int16_t validate_port(char *);
374@@ -2869,6 +2870,7 @@ void parse_client_lease_declaration (str
375 int parse_option_decl (struct option_cache **, struct parse *);
376 void parse_string_list (struct parse *, struct string_list **, int);
377 int parse_ip_addr (struct parse *, struct iaddr *);
378+int parse_destination_descriptor (struct parse *, struct iaddr *);
379 int parse_ip_addr_with_subnet(struct parse *, struct iaddrmatch *);
380 void parse_reject_statement (struct parse *, struct client_config *);
381
382diff -up dhcp-4.2.2b1/includes/dhcp.h.rfc3442 dhcp-4.2.2b1/includes/dhcp.h
383--- dhcp-4.2.2b1/includes/dhcp.h.rfc3442 2009-11-20 02:49:01.000000000 +0100
384+++ dhcp-4.2.2b1/includes/dhcp.h 2011-07-01 14:22:38.145532665 +0200
385@@ -158,6 +158,7 @@ struct dhcp_packet {
386 #define DHO_ASSOCIATED_IP 92
387 #define DHO_SUBNET_SELECTION 118 /* RFC3011! */
388 #define DHO_DOMAIN_SEARCH 119 /* RFC3397 */
389+#define DHO_CLASSLESS_STATIC_ROUTES 121 /* RFC3442 */
390 #define DHO_VIVCO_SUBOPTIONS 124
391 #define DHO_VIVSO_SUBOPTIONS 125
392
393diff -up dhcp-4.2.2b1/includes/dhctoken.h.rfc3442 dhcp-4.2.2b1/includes/dhctoken.h
394--- dhcp-4.2.2b1/includes/dhctoken.h.rfc3442 2011-07-01 14:22:37.000000000 +0200
395+++ dhcp-4.2.2b1/includes/dhctoken.h 2011-07-01 14:25:12.541867623 +0200
396@@ -362,7 +362,8 @@ enum dhcp_token {
397 REWIND = 663,
398 INITIAL_DELAY = 664,
399 GETHOSTBYNAME = 665,
400- BOOTP_BROADCAST_ALWAYS = 666
401+ BOOTP_BROADCAST_ALWAYS = 666,
402+ DESTINATION_DESCRIPTOR = 667
403 };
404
405 #define is_identifier(x) ((x) >= FIRST_TOKEN && \