chiark / gitweb /
shared: in-addr-utils - add default_subnet_mask and default_prefixlen methods
[elogind.git] / src / libsystemd-network / sd-dhcp-lease.c
1 /***
2   This file is part of systemd.
3
4   Copyright (C) 2013 Intel Corporation. All rights reserved.
5   Copyright (C) 2014 Tom Gundersen
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <net/ethernet.h>
26 #include <arpa/inet.h>
27 #include <sys/param.h>
28
29 #include "util.h"
30 #include "list.h"
31 #include "mkdir.h"
32 #include "fileio.h"
33 #include "in-addr-util.h"
34
35 #include "dhcp-protocol.h"
36 #include "dhcp-internal.h"
37 #include "dhcp-lease-internal.h"
38 #include "sd-dhcp-lease.h"
39 #include "sd-dhcp-client.h"
40 #include "network-internal.h"
41
42 int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
43         assert_return(lease, -EINVAL);
44         assert_return(addr, -EINVAL);
45
46         addr->s_addr = lease->address;
47
48         return 0;
49 }
50
51 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
52         assert_return(lease, -EINVAL);
53         assert_return(lease, -EINVAL);
54
55         *lifetime = lease->lifetime;
56
57         return 0;
58 }
59
60 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
61         assert_return(lease, -EINVAL);
62         assert_return(mtu, -EINVAL);
63
64         if (lease->mtu)
65                 *mtu = lease->mtu;
66         else
67                 return -ENOENT;
68
69         return 0;
70 }
71
72 int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
73         assert_return(lease, -EINVAL);
74         assert_return(addr, -EINVAL);
75
76         if (lease->dns_size) {
77                 *addr = lease->dns;
78                 return lease->dns_size;
79         } else
80                 return -ENOENT;
81
82         return 0;
83 }
84
85 int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
86         assert_return(lease, -EINVAL);
87         assert_return(addr, -EINVAL);
88
89         if (lease->ntp_size) {
90                 *addr = lease->ntp;
91                 return lease->ntp_size;
92         } else
93                 return -ENOENT;
94
95         return 0;
96 }
97
98 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
99         assert_return(lease, -EINVAL);
100         assert_return(domainname, -EINVAL);
101
102         if (lease->domainname)
103                 *domainname = lease->domainname;
104         else
105                 return -ENOENT;
106
107         return 0;
108 }
109
110 int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
111         assert_return(lease, -EINVAL);
112         assert_return(hostname, -EINVAL);
113
114         if (lease->hostname)
115                 *hostname = lease->hostname;
116         else
117                 return -ENOENT;
118
119         return 0;
120 }
121
122 int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
123         assert_return(lease, -EINVAL);
124         assert_return(root_path, -EINVAL);
125
126         if (lease->root_path)
127                 *root_path = lease->root_path;
128         else
129                 return -ENOENT;
130
131         return 0;
132 }
133
134 int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
135         assert_return(lease, -EINVAL);
136         assert_return(addr, -EINVAL);
137
138         if (lease->router != INADDR_ANY)
139                 addr->s_addr = lease->router;
140         else
141                 return -ENOENT;
142
143         return 0;
144 }
145
146 int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
147         assert_return(lease, -EINVAL);
148         assert_return(addr, -EINVAL);
149
150         addr->s_addr = lease->subnet_mask;
151
152         return 0;
153 }
154
155 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
156         assert_return(lease, -EINVAL);
157         assert_return(addr, -EINVAL);
158
159         addr->s_addr = lease->server_address;
160
161         return 0;
162 }
163
164 int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
165         assert_return(lease, -EINVAL);
166         assert_return(addr, -EINVAL);
167
168         addr->s_addr = lease->next_server;
169
170         return 0;
171 }
172
173 int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
174
175         assert_return(lease, -EINVAL);
176         assert_return(routes, -EINVAL);
177
178         if (lease->static_route_size) {
179                 *routes = lease->static_route;
180                 return lease->static_route_size;
181         } else
182                 return -ENOENT;
183
184         return 0;
185 }
186
187 sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
188         if (lease)
189                 assert_se(REFCNT_INC(lease->n_ref) >= 2);
190
191         return lease;
192 }
193
194 sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
195         if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
196                 free(lease->hostname);
197                 free(lease->domainname);
198                 free(lease->dns);
199                 free(lease->ntp);
200                 free(lease->static_route);
201                 free(lease);
202         }
203
204         return NULL;
205 }
206
207 static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
208         be32_t val;
209
210         assert(option);
211         assert(ret);
212
213         if (len == 4) {
214                 memcpy(&val, option, 4);
215                 *ret = be32toh(val);
216
217                 if (*ret < min)
218                         *ret = min;
219         }
220 }
221
222 static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
223         lease_parse_u32(option, len, (uint32_t *)ret, 0);
224 }
225
226 static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
227         be16_t val;
228
229         assert(option);
230         assert(ret);
231
232         if (len == 2) {
233                 memcpy(&val, option, 2);
234                 *ret = be16toh(val);
235
236                 if (*ret < min)
237                         *ret = min;
238         }
239 }
240
241 static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
242         assert(option);
243         assert(ret);
244
245         if (len == 4)
246                 memcpy(ret, option, 4);
247 }
248
249 static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) {
250         assert(option);
251         assert(ret);
252
253         if (len == 1)
254                 *ret = !!(*option);
255 }
256
257 static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) {
258         assert(option);
259         assert(ret);
260
261         if (len == 1) {
262                 *ret = *option;
263
264                 if (*ret < min)
265                         *ret = min;
266         }
267 }
268
269 static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
270         assert(option);
271         assert(ret);
272
273         if (len >= 1) {
274                 char *string;
275
276                 string = strndup((const char *)option, len);
277                 if (!string)
278                         return -errno;
279
280                 free(*ret);
281                 *ret = string;
282         }
283
284         return 0;
285 }
286
287 static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
288         assert(option);
289         assert(ret);
290         assert(ret_size);
291
292         if (len && !(len % (4 * mult))) {
293                 size_t size;
294                 struct in_addr *addresses;
295
296                 size = len / 4;
297
298                 addresses = newdup(struct in_addr, option, size);
299                 if (!addresses)
300                         return -ENOMEM;
301
302                 free(*ret);
303                 *ret = addresses;
304                 *ret_size = size;
305         }
306
307         return 0;
308 }
309
310 static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
311         return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1);
312 }
313
314 static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
315         return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
316 }
317
318 static int class_prefixlen(uint8_t msb_octet, uint8_t *ret) {
319         if (msb_octet < 128)
320                 /* Class A */
321                 *ret = 8;
322         else if (msb_octet < 192)
323                 /* Class B */
324                 *ret = 16;
325         else if (msb_octet < 224)
326                 /* Class C */
327                 *ret = 24;
328         else
329                 /* Class D or E -- no subnet mask */
330                 return -ERANGE;
331
332         return 0;
333 }
334
335 static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
336         size_t *routes_size, size_t *routes_allocated) {
337
338         struct in_addr addr;
339
340         assert(option);
341         assert(routes);
342         assert(routes_size);
343         assert(routes_allocated);
344
345         if (!len)
346                 return 0;
347
348         if (len % 8 != 0)
349                 return -EINVAL;
350
351         if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8)))
352                 return -ENOMEM;
353
354         while (len >= 8) {
355                 struct sd_dhcp_route *route = *routes + *routes_size;
356
357                 if (class_prefixlen(*option, &route->dst_prefixlen) < 0) {
358                         log_error("Failed to determine destination prefix length from class based IP, ignoring");
359                         continue;
360                 }
361
362                 lease_parse_be32(option, 4, &addr.s_addr);
363                 route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
364                 option += 4;
365
366                 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
367                 option += 4;
368
369                 len -= 8;
370                 (*routes_size)++;
371         }
372
373         return 0;
374 }
375
376 /* parses RFC3442 Classless Static Route Option */
377 static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
378         size_t *routes_size, size_t *routes_allocated) {
379
380         assert(option);
381         assert(routes);
382         assert(routes_size);
383         assert(routes_allocated);
384
385         /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)*  */
386
387         while (len > 0) {
388                 uint8_t dst_octets;
389                 struct sd_dhcp_route *route;
390
391                 if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1))
392                     return -ENOMEM;
393
394                 route = *routes + *routes_size;
395
396                 dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1);
397                 route->dst_prefixlen = *option;
398                 option++;
399                 len--;
400
401                 /* can't have more than 4 octets in IPv4 */
402                 if (dst_octets > 4 || len < dst_octets)
403                         return -EINVAL;
404
405                 route->dst_addr.s_addr = 0;
406                 memcpy(&route->dst_addr.s_addr, option, dst_octets);
407                 option += dst_octets;
408                 len -= dst_octets;
409
410                 if (len < 4)
411                         return -EINVAL;
412
413                 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
414                 option += 4;
415                 len -= 4;
416
417                 (*routes_size)++;
418         }
419
420         return 0;
421 }
422
423 int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
424                               void *user_data) {
425         sd_dhcp_lease *lease = user_data;
426         int r;
427
428         assert(lease);
429
430         switch(code) {
431
432         case DHCP_OPTION_TIME_OFFSET:
433                 lease_parse_s32(option, len, &lease->time_offset);
434
435                 break;
436
437         case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT:
438                 lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0);
439
440                 break;
441
442         case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
443                 lease_parse_u32(option, len, &lease->lifetime, 1);
444
445                 break;
446
447         case DHCP_OPTION_SERVER_IDENTIFIER:
448                 lease_parse_be32(option, len, &lease->server_address);
449
450                 break;
451
452         case DHCP_OPTION_SUBNET_MASK:
453                 lease_parse_be32(option, len, &lease->subnet_mask);
454
455                 break;
456
457         case DHCP_OPTION_BROADCAST:
458                 lease_parse_be32(option, len, &lease->broadcast);
459
460                 break;
461
462         case DHCP_OPTION_ROUTER:
463                 lease_parse_be32(option, len, &lease->router);
464
465                 break;
466
467         case DHCP_OPTION_DOMAIN_NAME_SERVER:
468                 r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
469                 if (r < 0)
470                         return r;
471
472                 break;
473
474         case DHCP_OPTION_NTP_SERVER:
475                 r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
476                 if (r < 0)
477                         return r;
478
479                 break;
480
481         case DHCP_OPTION_POLICY_FILTER:
482                 r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size);
483                 if (r < 0)
484                         return r;
485
486                 break;
487
488         case DHCP_OPTION_STATIC_ROUTE:
489                 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size,
490                         &lease->static_route_allocated);
491                 if (r < 0)
492                         return r;
493
494                 break;
495
496         case DHCP_OPTION_INTERFACE_MTU:
497                 lease_parse_u16(option, len, &lease->mtu, 68);
498
499                 break;
500
501         case DHCP_OPTION_INTERFACE_MDR:
502                 lease_parse_u16(option, len, &lease->mdr, 576);
503
504                 break;
505
506         case DHCP_OPTION_INTERFACE_TTL:
507                 lease_parse_u8(option, len, &lease->ttl, 1);
508
509                 break;
510
511         case DHCP_OPTION_BOOT_FILE_SIZE:
512                 lease_parse_u16(option, len, &lease->boot_file_size, 0);
513
514                 break;
515
516         case DHCP_OPTION_DOMAIN_NAME:
517         {
518                 _cleanup_free_ char *domainname = NULL;
519
520                 r = lease_parse_string(option, len, &domainname);
521                 if (r < 0)
522                         return r;
523
524                 if (!hostname_is_valid(domainname) || is_localhost(domainname))
525                         break;
526
527                 free(lease->domainname);
528                 lease->domainname = domainname;
529                 domainname = NULL;
530
531                 break;
532         }
533         case DHCP_OPTION_HOST_NAME:
534         {
535                 _cleanup_free_ char *hostname = NULL;
536
537                 r = lease_parse_string(option, len, &hostname);
538                 if (r < 0)
539                         return r;
540
541                 if (!hostname_is_valid(hostname) || is_localhost(hostname))
542                         break;
543
544                 free(lease->hostname);
545                 lease->hostname = hostname;
546                 hostname = NULL;
547
548                 break;
549         }
550         case DHCP_OPTION_ROOT_PATH:
551                 r = lease_parse_string(option, len, &lease->root_path);
552                 if (r < 0)
553                         return r;
554
555                 break;
556
557         case DHCP_OPTION_RENEWAL_T1_TIME:
558                 lease_parse_u32(option, len, &lease->t1, 1);
559
560                 break;
561
562         case DHCP_OPTION_REBINDING_T2_TIME:
563                 lease_parse_u32(option, len, &lease->t2, 1);
564
565                 break;
566
567         case DHCP_OPTION_ENABLE_IP_FORWARDING:
568                 lease_parse_bool(option, len, &lease->ip_forward);
569
570                 break;
571
572         case DHCP_OPTION_ENABLE_IP_FORWARDING_NL:
573                 lease_parse_bool(option, len, &lease->ip_forward_non_local);
574
575                 break;
576
577         case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
578                 r = lease_parse_classless_routes(option, len, &lease->static_route, &lease->static_route_size,
579                         &lease->static_route_allocated);
580                 if (r < 0)
581                         return r;
582
583                 break;
584         }
585
586         return 0;
587 }
588
589 int dhcp_lease_new(sd_dhcp_lease **ret) {
590         sd_dhcp_lease *lease;
591
592         lease = new0(sd_dhcp_lease, 1);
593         if (!lease)
594                 return -ENOMEM;
595
596         lease->router = INADDR_ANY;
597         lease->n_ref = REFCNT_INIT;
598
599         *ret = lease;
600         return 0;
601 }
602
603 int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
604         _cleanup_free_ char *temp_path = NULL;
605         _cleanup_fclose_ FILE *f = NULL;
606         struct in_addr address;
607         const struct in_addr *addresses;
608         const char *string;
609         uint16_t mtu;
610         struct sd_dhcp_route *routes;
611         int r;
612
613         assert(lease);
614         assert(lease_file);
615
616         r = fopen_temporary(lease_file, &f, &temp_path);
617         if (r < 0)
618                 goto finish;
619
620         fchmod(fileno(f), 0644);
621
622         r = sd_dhcp_lease_get_address(lease, &address);
623         if (r < 0)
624                 goto finish;
625
626         fprintf(f,
627                 "# This is private data. Do not parse.\n"
628                 "ADDRESS=%s\n", inet_ntoa(address));
629
630         r = sd_dhcp_lease_get_netmask(lease, &address);
631         if (r < 0)
632                 goto finish;
633
634         fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
635
636         r = sd_dhcp_lease_get_router(lease, &address);
637         if (r >= 0)
638                 fprintf(f, "ROUTER=%s\n", inet_ntoa(address));
639
640         r = sd_dhcp_lease_get_server_identifier(lease, &address);
641         if (r >= 0)
642                 fprintf(f, "SERVER_ADDRESS=%s\n",
643                         inet_ntoa(address));
644
645         r = sd_dhcp_lease_get_next_server(lease, &address);
646         if (r >= 0)
647                 fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
648
649         r = sd_dhcp_lease_get_mtu(lease, &mtu);
650         if (r >= 0)
651                 fprintf(f, "MTU=%" PRIu16 "\n", mtu);
652
653         fputs("DNS=", f);
654         r = sd_dhcp_lease_get_dns(lease, &addresses);
655         if (r >= 0)
656                 serialize_in_addrs(f, addresses, r);
657         fputs("\n", f);
658
659         fputs("NTP=", f);
660         r = sd_dhcp_lease_get_ntp(lease, &addresses);
661         if (r >= 0)
662                 serialize_in_addrs(f, addresses, r);
663         fputs("\n", f);
664
665         r = sd_dhcp_lease_get_domainname(lease, &string);
666         if (r >= 0)
667                 fprintf(f, "DOMAINNAME=%s\n", string);
668
669         r = sd_dhcp_lease_get_hostname(lease, &string);
670         if (r >= 0)
671                 fprintf(f, "HOSTNAME=%s\n", string);
672
673         r = sd_dhcp_lease_get_root_path(lease, &string);
674         if (r >= 0)
675                 fprintf(f, "ROOT_PATH=%s\n", string);
676
677         r = sd_dhcp_lease_get_routes(lease, &routes);
678         if (r >= 0)
679                 serialize_dhcp_routes(f, "ROUTES", routes, r);
680
681         r = 0;
682
683         fflush(f);
684
685         if (ferror(f) || rename(temp_path, lease_file) < 0) {
686                 r = -errno;
687                 unlink(lease_file);
688                 unlink(temp_path);
689         }
690
691 finish:
692         if (r < 0)
693                 log_error("Failed to save lease data %s: %s", lease_file, strerror(-r));
694
695         return r;
696 }
697
698 int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) {
699         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
700         _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
701                             *server_address = NULL, *next_server = NULL,
702                             *dns = NULL, *ntp = NULL, *mtu = NULL, *routes = NULL;
703         struct in_addr addr;
704         int r;
705
706         assert(lease_file);
707         assert(ret);
708
709         r = dhcp_lease_new(&lease);
710         if (r < 0)
711                 return r;
712
713         r = parse_env_file(lease_file, NEWLINE,
714                            "ADDRESS", &address,
715                            "ROUTER", &router,
716                            "NETMASK", &netmask,
717                            "SERVER_IDENTIFIER", &server_address,
718                            "NEXT_SERVER", &next_server,
719                            "DNS", &dns,
720                            "NTP", &ntp,
721                            "MTU", &mtu,
722                            "DOMAINNAME", &lease->domainname,
723                            "HOSTNAME", &lease->hostname,
724                            "ROOT_PATH", &lease->root_path,
725                            "ROUTES", &routes,
726                            NULL);
727         if (r < 0) {
728                 if (r == -ENOENT)
729                         return 0;
730
731                 log_error("Failed to read %s: %s", lease_file, strerror(-r));
732                 return r;
733         }
734
735         r = inet_pton(AF_INET, address, &addr);
736         if (r < 0)
737                 return r;
738
739         lease->address = addr.s_addr;
740
741         if (router) {
742                 r = inet_pton(AF_INET, router, &addr);
743                 if (r < 0)
744                         return r;
745
746                 lease->router = addr.s_addr;
747         }
748
749         r = inet_pton(AF_INET, netmask, &addr);
750         if (r < 0)
751                 return r;
752
753         lease->subnet_mask = addr.s_addr;
754
755         if (server_address) {
756                 r = inet_pton(AF_INET, server_address, &addr);
757                 if (r < 0)
758                         return r;
759
760                 lease->server_address = addr.s_addr;
761         }
762
763         if (next_server) {
764                 r = inet_pton(AF_INET, next_server, &addr);
765                 if (r < 0)
766                         return r;
767
768                 lease->next_server = addr.s_addr;
769         }
770
771         if (dns) {
772                 r = deserialize_in_addrs(&lease->dns, dns);
773                 if (r < 0)
774                         return r;
775
776                 lease->dns_size = r;
777         }
778
779         if (ntp) {
780                 r = deserialize_in_addrs(&lease->ntp, ntp);
781                 if (r < 0)
782                         return r;
783
784                 lease->ntp_size = r;
785         }
786
787         if (mtu) {
788                 uint16_t u;
789                 if (sscanf(mtu, "%" SCNu16, &u) > 0)
790                         lease->mtu = u;
791         }
792
793         if (routes) {
794                 r = deserialize_dhcp_routes(&lease->static_route, &lease->static_route_size,
795                                 &lease->static_route_allocated, routes);
796                 if (r < 0)
797                     return r;
798         }
799
800         *ret = lease;
801         lease = NULL;
802
803         return 0;
804 }
805
806 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
807         struct in_addr address;
808         struct in_addr mask;
809         int r;
810
811         assert(lease);
812
813         address.s_addr = lease->address;
814
815         /* fall back to the default subnet masks based on address class */
816         r = in_addr_default_subnet_mask(&address, &mask);
817         if (r < 0)
818                 return r;
819
820         lease->subnet_mask = mask.s_addr;
821
822         return 0;
823 }