]> git.ipfire.org Git - people/ms/network.git/blob - src/networkctl/port.c
Makefile: Fix typo in localstatedir
[people/ms/network.git] / src / networkctl / port.c
1 /*#############################################################################
2 # #
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <limits.h>
22 #include <stdlib.h>
23
24 #include <systemd/sd-bus.h>
25
26 #include "../networkd/json.h"
27 #include "../networkd/string.h"
28 #include "command.h"
29 #include "port.h"
30 #include "terminal.h"
31
32 typedef int (*networkctl_port_walk_callback)
33 (sd_bus* bus, const char* path, const char* name, void* data);
34
35 static int networkctl_port_walk(sd_bus* bus,
36 networkctl_port_walk_callback callback, void* data) {
37 sd_bus_message* reply = NULL;
38 sd_bus_error error = SD_BUS_ERROR_NULL;
39 int r;
40
41 // Call Listports
42 r = sd_bus_call_method(bus, "org.ipfire.network1", "/org/ipfire/network1",
43 "org.ipfire.network1", "ListPorts", &error, &reply, "");
44 if (r < 0) {
45 fprintf(stderr, "ListPorts call failed: %m\n");
46 goto ERROR;
47 }
48
49 const char* name = NULL;
50 const char* path = NULL;
51
52 // Open the container
53 r = sd_bus_message_enter_container(reply, 'a', "(so)");
54 if (r < 0) {
55 fprintf(stderr, "Could not open container: %m\n");
56 goto ERROR;
57 }
58
59 // Iterate over all ports
60 for (;;) {
61 r = sd_bus_message_read(reply, "(so)", &name, &path);
62 if (r < 0)
63 goto ERROR;
64
65 // Break if we reached the end of the container
66 if (r == 0)
67 break;
68
69 // Call the callback
70 r = callback(bus, path, name, data);
71 if (r)
72 goto ERROR;
73 }
74
75 // Close the container
76 sd_bus_message_exit_container(reply);
77
78 ERROR:
79 if (reply)
80 sd_bus_message_unref(reply);
81 sd_bus_error_free(&error);
82
83 return r;
84 }
85
86 static int networkctl_port_describe(sd_bus* bus, const char* name, char** text) {
87 sd_bus_message* reply = NULL;
88 sd_bus_error error = SD_BUS_ERROR_NULL;
89 char path[PATH_MAX];
90 const char* t = NULL;
91 int r;
92
93 // Check input
94 if (!name || !text)
95 return -EINVAL;
96
97 // Make port path
98 r = nw_string_format(path, "/org/ipfire/network1/port/%s", name);
99 if (r < 0)
100 goto ERROR;
101
102 // Call Describe
103 r = sd_bus_call_method(bus, "org.ipfire.network1", path,
104 "org.ipfire.network1.Port", "Describe", &error, &reply, "");
105 if (r < 0) {
106 fprintf(stderr, "Describe() call failed: %m\n");
107 goto ERROR;
108 }
109
110 // Read the text
111 r = sd_bus_message_read(reply, "s", &t);
112 if (r < 0) {
113 fprintf(stderr, "Could not parse bus message: %s\n", strerror(-r));
114 goto ERROR;
115 }
116
117 // Copy text to heap
118 *text = strdup(t);
119 if (!*text)
120 r = -errno;
121
122 ERROR:
123 if (reply)
124 sd_bus_message_unref(reply);
125
126 return r;
127 }
128
129 // Dump
130
131 static int networkctl_port_dump(sd_bus* bus, int argc, char* argv[]) {
132 char* text = NULL;
133 int r;
134
135 if (argc < 1) {
136 fprintf(stderr, "Port required\n");
137 return -EINVAL;
138 }
139
140 // Describe the port
141 r = networkctl_port_describe(bus, argv[0], &text);
142 if (r < 0)
143 return r;
144
145 // Print the text
146 printf("%s\n", text);
147
148 if (text)
149 free(text);
150
151 return 0;
152 }
153
154 // List
155
156 static int __networkctl_port_list(sd_bus* bus, const char* path, const char* name, void* data) {
157 printf("%s\n", name);
158
159 return 0;
160 }
161
162 static int networkctl_port_list(sd_bus* bus, int argc, char* argv[]) {
163 return networkctl_port_walk(bus, __networkctl_port_list, NULL);
164 }
165
166 // Show
167
168 #define SHOW_LINE " %-12s : %s\n"
169
170 static int __networkctl_port_show(sd_bus* bus, const char* path, const char* name, void* data) {
171 struct json_object* object = NULL;
172 enum json_tokener_error json_error;
173 char* describe = NULL;
174 int r;
175
176 // Describe this port
177 r = networkctl_port_describe(bus, name, &describe);
178 if (r < 0)
179 goto ERROR;
180
181 // Parse JSON
182 object = json_tokener_parse_verbose(describe, &json_error);
183 if (!object) {
184 fprintf(stderr, "Could not parse port %s: %s\n",
185 name, json_tokener_error_desc(json_error));
186 return -EINVAL;
187 }
188
189 // Show headline
190 printf("Port %s%s%s\n", color_highlight(), name, color_reset());
191
192 // Show type
193 const char* type = json_object_fetch_string(object, "Type");
194 if (type)
195 printf(SHOW_LINE, "Type", type);
196
197 // Show address
198 const char* address = json_object_fetch_string(object, "Address");
199 if (address)
200 printf(SHOW_LINE, "Address", address);
201
202 // Show an empty line at the end
203 printf("\n");
204
205 // Success!
206 r = 0;
207
208 ERROR:
209 if (describe)
210 free(describe);
211 if (object)
212 json_object_unref(object);
213
214 return r;
215 }
216
217 static int networkctl_port_show(sd_bus* bus, int argc, char* argv[]) {
218 switch (argc) {
219 case 0:
220 return networkctl_port_walk(bus, __networkctl_port_show, NULL);
221
222 case 1:
223 return __networkctl_port_show(bus, NULL, argv[0], NULL);
224
225 default:
226 fprintf(stderr, "Too many arguments\n");
227 return 1;
228 }
229 }
230
231 int networkctl_port(sd_bus* bus, int argc, char* argv[]) {
232 static const struct command commands[] = {
233 { "dump", 0, networkctl_port_dump },
234 { "list", 0, networkctl_port_list },
235 { "show", 0, networkctl_port_show },
236 { NULL },
237 };
238
239 return command_dispatch(bus, commands, argc, argv);
240 }