1 /* 2 * firewall3 - 3rd OpenWrt UCI firewall implementation 3 * 4 * Copyright (C) 2013 Jo-Philipp Wich <jo@mein.io> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "ubus.h" 20 21 static struct blob_attr *interfaces = NULL; 22 static struct blob_attr *procd_data; 23 24 25 static void dump_cb(struct ubus_request *req, int type, struct blob_attr *msg) 26 { 27 static const struct blobmsg_policy policy = { "interface", BLOBMSG_TYPE_ARRAY }; 28 struct blob_attr *cur; 29 30 blobmsg_parse(&policy, 1, &cur, blob_data(msg), blob_len(msg)); 31 if (cur) 32 interfaces = blob_memdup(cur); 33 } 34 35 static void procd_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) 36 { 37 procd_data = blob_memdup(msg); 38 } 39 40 bool 41 fw3_ubus_connect(void) 42 { 43 bool status = false; 44 uint32_t id; 45 struct ubus_context *ctx = ubus_connect(NULL); 46 struct blob_buf b = { }; 47 48 blob_buf_init(&b, 0); 49 50 if (!ctx) 51 goto out; 52 53 if (ubus_lookup_id(ctx, "network.interface", &id)) 54 goto out; 55 56 if (ubus_invoke(ctx, id, "dump", b.head, dump_cb, NULL, 2000)) 57 goto out; 58 59 status = true; 60 61 if (ubus_lookup_id(ctx, "service", &id)) 62 goto out; 63 64 blobmsg_add_string(&b, "type", "firewall"); 65 ubus_invoke(ctx, id, "get_data", b.head, procd_data_cb, NULL, 2000); 66 67 out: 68 blob_buf_free(&b); 69 70 if (ctx) 71 ubus_free(ctx); 72 73 return status; 74 } 75 76 void 77 fw3_ubus_disconnect(void) 78 { 79 free(interfaces); 80 interfaces = NULL; 81 } 82 83 static struct fw3_address * 84 parse_subnet(enum fw3_family family, struct blob_attr *dict, int rem) 85 { 86 struct blob_attr *cur; 87 struct fw3_address *addr; 88 89 addr = calloc(1, sizeof(*addr)); 90 if (!addr) 91 return NULL; 92 93 addr->set = true; 94 addr->family = family; 95 96 __blob_for_each_attr(cur, dict, rem) 97 { 98 if (!strcmp(blobmsg_name(cur), "address")) 99 inet_pton(family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, 100 blobmsg_get_string(cur), &addr->address.v6); 101 102 else if (!strcmp(blobmsg_name(cur), "mask")) 103 fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6); 104 } 105 106 return addr; 107 } 108 109 static int 110 parse_subnets(struct list_head *head, enum fw3_family family, 111 struct blob_attr *list) 112 { 113 struct blob_attr *cur; 114 struct fw3_address *addr; 115 int rem, n = 0; 116 117 if (!list) 118 return 0; 119 120 rem = blobmsg_data_len(list); 121 122 __blob_for_each_attr(cur, blobmsg_data(list), rem) 123 { 124 addr = parse_subnet(family, blobmsg_data(cur), blobmsg_data_len(cur)); 125 126 if (addr) 127 { 128 list_add_tail(&addr->list, head); 129 n++; 130 } 131 } 132 133 return n; 134 } 135 136 struct fw3_device * 137 fw3_ubus_device(const char *net) 138 { 139 enum { 140 DEV_INTERFACE, 141 DEV_DEVICE, 142 DEV_L3_DEVICE, 143 __DEV_MAX 144 }; 145 static const struct blobmsg_policy policy[__DEV_MAX] = { 146 [DEV_INTERFACE] = { "interface", BLOBMSG_TYPE_STRING }, 147 [DEV_DEVICE] = { "device", BLOBMSG_TYPE_STRING }, 148 [DEV_L3_DEVICE] = { "l3_device", BLOBMSG_TYPE_STRING }, 149 }; 150 struct fw3_device *dev = NULL; 151 struct blob_attr *tb[__DEV_MAX]; 152 struct blob_attr *cur; 153 char *name = NULL; 154 int rem; 155 156 if (!net || !interfaces) 157 return NULL; 158 159 blobmsg_for_each_attr(cur, interfaces, rem) { 160 blobmsg_parse(policy, __DEV_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 161 if (!tb[DEV_INTERFACE] || 162 strcmp(blobmsg_data(tb[DEV_INTERFACE]), net) != 0) 163 continue; 164 165 if (tb[DEV_L3_DEVICE]) 166 name = blobmsg_data(tb[DEV_L3_DEVICE]); 167 else if (tb[DEV_DEVICE]) 168 name = blobmsg_data(tb[DEV_DEVICE]); 169 else 170 continue; 171 172 break; 173 } 174 175 if (!name) 176 return NULL; 177 178 dev = calloc(1, sizeof(*dev)); 179 180 if (!dev) 181 return NULL; 182 183 snprintf(dev->name, sizeof(dev->name), "%s", name); 184 dev->set = true; 185 186 return dev; 187 } 188 189 int 190 fw3_ubus_address(struct list_head *list, const char *net) 191 { 192 enum { 193 ADDR_INTERFACE, 194 ADDR_IPV4, 195 ADDR_IPV6, 196 ADDR_IPV6_PREFIX, 197 __ADDR_MAX 198 }; 199 static const struct blobmsg_policy policy[__ADDR_MAX] = { 200 [ADDR_INTERFACE] = { "interface", BLOBMSG_TYPE_STRING }, 201 [ADDR_IPV4] = { "ipv4-address", BLOBMSG_TYPE_ARRAY }, 202 [ADDR_IPV6] = { "ipv6-address", BLOBMSG_TYPE_ARRAY }, 203 [ADDR_IPV6_PREFIX] = { "ipv6-prefix-assignment", BLOBMSG_TYPE_ARRAY }, 204 }; 205 struct blob_attr *tb[__ADDR_MAX]; 206 struct blob_attr *cur; 207 int rem, n = 0; 208 209 if (!net || !interfaces) 210 return 0; 211 212 blobmsg_for_each_attr(cur, interfaces, rem) { 213 blobmsg_parse(policy, __ADDR_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 214 215 if (!tb[ADDR_INTERFACE] || 216 strcmp(blobmsg_data(tb[ADDR_INTERFACE]), net) != 0) 217 continue; 218 219 n += parse_subnets(list, FW3_FAMILY_V4, tb[ADDR_IPV4]); 220 n += parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6]); 221 n += parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6_PREFIX]); 222 } 223 224 return n; 225 } 226 227 void 228 fw3_ubus_zone_devices(struct fw3_zone *zone) 229 { 230 struct blob_attr *c, *cur, *dcur; 231 unsigned r, rem, drem; 232 const char *name; 233 bool matches; 234 235 blobmsg_for_each_attr(c, interfaces, r) { 236 name = NULL; 237 matches = false; 238 239 blobmsg_for_each_attr(cur, c, rem) { 240 if (!strcmp(blobmsg_name(cur), "interface")) 241 name = blobmsg_get_string(cur); 242 else if (!strcmp(blobmsg_name(cur), "data")) 243 blobmsg_for_each_attr(dcur, cur, drem) 244 if (!strcmp(blobmsg_name(dcur), "zone")) 245 matches = !strcmp(blobmsg_get_string(dcur), zone->name); 246 } 247 248 if (name && matches) 249 fw3_parse_device(&zone->networks, name, true); 250 } 251 } 252 253 static void fw3_ubus_rules_add(struct blob_buf *b, const char *service, 254 const char *instance, const char *device, 255 const struct blob_attr *rule, unsigned n) 256 { 257 void *k = blobmsg_open_table(b, ""); 258 struct blob_attr *ropt; 259 unsigned orem; 260 char *type = NULL, *name = NULL; 261 char comment[256]; 262 263 blobmsg_for_each_attr(ropt, rule, orem) { 264 if (!strcmp(blobmsg_name(ropt), "type")) 265 type = blobmsg_data(ropt); 266 else if (!strcmp(blobmsg_name(ropt), "name")) 267 name = blobmsg_data(ropt); 268 269 if (device && !strcmp(blobmsg_name(ropt), "device")) 270 device = blobmsg_get_string(ropt); 271 else if (strcmp(blobmsg_name(ropt), "name")) 272 blobmsg_add_blob(b, ropt); 273 } 274 275 if (!type || strcmp(type, "ipset")) { 276 if (instance) 277 snprintf(comment, sizeof(comment), "ubus:%s[%s] %s %d", 278 service, instance, type ? type : "rule", n); 279 else 280 snprintf(comment, sizeof(comment), "ubus:%s %s %d", 281 service, type ? type : "rule", n); 282 283 blobmsg_add_string(b, "name", comment); 284 } 285 else if (name) { 286 blobmsg_add_string(b, "name", name); 287 } 288 289 if (device) 290 blobmsg_add_string(b, "device", device); 291 292 blobmsg_close_table(b, k); 293 } 294 295 void 296 fw3_ubus_rules(struct blob_buf *b) 297 { 298 blob_buf_init(b, 0); 299 300 struct blob_attr *c, *cur, *dcur, *rule; 301 unsigned n, r, rem, drem, rrem; 302 303 blobmsg_for_each_attr(c, interfaces, r) { 304 const char *l3_device = NULL; 305 const char *iface_proto = "unknown"; 306 const char *iface_name = "unknown"; 307 struct blob_attr *data = NULL; 308 309 blobmsg_for_each_attr(cur, c, rem) { 310 if (!strcmp(blobmsg_name(cur), "l3_device")) 311 l3_device = blobmsg_get_string(cur); 312 else if (!strcmp(blobmsg_name(cur), "interface")) 313 iface_name = blobmsg_get_string(cur); 314 else if (!strcmp(blobmsg_name(cur), "proto")) 315 iface_proto = blobmsg_get_string(cur); 316 else if (!strcmp(blobmsg_name(cur), "data")) 317 data = cur; 318 } 319 320 if (!data || !l3_device) 321 continue; 322 323 blobmsg_for_each_attr(dcur, data, drem) { 324 if (strcmp(blobmsg_name(dcur), "firewall")) 325 continue; 326 327 n = 0; 328 329 blobmsg_for_each_attr(rule, dcur, rrem) 330 fw3_ubus_rules_add(b, iface_name, iface_proto, 331 l3_device, rule, n++); 332 } 333 } 334 335 if (!procd_data) 336 return; 337 338 /* service */ 339 blobmsg_for_each_attr(c, procd_data, r) { 340 if (!blobmsg_check_attr(c, true)) 341 continue; 342 343 /* instance */ 344 blobmsg_for_each_attr(cur, c, rem) { 345 if (!blobmsg_check_attr(cur, true)) 346 continue; 347 348 /* fw rules within the service itself */ 349 if (!strcmp(blobmsg_name(cur), "firewall")) { 350 n = 0; 351 352 blobmsg_for_each_attr(rule, cur, rrem) 353 fw3_ubus_rules_add(b, blobmsg_name(c), 354 NULL, NULL, rule, n++); 355 356 continue; 357 } 358 359 /* type */ 360 blobmsg_for_each_attr(dcur, cur, drem) { 361 if (!blobmsg_check_attr(dcur, true)) 362 continue; 363 364 if (strcmp(blobmsg_name(dcur), "firewall")) 365 continue; 366 367 n = 0; 368 369 blobmsg_for_each_attr(rule, dcur, rrem) 370 fw3_ubus_rules_add(b, blobmsg_name(c), 371 blobmsg_name(cur), NULL, rule, n++); 372 } 373 } 374 } 375 } 376
This page was automatically generated by LXR 0.3.1. • OpenWrt