8 #include <netinet/in.h>
12 #include "libsmooth.h"
17 struct keyvalue
*kv
= NULL
;
18 FILE *ifacefile
= NULL
;
20 char redif
[STRING_SIZE
];
21 char blueif
[STRING_SIZE
];
22 char orangeif
[STRING_SIZE
];
23 char enablered
[STRING_SIZE
] = "off";
24 char enableblue
[STRING_SIZE
] = "off";
25 char enableorange
[STRING_SIZE
] = "off";
28 char OVPNINPUT
[STRING_SIZE
] = "OVPNINPUT";
29 char OVPNBLOCK
[STRING_SIZE
] = "OVPNBLOCK";
30 char OVPNNAT
[STRING_SIZE
] = "OVPNNAT";
31 char WRAPPERVERSION
[STRING_SIZE
] = "ipfire-2.2.4";
33 struct connection_struct
{
34 char name
[STRING_SIZE
];
35 char type
[STRING_SIZE
];
36 char proto
[STRING_SIZE
];
37 char status
[STRING_SIZE
];
38 char local_subnet
[STRING_SIZE
];
39 char transfer_subnet
[STRING_SIZE
];
40 char role
[STRING_SIZE
];
41 char port
[STRING_SIZE
];
42 struct connection_struct
*next
;
45 typedef struct connection_struct connection
;
47 void exithandler(void)
58 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION
);
60 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION
);
62 printf("openvpnctrl <option>\n");
63 printf(" Valid options are:\n");
64 printf(" -s --start\n");
65 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
66 printf(" -k --kill\n");
67 printf(" kills/stops OpenVPN\n");
68 printf(" -r --restart\n");
69 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
70 printf(" -sn2n --start-net-2-net\n");
71 printf(" starts all net2net connections\n");
72 printf(" you may pass a connection name to the switch to only start a specific one\n");
73 printf(" -kn2n --kill-net-2-net\n");
74 printf(" kills all net2net connections\n");
75 printf(" you may pass a connection name to the switch to only start a specific one\n");
76 printf(" -d --display\n");
77 printf(" displays OpenVPN status to syslog\n");
78 printf(" -fwr --firewall-rules\n");
79 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
80 printf(" -sdo --start-daemon-only\n");
81 printf(" starts OpenVPN daemon only\n");
85 connection
*getConnections() {
88 if (!(fp
= fopen(CONFIG_ROOT
"/ovpn/ovpnconfig", "r"))) {
89 fprintf(stderr
, "Could not open openvpn n2n configuration file.\n");
93 char line
[STRING_SIZE
] = "";
94 char result
[STRING_SIZE
] = "";
97 connection
*conn_first
= NULL
;
98 connection
*conn_last
= NULL
;
99 connection
*conn_curr
;
101 while ((fgets(line
, STRING_SIZE
, fp
) != NULL
)) {
102 if (line
[strlen(line
) - 1] == '\n')
103 line
[strlen(line
) - 1] = '\0';
105 conn_curr
= (connection
*)malloc(sizeof(connection
));
106 memset(conn_curr
, 0, sizeof(connection
));
108 if (conn_first
== NULL
) {
109 conn_first
= conn_curr
;
111 conn_last
->next
= conn_curr
;
113 conn_last
= conn_curr
;
116 char *lineptr
= &line
;
118 if (*lineptr
== NULL
)
122 while (*lineptr
!= NULL
) {
123 if (*lineptr
== ',') {
127 *resultptr
++ = *lineptr
++;
132 strcpy(conn_curr
->status
, result
);
133 } else if (count
== 2) {
134 strcpy(conn_curr
->name
, result
);
135 } else if (count
== 4) {
136 strcpy(conn_curr
->type
, result
);
137 } else if (count
== 7) {
138 strcpy(conn_curr
->role
, result
);
139 } else if (count
== 9) {
140 strcpy(conn_curr
->local_subnet
, result
);
141 } else if (count
== 28) {
142 strcpy(conn_curr
->transfer_subnet
, result
);
143 } else if (count
== 29) {
144 strcpy(conn_curr
->proto
, result
);
145 } else if (count
== 30) {
146 strcpy(conn_curr
->port
, result
);
158 int readPidFile(const char *pidfile
) {
159 FILE *fp
= fopen(pidfile
, "r");
165 fscanf(fp
, "%d", &pid
);
171 int readExternalAddress(char* address
) {
172 FILE *fp
= fopen("/var/ipfire/red/local-ipaddress", "r");
176 int r
= fscanf(fp
, "%s", address
);
182 /* In case the read IP address is not valid, we empty
183 * the content of address and return non-zero. */
184 if (!VALID_IP(address
))
194 void ovpnInit(void) {
195 // Read OpenVPN configuration
196 kv
= initkeyvalues();
197 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings")) {
198 fprintf(stderr
, "Cannot read ovpn settings\n");
202 if (!findkey(kv
, "ENABLED", enablered
)) {
206 if (!findkey(kv
, "ENABLED_BLUE", enableblue
)){
210 if (!findkey(kv
, "ENABLED_ORANGE", enableorange
)){
215 // read interface settings
217 // details for the red int
218 memset(redif
, 0, STRING_SIZE
);
219 if ((ifacefile
= fopen(CONFIG_ROOT
"/red/iface", "r")))
221 if (fgets(redif
, STRING_SIZE
, ifacefile
))
223 if (redif
[strlen(redif
) - 1] == '\n')
224 redif
[strlen(redif
) - 1] = '\0';
229 if (!VALID_DEVICE(redif
))
231 memset(redif
, 0, STRING_SIZE
);
236 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
237 fprintf(stderr
, "Cannot read ethernet settings\n");
241 if (strcmp(enableblue
, "on") == 0) {
242 if (!findkey(kv
, "BLUE_DEV", blueif
)) {
247 if (strcmp(enableorange
, "on") == 0) {
248 if (!findkey(kv
, "ORANGE_DEV", orangeif
)) {
255 void executeCommand(char *command
) {
257 printf(strncat(command
, "\n", 2));
259 safe_system(strncat(command
, " >/dev/null 2>&1", 17));
262 void addRule(const char *chain
, const char *interface
, const char *protocol
, const char *port
) {
263 char command
[STRING_SIZE
];
265 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -i %s -p %s --dport %s -j ACCEPT",
266 chain
, interface
, protocol
, port
);
267 executeCommand(command
);
270 void flushChain(char *chain
) {
271 char str
[STRING_SIZE
];
273 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -F %s", chain
);
277 void flushChainNAT(char *chain
) {
278 char str
[STRING_SIZE
];
280 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -t nat -F %s", chain
);
284 char* calcTransferNetAddress(const connection
* conn
) {
285 char *subnetmask
= strdup(conn
->transfer_subnet
);
286 char *address
= strsep(&subnetmask
, "/");
288 if ((address
== NULL
) || (subnetmask
== NULL
)) {
292 in_addr_t _address
= inet_addr(address
);
293 in_addr_t _subnetmask
= inet_addr(subnetmask
);
294 _address
&= _subnetmask
;
296 if (strcmp(conn
->role
, "server") == 0) {
298 } else if (strcmp(conn
->role
, "client") == 0) {
304 struct in_addr address_info
;
305 address_info
.s_addr
= _address
;
307 return inet_ntoa(address_info
);
310 fprintf(stderr
, "Could not determine transfer net address: %s\n", conn
->name
);
316 char* getLocalSubnetAddress(const connection
* conn
) {
317 kv
= initkeyvalues();
318 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
319 fprintf(stderr
, "Cannot read ethernet settings\n");
323 const char *zones
[] = {"GREEN", "BLUE", "ORANGE", NULL
};
326 // Get net address of the local openvpn subnet.
327 char *subnetmask
= strdup(conn
->local_subnet
);
328 char *address
= strsep(&subnetmask
, "/");
330 if ((address
== NULL
) || (subnetmask
== NULL
)) {
334 in_addr_t _address
= inet_addr(address
);
335 in_addr_t _subnetmask
= inet_addr(subnetmask
);
337 in_addr_t _netaddr
= (_address
& _subnetmask
);
338 in_addr_t _broadcast
= (_address
| ~_subnetmask
);
340 char zone_address_key
[STRING_SIZE
];
341 char zone_address
[STRING_SIZE
];
347 snprintf(zone_address_key
, STRING_SIZE
, "%s_ADDRESS", zone
);
349 if (!findkey(kv
, zone_address_key
, zone_address
))
352 zone_addr
= inet_addr(zone_address
);
353 if ((zone_addr
> _netaddr
) && (zone_addr
< _broadcast
)) {
356 return strdup(zone_address
);
361 fprintf(stderr
, "Could not determine local subnet address: %s\n", conn
->name
);
367 void setFirewallRules(void) {
368 char command
[STRING_SIZE
];
369 char protocol
[STRING_SIZE
] = "";
370 char dport
[STRING_SIZE
] = "";
371 char dovpnip
[STRING_SIZE
] = "";
373 kv
= initkeyvalues();
374 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings"))
376 fprintf(stderr
, "Cannot read ovpn settings\n");
380 /* we got one device, so lets proceed further */
381 if (!findkey(kv
, "DDEST_PORT", dport
)){
382 fprintf(stderr
, "Cannot read DDEST_PORT\n");
386 if (!findkey(kv
, "DPROTOCOL", protocol
)){
387 fprintf(stderr
, "Cannot read DPROTOCOL\n");
391 if (!findkey(kv
, "VPN_IP", dovpnip
)){
392 fprintf(stderr
, "Cannot read VPN_IP\n");
397 flushChain(OVPNINPUT
);
398 flushChain(OVPNBLOCK
);
399 flushChainNAT(OVPNNAT
);
401 // set firewall rules
402 if (!strcmp(enablered
, "on") && strlen(redif
))
403 addRule(OVPNINPUT
, redif
, protocol
, dport
);
404 if (!strcmp(enableblue
, "on") && strlen(blueif
))
405 addRule(OVPNINPUT
, blueif
, protocol
, dport
);
406 if (!strcmp(enableorange
, "on") && strlen(orangeif
))
407 addRule(OVPNINPUT
, orangeif
, protocol
, dport
);
409 /* Allow ICMP error messages to pass. */
410 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -p icmp"
411 " -m conntrack --ctstate RELATED -j RETURN", OVPNBLOCK
);
412 executeCommand(command
);
414 // read connection configuration
415 connection
*conn
= getConnections();
417 // set firewall rules for n2n connections
418 char *local_subnet_address
= NULL
;
419 char *transfer_subnet_address
= NULL
;
420 while (conn
!= NULL
) {
421 if (strcmp(conn
->type
, "net") == 0) {
422 addRule(OVPNINPUT
, redif
, conn
->proto
, conn
->port
);
424 /* Block all communication from the transfer nets. */
425 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -s %s -j DROP",
426 OVPNBLOCK
, conn
->transfer_subnet
);
427 executeCommand(command
);
429 local_subnet_address
= getLocalSubnetAddress(conn
);
430 transfer_subnet_address
= calcTransferNetAddress(conn
);
432 if ((local_subnet_address
) && (transfer_subnet_address
)) {
433 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -t nat -A %s -s %s -j SNAT --to-source %s",
434 OVPNNAT
, transfer_subnet_address
, local_subnet_address
);
435 executeCommand(command
);
443 void stopDaemon(void) {
444 char command
[STRING_SIZE
];
446 int pid
= readPidFile("/var/run/openvpn.pid");
451 fprintf(stderr
, "Killing PID %d.\n", pid
);
454 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f /var/run/openvpn.pid");
455 executeCommand(command
);
458 void startDaemon(void) {
459 char command
[STRING_SIZE
];
461 if (!((strcmp(enablered
, "on") == 0) || (strcmp(enableblue
, "on") == 0) || (strcmp(enableorange
, "on") == 0))) {
462 fprintf(stderr
, "OpenVPN is not enabled on any interface\n");
465 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
466 executeCommand(command
);
467 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
468 executeCommand(command
);
472 int startNet2Net(char *name
) {
473 connection
*conn
= NULL
;
474 connection
*conn_iter
;
476 conn_iter
= getConnections();
479 if ((strcmp(conn_iter
->type
, "net") == 0) && (strcmp(conn_iter
->name
, name
) == 0)) {
483 conn_iter
= conn_iter
->next
;
487 fprintf(stderr
, "Connection not found.\n");
491 if (strcmp(conn
->status
, "on") != 0) {
492 fprintf(stderr
, "Connection '%s' is not enabled.\n", conn
->name
);
496 fprintf(stderr
, "Starting connection %s...\n", conn
->name
);
498 char configfile
[STRING_SIZE
];
499 snprintf(configfile
, STRING_SIZE
- 1, CONFIG_ROOT
"/ovpn/n2nconf/%s/%s.conf",
500 conn
->name
, conn
->name
);
502 FILE *fp
= fopen(configfile
, "r");
504 fprintf(stderr
, "Could not find configuration file for connection '%s' at '%s'.\n",
505 conn
->name
, configfile
);
510 // Make sure all firewall rules are up to date.
513 // Get the external IP address.
514 char address
[STRING_SIZE
] = "";
515 int r
= readExternalAddress(address
);
517 fprintf(stderr
, "Could not read the external address\n");
521 char command
[STRING_SIZE
];
522 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
523 executeCommand(command
);
524 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --local %s --config %s", address
, configfile
);
525 executeCommand(command
);
530 int killNet2Net(char *name
) {
531 connection
*conn
= NULL
;
532 connection
*conn_iter
;
534 conn_iter
= getConnections();
537 if (strcmp(conn_iter
->name
, name
) == 0) {
541 conn_iter
= conn_iter
->next
;
545 fprintf(stderr
, "Connection not found.\n");
549 char pidfile
[STRING_SIZE
];
550 snprintf(pidfile
, STRING_SIZE
- 1, "/var/run/%sn2n.pid", conn
->name
);
552 int pid
= readPidFile(pidfile
);
554 fprintf(stderr
, "Could not read pid file of connection %s.", conn
->name
);
558 fprintf(stderr
, "Killing connection %s (PID %d)...\n", conn
->name
, pid
);
561 char command
[STRING_SIZE
];
562 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f %s", pidfile
);
563 executeCommand(command
);
568 void startAllNet2Net() {
569 int exitcode
= 0, _exitcode
= 0;
571 connection
*conn
= getConnections();
574 /* Skip all connections that are not of type "net" or disabled. */
575 if ((strcmp(conn
->type
, "net") != 0) || (strcmp(conn
->status
, "on") != 0)) {
580 _exitcode
= startNet2Net(conn
->name
);
583 if (_exitcode
> exitcode
) {
584 exitcode
= _exitcode
;
591 void killAllNet2Net() {
592 int exitcode
= 0, _exitcode
= 0;
594 connection
*conn
= getConnections();
597 /* Skip all connections that are not of type "net". */
598 if (strcmp(conn
->type
, "net") != 0) {
603 _exitcode
= killNet2Net(conn
->name
);
606 if (_exitcode
> exitcode
) {
607 exitcode
= _exitcode
;
614 void displayopenvpn(void) {
615 char command
[STRING_SIZE
];
617 snprintf(command
, STRING_SIZE
- 1, "/bin/killall -sSIGUSR2 openvpn");
618 executeCommand(command
);
621 int main(int argc
, char *argv
[]) {
630 if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
631 startNet2Net(argv
[2]);
634 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
635 killNet2Net(argv
[2]);
643 if( (strcmp(argv
[1], "-k") == 0) || (strcmp(argv
[1], "--kill") == 0) ) {
647 else if( (strcmp(argv
[1], "-d") == 0) || (strcmp(argv
[1], "--display") == 0) ) {
654 if( (strcmp(argv
[1], "-s") == 0) || (strcmp(argv
[1], "--start") == 0) ) {
659 else if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
663 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
667 else if( (strcmp(argv
[1], "-sdo") == 0) || (strcmp(argv
[1], "--start-daemon-only") == 0) ) {
671 else if( (strcmp(argv
[1], "-r") == 0) || (strcmp(argv
[1], "--restart") == 0) ) {
677 else if( (strcmp(argv
[1], "-fwr") == 0) || (strcmp(argv
[1], "--firewall-rules") == 0) ) {