]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/bus-message-util.c
util: introduce bus_mesage_read_dns_servers()
[thirdparty/systemd.git] / src / shared / bus-message-util.c
CommitLineData
97600989
YW
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include "bus-message-util.h"
4
10d46204
YW
5#include "resolve-util.h"
6
97600989
YW
7int bus_message_read_family(sd_bus_message *message, sd_bus_error *error, int *ret) {
8 int family, r;
9
10 assert(message);
11 assert(ret);
12
13 assert_cc(sizeof(int) == sizeof(int32_t));
14
15 r = sd_bus_message_read(message, "i", &family);
16 if (r < 0)
17 return r;
18
19 if (!IN_SET(family, AF_INET, AF_INET6))
20 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
21
22 *ret = family;
23 return 0;
24}
25
26int bus_message_read_in_addr_auto(sd_bus_message *message, sd_bus_error *error, int *ret_family, union in_addr_union *ret_addr) {
27 int family, r;
28 const void *d;
29 size_t sz;
30
31 assert(message);
32
33 r = sd_bus_message_read(message, "i", &family);
34 if (r < 0)
35 return r;
36
37 r = sd_bus_message_read_array(message, 'y', &d, &sz);
38 if (r < 0)
39 return r;
40
41 if (!IN_SET(family, AF_INET, AF_INET6))
42 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
43
44 if (sz != FAMILY_ADDRESS_SIZE(family))
45 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
46
47 if (ret_family)
48 *ret_family = family;
49 if (ret_addr)
50 memcpy(ret_addr, d, sz);
51 return 0;
52}
10d46204
YW
53
54static int bus_message_read_dns_one(
55 sd_bus_message *message,
56 sd_bus_error *error,
57 bool extended,
58 int *ret_family,
59 union in_addr_union *ret_address,
60 uint16_t *ret_port,
61 const char **ret_server_name) {
62 const char *server_name = NULL;
63 union in_addr_union a;
64 uint16_t port = 0;
65 int family, r;
66
67 assert(message);
68 assert(ret_family);
69 assert(ret_address);
70 assert(ret_port);
71 assert(ret_server_name);
72
73 r = sd_bus_message_enter_container(message, 'r', extended ? "iayqs" : "iay");
74 if (r <= 0)
75 return r;
76
77 r = bus_message_read_in_addr_auto(message, error, &family, &a);
78 if (r < 0)
79 return r;
80
81 if (!dns_server_address_valid(family, &a))
82 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
83
84 if (extended) {
85 r = sd_bus_message_read(message, "q", &port);
86 if (r < 0)
87 return r;
88
89 if (IN_SET(port, 53, 853))
90 port = 0;
91
92 r = sd_bus_message_read(message, "s", &server_name);
93 if (r < 0)
94 return r;
95 }
96
97 r = sd_bus_message_exit_container(message);
98 if (r < 0)
99 return r;
100
101 *ret_family = family;
102 *ret_address = a;
103 *ret_port = port;
104 *ret_server_name = server_name;
105
106 return 1;
107}
108
109int bus_message_read_dns_servers(
110 sd_bus_message *message,
111 sd_bus_error *error,
112 bool extended,
113 struct in_addr_full ***ret_dns,
114 size_t *ret_n_dns) {
115
116 struct in_addr_full **dns = NULL;
117 size_t n = 0, allocated = 0;
118 int r;
119
120 assert(message);
121 assert(ret_dns);
122 assert(ret_n_dns);
123
124 r = sd_bus_message_enter_container(message, 'a', extended ? "(iayqs)" : "(iay)");
125 if (r < 0)
126 return r;
127
128 for (;;) {
129 const char *server_name;
130 union in_addr_union a;
131 uint16_t port;
132 int family;
133
134 r = bus_message_read_dns_one(message, error, extended, &family, &a, &port, &server_name);
135 if (r < 0)
136 goto clear;
137 if (r == 0)
138 break;
139
140 if (!GREEDY_REALLOC(dns, allocated, n+1)) {
141 r = -ENOMEM;
142 goto clear;
143 }
144
145 r = in_addr_full_new(family, &a, port, 0, server_name, dns + n);
146 if (r < 0)
147 goto clear;
148
149 n++;
150 }
151
152 *ret_dns = TAKE_PTR(dns);
153 *ret_n_dns = n;
154 return 0;
155
156clear:
157 for (size_t i = 0; i < n; i++)
158 in_addr_full_free(dns[i]);
159 free(dns);
160
161 return r;
162}