]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/sd-radv.c
sd-radv: Add Router Advertisement prefix handling
[thirdparty/systemd.git] / src / libsystemd-network / sd-radv.c
CommitLineData
04473969
PF
1/***
2 This file is part of systemd.
3
4 Copyright (C) 2017 Intel Corporation. All rights reserved.
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <netinet/icmp6.h>
21#include <netinet/in.h>
22
23#include "sd-radv.h"
24
25#include "alloc-util.h"
26#include "fd-util.h"
27#include "icmp6-util.h"
28#include "in-addr-util.h"
29#include "radv-internal.h"
30#include "socket-util.h"
31#include "string-util.h"
32#include "util.h"
33
34_public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
35 _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
36
37 assert_return(ret, -EINVAL);
38
39 p = new0(sd_radv_prefix, 1);
40 if (!p)
41 return -ENOMEM;
42
43 p->n_ref = 1;
44
45 p->opt.type = ND_OPT_PREFIX_INFORMATION;
46 p->opt.length = (sizeof(p->opt) - 1) /8 + 1;
47
48 p->opt.prefixlen = 64;
49
50 /* RFC 4861, Section 6.2.1 */
51 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, true);
52 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, true);
53 p->opt.preferred_lifetime = htobe32(604800);
54 p->opt.valid_lifetime = htobe32(2592000);
55
56 *ret = p;
57 p = NULL;
58
59 return 0;
60}
61
62_public_ sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *p) {
63 if (!p)
64 return NULL;
65
66 assert(p->n_ref > 0);
67 p->n_ref++;
68
69 return p;
70}
71
72_public_ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *p) {
73 if (!p)
74 return NULL;
75
76 assert(p->n_ref > 0);
77 p->n_ref--;
78
79 if (p->n_ref > 0)
80 return NULL;
81
82 return mfree(p);
83}
84
85_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
86 unsigned char prefixlen) {
87 assert_return(p, -EINVAL);
88 assert_return(in6_addr, -EINVAL);
89
90 if (prefixlen < 3 || prefixlen > 128)
91 return -EINVAL;
92
93 if (prefixlen > 64)
94 /* unusual but allowed, log it */
95 log_radv("Unusual prefix length %d greater than 64", prefixlen);
96
97 p->opt.in6_addr = *in6_addr;
98 p->opt.prefixlen = prefixlen;
99
100 return 0;
101}
102
103_public_ int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) {
104 assert_return(p, -EINVAL);
105
106 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, onlink);
107
108 return 0;
109}
110
111_public_ int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
112 int address_autoconfiguration) {
113 assert_return(p, -EINVAL);
114
115 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, address_autoconfiguration);
116
117 return 0;
118}
119
120_public_ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p,
121 uint32_t valid_lifetime) {
122 assert_return(p, -EINVAL);
123
124 p->opt.valid_lifetime = htobe32(valid_lifetime);
125
126 return 0;
127}
128
129_public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p,
130 uint32_t preferred_lifetime) {
131 assert_return(p, -EINVAL);
132
133 p->opt.preferred_lifetime = htobe32(preferred_lifetime);
134
135 return 0;
136}