1 /* 2 * Copyright 2015 Steven Barth <steven at midlink.org> 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 #include <stdio.h> 19 #include <signal.h> 20 #include <string.h> 21 #include <stdlib.h> 22 #include <netdb.h> 23 #include <net/if.h> 24 #include <unistd.h> 25 26 #include <libubox/uloop.h> 27 #include <libubox/blobmsg.h> 28 29 #include "omcproxy.h" 30 #include "proxy.h" 31 32 int log_level = LOG_WARNING; 33 34 35 enum { 36 PROXY_ATTR_SOURCE, 37 PROXY_ATTR_SCOPE, 38 PROXY_ATTR_DEST, 39 PROXY_ATTR_MAX, 40 }; 41 42 static struct blobmsg_policy proxy_policy[PROXY_ATTR_MAX] = { 43 [PROXY_ATTR_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING }, 44 [PROXY_ATTR_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING }, 45 [PROXY_ATTR_DEST] = { .name = "dest", .type = BLOBMSG_TYPE_ARRAY }, 46 }; 47 48 static int handle_proxy_set(void *data, size_t len) 49 { 50 struct blob_attr *tb[PROXY_ATTR_MAX], *c; 51 blobmsg_parse(proxy_policy, PROXY_ATTR_MAX, tb, data, len); 52 53 const char *name = ((c = tb[PROXY_ATTR_SOURCE])) ? blobmsg_get_string(c) : NULL; 54 int uplink = 0; 55 int downlinks[32] = {0}; 56 size_t downlinks_cnt = 0; 57 enum proxy_flags flags = 0; 58 59 if (!name) 60 return -EINVAL; 61 62 if (!(uplink = if_nametoindex(name))) { 63 L_WARN("%s(%s): %s", __FUNCTION__, name, strerror(errno)); 64 return -errno; 65 } 66 67 if ((c = tb[PROXY_ATTR_SCOPE])) { 68 const char *scope = blobmsg_get_string(c); 69 if (!strcmp(scope, "global")) 70 flags = PROXY_GLOBAL; 71 else if (!strcmp(scope, "organization")) 72 flags = PROXY_ORGLOCAL; 73 else if (!strcmp(scope, "site")) 74 flags = PROXY_SITELOCAL; 75 else if (!strcmp(scope, "admin")) 76 flags = PROXY_ADMINLOCAL; 77 else if (!strcmp(scope, "realm")) 78 flags = PROXY_REALMLOCAL; 79 80 if (!flags) { 81 L_WARN("%s(%s): invalid scope (%s)", __FUNCTION__, name, scope); 82 return -EINVAL; 83 } 84 } 85 86 if ((c = tb[PROXY_ATTR_DEST])) { 87 struct blob_attr *d; 88 unsigned rem; 89 blobmsg_for_each_attr(d, c, rem) { 90 if (downlinks_cnt >= 32) { 91 L_WARN("%s(%s): maximum number of destinations exceeded", __FUNCTION__, name); 92 return -EINVAL; 93 } 94 95 const char *n = blobmsg_type(d) == BLOBMSG_TYPE_STRING ? blobmsg_get_string(d) : ""; 96 if (!(downlinks[downlinks_cnt++] = if_nametoindex(n))) { 97 L_WARN("%s(%s): %s (%s)", __FUNCTION__, name, strerror(errno), blobmsg_get_string(d)); 98 return -errno; 99 } 100 } 101 } 102 103 return proxy_set(uplink, downlinks, downlinks_cnt, flags); 104 } 105 106 static void handle_signal(__unused int signal) 107 { 108 uloop_end(); 109 } 110 111 static void usage(const char *arg) { 112 fprintf(stderr, "Usage: %s [options] <proxy1> [<proxy2>] [...]\n" 113 "\nProxy examples:\n" 114 "eth1,eth2\n" 115 "eth1,eth2,eth3,scope=organization\n" 116 "\nProxy options (each option may only occur once):\n" 117 " <interface> interfaces to proxy (first is uplink)\n" 118 " scope=<scope> minimum multicast scope to proxy\n" 119 " [global,organization,site,admin,realm] (default: global)\n" 120 "\nOptions:\n" 121 " -v verbose logging\n" 122 " -h show this help\n", 123 arg); 124 } 125 126 int main(int argc, char **argv) { 127 signal(SIGINT, handle_signal); 128 signal(SIGTERM, handle_signal); 129 signal(SIGHUP, SIG_IGN); 130 signal(SIGPIPE, SIG_IGN); 131 openlog("omcproxy", LOG_PERROR, LOG_DAEMON); 132 133 if (getuid()) { 134 L_ERR("must be run as root!"); 135 return 2; 136 } 137 138 uloop_init(); 139 bool start = true; 140 141 for (ssize_t i = 1; i < argc; ++i) { 142 const char *source = NULL; 143 const char *scope = NULL; 144 struct blob_buf b = {NULL, NULL, 0, NULL}; 145 146 if (!strcmp(argv[i], "-h")) { 147 usage(argv[0]); 148 return 1; 149 } else if (!strncmp(argv[i], "-v", 2)) { 150 if ((log_level = atoi(&argv[i][2])) <= 0) 151 log_level = 7; 152 continue; 153 } 154 155 156 blob_buf_init(&b, 0); 157 158 void *k = blobmsg_open_array(&b, "dest"); 159 for (char *c = strtok(argv[i], ","); c; c = strtok(NULL, ",")) { 160 if (!strncmp(c, "scope=", 6)) { 161 scope = &c[6]; 162 } else if (!source) { 163 source = c; 164 } else { 165 blobmsg_add_string(&b, NULL, c); 166 } 167 } 168 blobmsg_close_array(&b, k); 169 170 if (source) 171 blobmsg_add_string(&b, "source", source); 172 173 if (scope) 174 blobmsg_add_string(&b, "scope", scope); 175 176 if (handle_proxy_set(blob_data(b.head), blob_len(b.head))) { 177 fprintf(stderr, "failed to setup proxy: %s\n", argv[i]); 178 start = false; 179 } 180 181 blob_buf_free(&b); 182 } 183 184 if (argc < 2) { 185 usage(argv[0]); 186 start = false; 187 } 188 189 if (start) 190 uloop_run(); 191 192 proxy_update(true); 193 proxy_flush(); 194 195 uloop_done(); 196 return 0; 197 } 198
This page was automatically generated by LXR 0.3.1. • OpenWrt