olsrd: fix setting default interface config
[feed/routing.git] / olsrd / src / src / ubus.c
1 #include <stdbool.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <sys/select.h>
5
6 #include <libubox/blob.h>
7 #include <libubox/blobmsg.h>
8 #include <libubus.h>
9
10 #include <arpa/inet.h>
11 #include <net/if.h>
12 #include <netinet/in.h>
13 #include <sys/ioctl.h>
14 #include <sys/socket.h>
15
16 #include "defs.h"
17 #include "ifnet.h"
18 #include "interfaces.h"
19 #include "log.h"
20 #include "olsr.h"
21 #include "olsr_cfg.h"
22
23 #include "ubus.h"
24
25 #define MAX(a, b) ((a) > (b) ? (a) : (b))
26 #define MIN(a, b) ((a) < (b) ? (a) : (b))
27
28 // Shared state maintained throughout calls to handle ubus messages.
29 static struct ubus_context *shared_ctx;
30
31 enum { INTERFACE_IFNAME, __INTERFACE_MAX };
32
33 static const struct blobmsg_policy interface_policy[__INTERFACE_MAX] = {
34 [INTERFACE_IFNAME] = {"ifname", BLOBMSG_TYPE_STRING},
35 };
36
37 static int olsrd_ubus_add_interface(struct ubus_context *ctx_local,
38 struct ubus_object *obj,
39 struct ubus_request_data *req,
40 const char *method, struct blob_attr *msg) {
41 struct blob_attr *tb[__INTERFACE_MAX];
42 struct blob_buf b = {0};
43 int ret;
44 char *ifname;
45
46 blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg),
47 blob_len(msg));
48
49 if (!tb[INTERFACE_IFNAME])
50 return UBUS_STATUS_INVALID_ARGUMENT;
51
52 ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]);
53
54 struct interface_olsr *tmp = if_ifwithname(ifname);
55 if (tmp != NULL) {
56 return UBUS_STATUS_PERMISSION_DENIED;
57 }
58
59 struct olsr_if *temp;
60 for (temp = olsr_cnf->interfaces; temp != NULL; temp = temp->next) {
61 if (strcmp(temp->name, ifname) == 0)
62 return UBUS_STATUS_PERMISSION_DENIED;
63 }
64
65 struct olsr_if *tmp_ifs = olsr_create_olsrif(ifname, false);
66 tmp_ifs->cnf = olsr_malloc(sizeof(struct if_config_options),"Set default config");
67 *tmp_ifs->cnf = *olsr_cnf->interface_defaults;
68
69 blob_buf_init(&b, 0);
70 blobmsg_add_string(&b, "adding", ifname);
71
72 ret = ubus_send_reply(ctx_local, req, b.head);
73 if (ret)
74 olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n",
75 ubus_strerror(ret));
76
77 blob_buf_free(&b);
78
79 return ret;
80 }
81
82 static int olsrd_ubus_del_interface(struct ubus_context *ctx_local,
83 struct ubus_object *obj,
84 struct ubus_request_data *req,
85 const char *method, struct blob_attr *msg) {
86 struct blob_attr *tb[__INTERFACE_MAX];
87 struct blob_buf b = {0};
88 int ret;
89 char *ifname;
90 struct olsr_if *tmp_if, *del_if;
91
92 blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg),
93 blob_len(msg));
94
95 if (!tb[INTERFACE_IFNAME])
96 return UBUS_STATUS_INVALID_ARGUMENT;
97
98 ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]);
99
100 struct interface_olsr *tmp = if_ifwithname(ifname);
101
102 if (tmp != NULL) {
103
104 struct olsr_if *temp = olsr_cnf->interfaces, *prev;
105 if (temp != NULL && (strcmp(temp->name, ifname) == 0)) {
106 olsr_cnf->interfaces = temp->next;
107 olsr_remove_interface(temp);
108 goto send_reply;
109 }
110
111 while (temp != NULL && (strcmp(temp->name, ifname) != 0)) {
112 prev = temp;
113 temp = temp->next;
114 }
115
116 if (temp == NULL) {
117 goto send_reply;
118 }
119
120 prev->next = temp->next;
121 olsr_remove_interface(temp);
122 } else {
123 return UBUS_STATUS_PERMISSION_DENIED;
124 }
125
126 send_reply:
127
128 blob_buf_init(&b, 0);
129 blobmsg_add_string(&b, "deleting", ifname);
130
131 ret = ubus_send_reply(ctx_local, req, b.head);
132 if (ret)
133 olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n",
134 ubus_strerror(ret));
135
136 blob_buf_free(&b);
137
138 return ret;
139 }
140
141 // List of functions we expose via the ubus bus.
142 static const struct ubus_method olsrd_methods[] = {
143 UBUS_METHOD("add_interface", olsrd_ubus_add_interface, interface_policy),
144 UBUS_METHOD("del_interface", olsrd_ubus_del_interface, interface_policy),
145 };
146
147 // Definition of the ubus object type.
148 static struct ubus_object_type olsrd_object_type =
149 UBUS_OBJECT_TYPE("olsrd", olsrd_methods);
150
151 // Object we announce via the ubus bus.
152 static struct ubus_object olsrd_object = {
153 .name = "olsrd",
154 .type = &olsrd_object_type,
155 .methods = olsrd_methods,
156 .n_methods = ARRAY_SIZE(olsrd_methods),
157 };
158
159 // Registers handlers for olsrd methods in the global ubus context.
160 static bool ubus_init_object() {
161 int ret;
162
163 ret = ubus_add_object(shared_ctx, &olsrd_object);
164 if (ret) {
165 olsr_syslog(OLSR_LOG_ERR, "Failed to add object: %s\n",
166 ubus_strerror(ret));
167 return false;
168 }
169
170 return true;
171 }
172
173 // Initializes the global ubus context, connecting to the bus to be able to
174 // receive and send messages.
175 static bool olsrd_ubus_init(void) {
176 if (shared_ctx)
177 return true;
178
179 shared_ctx = ubus_connect(NULL);
180 if (!shared_ctx)
181 return false;
182
183 return true;
184 }
185
186 void olsrd_ubus_receive(fd_set *readfds) {
187 if (!shared_ctx)
188 return;
189 if (FD_ISSET(shared_ctx->sock.fd, readfds))
190 ubus_handle_event(shared_ctx);
191 }
192
193 int olsrd_ubus_add_read_sock(fd_set *readfds, int maxfd) {
194 if (!shared_ctx)
195 return maxfd;
196
197 FD_SET(shared_ctx->sock.fd, readfds);
198 return MAX(maxfd, shared_ctx->sock.fd + 1);
199 }
200
201 bool olsrd_add_ubus() {
202 if (!olsrd_ubus_init()) {
203 olsr_syslog(OLSR_LOG_ERR, "Failed to initialize ubus!\n");
204 return false;
205 }
206 if (!ubus_init_object()) {
207 olsr_syslog(OLSR_LOG_ERR, "Failed to add objects to ubus!\n");
208 return false;
209 }
210 return true;
211 }