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