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