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) )
109 printf("IFUP[%s]\n", net->ifname);
110 fwd_update_cidr(addr_old, addr_new);
111 fwd_ipt_addif(h, net->name);
113 else if( fwd_empty_cidr(addr_new) && !fwd_empty_cidr(addr_old) )
115 printf("IFDOWN[%s]\n", net->ifname);
116 fwd_update_cidr(addr_old, NULL);
117 fwd_ipt_delif(h, net->name);
119 else if( ! fwd_equal_cidr(addr_old, addr_new) )
121 printf("IFCHANGE[%s]\n", net->ifname);
122 fwd_update_cidr(addr_old, addr_new);
123 fwd_ipt_chgif(h, net->name);
128 fwd_free_addrs(addrs);
132 if( (unix_client = fwd_ipc_accept(h->unix_socket)) > -1 )
134 struct fwd_ipc_msg msg;
135 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
137 while( fwd_ipc_recvmsg(unix_client, &msg, sizeof(struct fwd_ipc_msg)) > 0 )
139 fwd_log_info("Got message [%i]", msg.type);
144 fwd_log_info("Flushing rules ...");
145 fwd_ipt_clear_ruleset(h);
146 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
150 fwd_log_info("Building rules ...");
151 fwd_ipt_clear_ruleset(h);
152 fwd_ipt_build_ruleset(h);
154 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
158 if( (data = fwd_read_config(h)) != NULL )
160 fwd_log_info("Flushing rules ...");
161 fwd_ipt_clear_ruleset(h);
162 fwd_free_config(h->conf);
164 fwd_log_info("Building rules ...");
165 fwd_ipt_build_ruleset(h);
167 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
171 fwd_log_err("Cannot reload configuration!");
172 fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
178 if( strlen(msg.data.network) > 0 )
180 fwd_ipt_delif(h, msg.data.network);
182 if( msg.type == FWD_IPC_ADDIF )
183 fwd_ipt_addif(h, msg.data.network);
185 fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
189 fwd_log_err("No network name provided!");
190 fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
200 fwd_ipc_shutdown(unix_client);
208 fwd_ipt_clear_ruleset(h);
210 close(h->rtnl_socket);
211 fwd_free_config(h->conf);
217 static void fwd_client_usage(const char *msg)
223 " Flush all rules in the firewall and reset policy\n\n"
225 " Rebuild firewall rules\n\n"
227 " Reload configuration and rebuild firewall rules\n\n"
228 " fw addif {network}\n"
229 " Add rules for given network\n\n"
230 " fw delif {network}\n"
231 " Remove rules for given network\n\n"
238 static int fwd_client_main(int argc, const char *argv[])
241 struct fwd_ipc_msg msg;
242 enum fwd_ipc_msgtype type;
245 fwd_client_usage("Command required");
247 if( (unix_server = fwd_ipc_connect()) < 0 )
248 fwd_fatal("Cannot connect to server instance (%m)");
251 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
253 if( !strcmp(argv[1], "flush") )
254 type = FWD_IPC_FLUSH;
256 else if( !strcmp(argv[1], "build") )
257 type = FWD_IPC_BUILD;
259 else if( !strcmp(argv[1], "reload") )
260 type = FWD_IPC_RELOAD;
262 else if( !strcmp(argv[1], "addif") || !strcmp(argv[1], "delif") )
265 fwd_client_usage("The command requires a parameter.");
267 type = strcmp(argv[1], "addif") ? FWD_IPC_DELIF : FWD_IPC_ADDIF;
268 strncpy(msg.data.network, argv[2], sizeof(msg.data.network));
272 fwd_client_usage("Invalid command given.");
275 fwd_ipc_sendmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg));
277 memset(&msg, 0, sizeof(struct fwd_ipc_msg));
279 while( fwd_ipc_recvmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg)) == 0 )
289 printf("The server reported an error, check logread!\n");
293 fwd_fatal("Unexpected response type %i", msg.type);
296 fwd_ipc_shutdown(unix_server);
301 int main(int argc, const char *argv[])
303 if( strstr(argv[0], "fwd") )
304 return fwd_server_main(argc, argv);
306 return fwd_client_main(argc, argv);