1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
9 static struct ubus_auto_conn conn
;
10 static struct blob_buf b
;
13 ubus_network_add(struct ubus_context
*ctx
, struct ubus_object
*obj
,
14 struct ubus_request_data
*req
, const char *method
,
15 struct blob_attr
*msg
)
17 struct blob_attr
*name
;
19 blobmsg_parse(&network_policy
[NETWORK_ATTR_NAME
], 1, &name
,
20 blobmsg_data(msg
), blobmsg_len(msg
));
23 return UBUS_STATUS_INVALID_ARGUMENT
;
25 if (unetd_network_add(blobmsg_get_string(name
), msg
))
26 return UBUS_STATUS_INVALID_ARGUMENT
;
33 ubus_network_del(struct ubus_context
*ctx
, struct ubus_object
*obj
,
34 struct ubus_request_data
*req
, const char *method
,
35 struct blob_attr
*msg
)
37 struct blob_attr
*name
;
39 blobmsg_parse(&network_policy
[NETWORK_ATTR_NAME
], 1, &name
,
40 blobmsg_data(msg
), blobmsg_len(msg
));
43 return UBUS_STATUS_INVALID_ARGUMENT
;
45 if (unetd_network_remove(blobmsg_get_string(name
)))
46 return UBUS_STATUS_NOT_FOUND
;
52 __network_dump(struct blob_buf
*buf
, struct network
*net
)
54 struct network_host
*local
= net
->net_config
.local_host
;
55 struct network_peer
*peer
;
59 blobmsg_add_field(buf
, BLOBMSG_TYPE_TABLE
, "config",
60 blobmsg_data(net
->config
.data
),
61 blobmsg_len(net
->config
.data
));
64 blobmsg_add_string(buf
, "local_host", network_host_name(local
));
66 c
= blobmsg_open_table(buf
, "peers");
67 vlist_for_each_element(&net
->peers
, peer
, node
) {
68 union network_endpoint
*ep
= &peer
->state
.endpoint
;
72 p
= blobmsg_open_table(buf
, network_peer_name(peer
));
73 blobmsg_add_u8(buf
, "connected", peer
->state
.connected
);
74 if (peer
->state
.connected
) {
75 str
= blobmsg_alloc_string_buffer(buf
, "endpoint",
76 INET6_ADDRSTRLEN
+ 7);
77 addr
= network_endpoint_addr(ep
, &len
);
78 inet_ntop(ep
->sa
.sa_family
, addr
, str
, INET6_ADDRSTRLEN
);
80 snprintf(str
+ len
, INET6_ADDRSTRLEN
+ 7 - len
, ":%d",
81 ntohs(ep
->in
.sin_port
));
82 blobmsg_add_string_buffer(buf
);
85 blobmsg_close_table(buf
, p
);
87 blobmsg_close_table(buf
, c
);
91 ubus_network_get(struct ubus_context
*ctx
, struct ubus_object
*obj
,
92 struct ubus_request_data
*req
, const char *method
,
93 struct blob_attr
*msg
)
95 struct blob_attr
*name
;
99 blobmsg_parse(&network_policy
[NETWORK_ATTR_NAME
], 1, &name
,
100 blobmsg_data(msg
), blobmsg_len(msg
));
102 blob_buf_init(&b
, 0);
104 net
= avl_find_element(&networks
, blobmsg_get_string(name
), net
, node
);
106 return UBUS_STATUS_NOT_FOUND
;
108 __network_dump(&b
, net
);
110 c
= blobmsg_open_table(&b
, "networks");
111 avl_for_each_element(&networks
, net
, node
) {
112 n
= blobmsg_open_table(&b
, network_name(net
));
113 __network_dump(&b
, net
);
114 blobmsg_close_table(&b
, n
);
116 blobmsg_close_table(&b
, c
);
119 ubus_send_reply(ctx
, req
, b
.head
);
125 SERVICE_ATTR_NETWORK
,
130 static const struct blobmsg_policy service_policy
[__SERVICE_ATTR_MAX
] = {
131 [SERVICE_ATTR_NETWORK
] = { "network", BLOBMSG_TYPE_STRING
},
132 [SERVICE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
137 ubus_service_get_network_members(struct blob_buf
*b
, struct network
*n
,
140 struct network_service
*s
;
143 s
= vlist_find(&n
->services
, name
, s
, node
);
147 for (i
= 0; i
< s
->n_members
; i
++) {
148 struct network_host
*host
= s
->members
[i
];
151 name
= blobmsg_alloc_string_buffer(b
, NULL
, INET6_ADDRSTRLEN
);
152 inet_ntop(AF_INET6
, &host
->peer
.local_addr
.in6
, name
, INET6_ADDRSTRLEN
);
153 blobmsg_add_string_buffer(b
);
159 ubus_service_get(struct ubus_context
*ctx
, struct ubus_object
*obj
,
160 struct ubus_request_data
*req
, const char *method
,
161 struct blob_attr
*msg
)
163 struct blob_attr
*tb
[__SERVICE_ATTR_MAX
];
164 struct blob_attr
*cur
;
165 struct network
*n
= NULL
;
169 blobmsg_parse(service_policy
, __SERVICE_ATTR_MAX
, tb
,
170 blobmsg_data(msg
), blobmsg_len(msg
));
172 if ((cur
= tb
[SERVICE_ATTR_NAME
]) != NULL
)
173 name
= blobmsg_get_string(cur
);
175 return UBUS_STATUS_INVALID_ARGUMENT
;
177 if ((cur
= tb
[SERVICE_ATTR_NETWORK
]) != NULL
) {
178 n
= avl_find_element(&networks
, blobmsg_get_string(cur
), n
, node
);
180 return UBUS_STATUS_INVALID_ARGUMENT
;
183 blob_buf_init(&b
, 0);
185 c
= blobmsg_open_array(&b
, "hosts");
187 ubus_service_get_network_members(&b
, n
, name
);
189 avl_for_each_element(&networks
, n
, node
)
190 ubus_service_get_network_members(&b
, n
, name
);
192 blobmsg_close_array(&b
, c
);
193 ubus_send_reply(ctx
, req
, b
.head
);
198 static const struct ubus_method unetd_methods
[] = {
199 UBUS_METHOD("network_add", ubus_network_add
, network_policy
),
200 UBUS_METHOD_MASK("network_del", ubus_network_del
, network_policy
,
201 (1 << NETWORK_ATTR_NAME
)),
202 UBUS_METHOD_MASK("network_get", ubus_network_get
, network_policy
,
203 (1 << NETWORK_ATTR_NAME
)),
204 UBUS_METHOD("service_get", ubus_service_get
, service_policy
),
207 static struct ubus_object_type unetd_object_type
=
208 UBUS_OBJECT_TYPE("unetd", unetd_methods
);
210 static struct ubus_object unetd_object
= {
212 .type
= &unetd_object_type
,
213 .methods
= unetd_methods
,
214 .n_methods
= ARRAY_SIZE(unetd_methods
),
218 ubus_connect_handler(struct ubus_context
*ctx
)
222 ret
= ubus_add_object(ctx
, &unetd_object
);
224 fprintf(stderr
, "Failed to add object: %s\n", ubus_strerror(ret
));
227 void unetd_ubus_netifd_update(struct blob_attr
*data
)
231 if (ubus_lookup_id(&conn
.ctx
, "network.interface", &id
))
234 ubus_invoke(&conn
.ctx
, id
, "notify_proto", data
, NULL
, NULL
, 5000);
237 void unetd_ubus_netifd_add_route(struct network
*net
, union network_endpoint
*ep
)
243 if (!net
->config
.interface
)
246 if (ubus_lookup_id(&conn
.ctx
, "network", &id
))
249 blob_buf_init(&b
, 0);
251 if (ep
->in
.sin_family
== AF_INET6
)
252 addr
= &ep
->in6
.sin6_addr
;
254 addr
= &ep
->in
.sin_addr
;
256 blobmsg_add_u8(&b
, "v6", ep
->in
.sin_family
== AF_INET6
);
257 buf
= blobmsg_alloc_string_buffer(&b
, "target", INET6_ADDRSTRLEN
);
258 inet_ntop(ep
->in
.sin_family
, addr
, buf
, INET6_ADDRSTRLEN
);
259 blobmsg_add_string_buffer(&b
);
260 blobmsg_add_string(&b
, "interface", net
->config
.interface
);
261 blobmsg_add_u8(&b
, "exclude", true);
263 ubus_invoke(&conn
.ctx
, id
, "add_host_route", b
.head
, NULL
, NULL
, -1);
266 void unetd_ubus_init(void)
268 conn
.cb
= ubus_connect_handler
;
269 ubus_auto_connect(&conn
);