]>
Commit | Line | Data |
---|---|---|
a032b68d | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
a10f5d05 MB |
2 | |
3 | #include "bus-message-util.h" | |
4 | ||
5 | #include "resolve-util.h" | |
6 | ||
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) | |
8b3d4ff0 | 20 | return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); |
a10f5d05 MB |
21 | |
22 | *ret = ifindex; | |
23 | ||
24 | return 0; | |
25 | } | |
26 | ||
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 | ||
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)) | |
8b3d4ff0 | 65 | return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); |
a10f5d05 MB |
66 | |
67 | if (ret_family) | |
68 | *ret_family = family; | |
69 | if (ret_addr) | |
70 | memcpy(ret_addr, d, sz); | |
71 | return 0; | |
72 | } | |
73 | ||
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 | ||
8b3d4ff0 MB |
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 | } | |
a10f5d05 MB |
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 | ||
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; | |
8b3d4ff0 | 140 | size_t n = 0; |
a10f5d05 MB |
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 | ||
8b3d4ff0 | 163 | if (!GREEDY_REALLOC(dns, n+1)) { |
a10f5d05 MB |
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 | } |