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
);