]>
Commit | Line | Data |
---|---|---|
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 |
7 | int 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 | ||
26 | int 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 | |
54 | static 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 | ||
109 | int 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 | ||
156 | clear: | |
157 | for (size_t i = 0; i < n; i++) | |
158 | in_addr_full_free(dns[i]); | |
159 | free(dns); | |
160 | ||
161 | return r; | |
162 | } |