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 enum { 33 PROXY_ATTR_SOURCE, 34 PROXY_ATTR_SCOPE, 35 PROXY_ATTR_DEST, 36 PROXY_ATTR_MAX, 37 }; 38 39 static struct blobmsg_policy proxy_policy[PROXY_ATTR_MAX] = { 40 [PROXY_ATTR_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING }, 41 [PROXY_ATTR_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING }, 42 [PROXY_ATTR_DEST] = { .name = "dest", .type = BLOBMSG_TYPE_ARRAY }, 43 }; 44 45 static int handle_proxy_set(void *data, size_t len) 46 { 47 struct blob_attr *tb[PROXY_ATTR_MAX], *c; 48 blobmsg_parse(proxy_policy, PROXY_ATTR_MAX, tb, data, len); 49 50 const char *name = ((c = tb[PROXY_ATTR_SOURCE])) ? blobmsg_get_string(c) : NULL; 51 int uplink = 0; 52 int downlinks[32] = {0}; 53 size_t downlinks_cnt = 0; 54 enum proxy_flags flags = 0; 55 56 if (!name) 57 return -EINVAL; 58 59 if (!(uplink = if_nametoindex(name))) { 60 L_WARN("%s(%s): %s", __FUNCTION__, name, strerror(errno)); 61 return -errno; 62 } 63 64 if ((c = tb[PROXY_ATTR_SCOPE])) { 65 const char *scope = blobmsg_get_string(c); 66 if (!strcmp(scope, "global")) 67 flags = PROXY_GLOBAL; 68 else if (!strcmp(scope, "organization")) 69 flags = PROXY_ORGLOCAL; 70 else if (!strcmp(scope, "site")) 71 flags = PROXY_SITELOCAL; 72 else if (!strcmp(scope, "admin")) 73 flags = PROXY_ADMINLOCAL; 74 else if (!strcmp(scope, "realm")) 75 flags = PROXY_REALMLOCAL; 76 77 if (!flags) { 78 L_WARN("%s(%s): invalid scope (%s)", __FUNCTION__, name, scope); 79 return -EINVAL; 80 } 81 } 82 83 if ((c = tb[PROXY_ATTR_DEST])) { 84 struct blob_attr *d; 85 unsigned rem; 86 blobmsg_for_each_attr(d, c, rem) { 87 if (downlinks_cnt >= 32) { 88 L_WARN("%s(%s): maximum number of destinations exceeded", __FUNCTION__, name); 89 return -EINVAL; 90 } 91 92 const char *n = blobmsg_type(d) == BLOBMSG_TYPE_STRING ? blobmsg_get_string(d) : ""; 93 if (!(downlinks[downlinks_cnt++] = if_nametoindex(n))) { 94 L_WARN("%s(%s): %s (%s)", __FUNCTION__, name, strerror(errno), blobmsg_get_string(d)); 95 return -errno; 96 } 97 } 98 } 99 100 return proxy_set(uplink, downlinks, downlinks_cnt, flags); 101 } 102 103 static void handle_signal(__unused int signal) 104 { 105 uloop_end(); 106 } 107 108 static void usage(const char *arg) { 109 fprintf(stderr, "Usage: %s [options] <proxy1> [<proxy2>] [...]\n" 110 "\nProxy examples:\n" 111 "eth1,eth2\n" 112 "eth1,eth2,eth3,scope=organization\n" 113 "\nProxy options (each option may only occur once):\n" 114 " <interface> interfaces to proxy (first is uplink)\n" 115 " scope=<scope> minimum multicast scope to proxy\n" 116 " [global,organization,site,admin,realm] (default: global)\n" 117 "\nOptions:\n" 118 " -v verbose logging\n" 119 " -h show this help\n", 120 arg); 121 } 122 123 int main(int argc, char **argv) { 124 signal(SIGINT, handle_signal); 125 signal(SIGTERM, handle_signal); 126 signal(SIGHUP, SIG_IGN); 127 signal(SIGPIPE, SIG_IGN); 128 openlog("omcproxy", LOG_PERROR | LOG_PID, LOG_DAEMON); 129 setlogmask(LOG_UPTO(L_LEVEL)); 130 131 if (getuid()) { 132 L_ERR("must be run as root!"); 133 return 2; 134 } 135 136 uloop_init(); 137 bool start = true; 138 139 for (ssize_t i = 1; i < argc; ++i) { 140 const char *source = NULL; 141 const char *scope = NULL; 142 struct blob_buf b = {NULL, NULL, 0, NULL}; 143 144 if (!strcmp(argv[i], "-h")) { 145 usage(argv[0]); 146 return 1; 147 } else if (!strncmp(argv[i], "-v", 2)) { 148 int log_level; 149 if ((log_level = atoi(&argv[i][2])) <= 0) 150 log_level = LOG_DEBUG; 151 setlogmask(LOG_UPTO(log_level)); 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