• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/omcproxy/src/omcproxy.c

  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