2 * fwd - OpenWrt firewall daemon - main part
4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
6 * The fwd program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * The fwd program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with the fwd program. If not, see http://www.gnu.org/licenses/.
22 #include "fwd_rules.h"
23 #include "fwd_config.h"
24 #include "fwd_xtables.h"
26 #include "fwd_utils.h"
29 static void fwd_foreach_network(
31 void (*cb)(struct fwd_handle *h, struct fwd_network *net)
33 struct fwd_data *data;
34 struct fwd_network *net;
36 for( data = h->conf; data; data = data->next )
38 if( data->type != FWD_S_ZONE )
41 for( net = data->section.zone.networks; net; net = net->next )
46 static void fwd_addif_all_cb(struct fwd_handle *h, struct fwd_network *net)
48 fwd_ipt_addif(h, net->name);
51 static void fwd_delif_all_cb(struct fwd_handle *h, struct fwd_network *net)
53 fwd_ipt_delif(h, net->name);
56 #define fwd_addif_all(h) fwd_foreach_network(h, fwd_addif_all_cb)
57 #define fwd_delif_all(h) fwd_foreach_network(h, fwd_delif_all_cb)
60 static int fwd_server_main(int argc, const char *argv[])
63 struct fwd_network *net;
64 struct fwd_addr *addrs;
65 struct fwd_data *data;
66 struct fwd_cidr *addr_old, *addr_new;
70 sa.sa_handler = SIG_IGN;
71 sigaction(SIGPIPE, &sa, NULL);
74 fwd_fatal("Need root permissions!");
76 if( !(h = fwd_alloc_ptr(struct fwd_handle)) )
77 fwd_fatal("Out of memory");
79 if( (h->rtnl_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1 )
80 fwd_fatal("Failed to create AF_NETLINK socket (%m)");
82 if( (h->unix_socket = fwd_ipc_listen()) == -1 )
83 fwd_fatal("Failed to create AF_UNIX socket (%m)");
85 if( !(h->conf = fwd_read_config(h)) )
86 fwd_fatal("Failed to read configuration");
90 fwd_ipt_build_ruleset(h);
95 if( (addrs = fwd_get_addrs(h->rtnl_socket, AF_INET)) != NULL )
97 for( data = h->conf; data; data = data->next )
99 if( data->type != FWD_S_ZONE )
102 for( net = data->section.zone.networks; net; net = net->next )
104 addr_new = fwd_lookup_addr(addrs, net->ifname);
105 addr_old = net->addr;
107 if( !fwd_empty_cidr(addr_new) && fwd_empty_cidr(addr_old) )
110 "Interface %s brought up - adding rules",
114 fwd_update_cidr(addr_old, addr_new);
115 fwd_ipt_addif(h, net->name);
117 else if( fwd_empty_cidr(addr_new) && !fwd_empty_cidr(addr_old) )
120 "Interface %s went down - removing rules",
124 fwd_update_cidr(addr_old, NULL);
125 fwd_ipt_delif(h, net->name);
127 else if( ! fwd_equal_cidr(addr_old, addr_new) )
130 "Interface %s changed IP - rebuilding rules",
134 fwd_update_cidr(addr_old, addr_new);
135 fwd_ipt_chgif(h, net->name);
140 fwd_free_addrs(addrs);
144 if( (unix_client = fwd_ipc_accept(h->unix_socket)) > -1 )
146 struct fwd_ipc_msg msg;
147 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
149 while( fwd_ipc_recvmsg(unix_client, &msg, sizeof(struct fwd_ipc_msg)) > 0 )
151 fwd_log_info("Got message [%i]", msg.type);
156 fwd_log_info("Flushing rules ...");
157 fwd_ipt_clear_ruleset(h);
158 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
162 fwd_log_info("Building rules ...");
163 fwd_ipt_clear_ruleset(h);
164 fwd_ipt_build_ruleset(h);
166 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
170 if( (data = fwd_read_config(h)) != NULL )
172 fwd_log_info("Flushing rules ...");
173 fwd_ipt_clear_ruleset(h);
174 fwd_free_config(h->conf);
176 fwd_log_info("Building rules ...");
177 fwd_ipt_build_ruleset(h);
179 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
183 fwd_log_err("Cannot reload configuration!");
184 fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
190 if( strlen(msg.data.network) > 0 )
192 fwd_ipt_delif(h, msg.data.network);
194 if( msg.type == FWD_IPC_ADDIF )
195 fwd_ipt_addif(h, msg.data.network);
197 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
201 fwd_log_err("No network name provided!");
202 fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
212 fwd_ipc_shutdown(unix_client);
220 fwd_ipt_clear_ruleset(h);
222 close(h->rtnl_socket);
223 fwd_free_config(h->conf);
229 static void fwd_client_usage(const char *msg)
235 " Flush all rules in the firewall and reset policy\n\n"
237 " Rebuild firewall rules\n\n"
239 " Reload configuration and rebuild firewall rules\n\n"
240 " fw addif {network}\n"
241 " Add rules for given network\n\n"
242 " fw delif {network}\n"
243 " Remove rules for given network\n\n"
250 static int fwd_client_main(int argc, const char *argv[])
253 struct fwd_ipc_msg msg;
254 enum fwd_ipc_msgtype type;
257 fwd_client_usage("Command required");
259 if( (unix_server = fwd_ipc_connect()) < 0 )
260 fwd_fatal("Cannot connect to server instance (%m)");
263 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
265 if( !strcmp(argv[1], "flush") )
266 type = FWD_IPC_FLUSH;
268 else if( !strcmp(argv[1], "build") )
269 type = FWD_IPC_BUILD;
271 else if( !strcmp(argv[1], "reload") )
272 type = FWD_IPC_RELOAD;
274 else if( !strcmp(argv[1], "addif") || !strcmp(argv[1], "delif") )
277 fwd_client_usage("The command requires a parameter.");
279 type = strcmp(argv[1], "addif") ? FWD_IPC_DELIF : FWD_IPC_ADDIF;
280 strncpy(msg.data.network, argv[2], sizeof(msg.data.network));
284 fwd_client_usage("Invalid command given.");
287 fwd_ipc_sendmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg));
289 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
291 while( fwd_ipc_recvmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg)) == 0 )
301 printf("The server reported an error, check logread!\n");
305 fwd_fatal("Unexpected response type %i", msg.type);
308 fwd_ipc_shutdown(unix_server);
313 int main(int argc, const char *argv[])
315 if( strstr(argv[0], "fwd") )
316 return fwd_server_main(argc, argv);
318 return fwd_client_main(argc, argv);