summaryrefslogtreecommitdiff
path: root/programs/starter/interfaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'programs/starter/interfaces.c')
-rw-r--r--programs/starter/interfaces.c582
1 files changed, 0 insertions, 582 deletions
diff --git a/programs/starter/interfaces.c b/programs/starter/interfaces.c
deleted file mode 100644
index 3b24e2faf..000000000
--- a/programs/starter/interfaces.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/* strongSwan IPsec interfaces management
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * RCSID $Id: interfaces.c,v 1.16 2006/05/25 12:10:15 as Exp $
- */
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <freeswan.h>
-#include <freeswan/ipsec_tunnel.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
-
-#include "interfaces.h"
-#include "exec.h"
-#include "files.h"
-
-#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )
-
-#define N_IPSEC_IF 4
-
-struct st_ipsec_if {
- char name[IFNAMSIZ];
- char phys[IFNAMSIZ];
- int up;
-};
-
-static struct st_ipsec_if _ipsec_if[N_IPSEC_IF];
-
-static char *
-_find_physical_iface(int sock, char *iface)
-{
- static char _if[IFNAMSIZ];
- char *b;
- struct ifreq req;
- FILE *fd;
- char line[BUF_LEN];
-
- strncpy(req.ifr_name, iface, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req)==0)
- {
- if (req.ifr_flags & IFF_UP)
- {
- strncpy(_if, iface, IFNAMSIZ);
- return _if;
- }
- }
- else
- {
- /* If there is a file named /var/run/dynip/<iface>, look if we
- * can get interface name from there (IP_PHYS)
- */
- b = (char *)alloc_bytes(strlen(DYNIP_DIR) + strlen(iface) + 10, "iface");
- if (b)
- {
- sprintf(b, "%s/%s", DYNIP_DIR, iface);
- fd = fopen(b, "r");
- pfree(b);
- if (fd)
- {
- memset(_if, 0, sizeof(_if));
- memset(line, 0, sizeof(line));
- while (fgets(line, sizeof(line), fd) != 0)
- {
- if ((strncmp(line,"IP_PHYS=\"", 9) == 0)
- && (line[strlen(line) - 2] == '"')
- && (line[strlen(line) - 1] == '\n'))
- {
- strncpy(_if, line + 9, MIN(strlen(line) - 11, IFNAMSIZ));
- break;
- }
- else if ((strncmp(line,"IP_PHYS=", 8) == 0)
- && (line[8] != '"')
- && (line[strlen(line) - 1] == '\n'))
- {
- strncpy(_if, line + 8, MIN(strlen(line) - 9, IFNAMSIZ));
- break;
- }
- }
- fclose(fd);
-
- if (*_if)
- {
- strncpy(req.ifr_name, _if, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
- {
- if (req.ifr_flags & IFF_UP)
- return _if;
- }
- }
- }
- }
- }
- return NULL;
-}
-
-int
-starter_iface_find(char *iface, int af, ip_address *dst, ip_address *nh)
-{
- char *phys;
- struct ifreq req;
- struct sockaddr_in *sa = (struct sockaddr_in *)(&req.ifr_addr);
- int sock;
-
- if (!iface)
- return -1;
-
- sock = socket(af, SOCK_DGRAM, 0);
- if (sock < 0)
- return -1;
-
- phys = _find_physical_iface(sock, iface);
- if (!phys)
- goto failed;
-
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req)!=0)
- goto failed;
- if (!(req.ifr_flags & IFF_UP))
- goto failed;
-
- if ((req.ifr_flags & IFF_POINTOPOINT)
- && nh
- && ioctl(sock, SIOCGIFDSTADDR, &req) == 0)
- {
- if (sa->sin_family == af)
- initaddr((const void *)&sa->sin_addr, sizeof(struct in_addr), af, nh);
- }
- if ((dst) && (ioctl(sock, SIOCGIFADDR, &req) == 0))
- {
- if (sa->sin_family == af)
- initaddr((const void *)&sa->sin_addr, sizeof(struct in_addr), af, dst);
- }
- close(sock);
- return 0;
-
-failed:
- close(sock);
- return -1;
-}
-
-static int
-valid_str(char *str, unsigned int *pn, char **pphys
-, defaultroute_t *defaultroute)
-{
- if (streq(str, "%defaultroute"))
- {
- if (!defaultroute->defined)
- {
- return 0;
- }
- *pn = 0;
- *pphys = defaultroute->iface;
- }
- else
- {
- if (strlen(str) < 8
- || str[0] != 'i' || str[1] != 'p' || str[2] !='s' || str[3] != 'e'
- || str[4] != 'c' || str[5] < '0' || str[5] > '9' || str[6] != '=')
- {
- return 0;
- }
- *pn = str[5] - '0';
- *pphys = &(str[7]);
- }
- return 1;
-}
-
-static int
-_iface_up (int sock, struct st_ipsec_if *iface, char *phys
-, unsigned int mtu, bool nat_t)
-{
- struct ifreq req;
- struct ipsectunnelconf *shc=(struct ipsectunnelconf *)&req.ifr_data;
- short phys_flags;
- int ret = 0;
-
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req) !=0 )
- return ret;
- phys_flags = req.ifr_flags;
-
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req) != 0)
- return ret;
-
- if ((!(req.ifr_flags & IFF_UP)) || (!iface->up))
- {
- DBG(DBG_CONTROL,
- DBG_log("attaching interface %s to %s", iface->name, phys)
- )
- ret = 1;
- }
-
- if ((*iface->phys) && (strcmp(iface->phys, phys) != 0 ))
- {
- /* tncfg --detach if phys has changed */
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- ioctl(sock, IPSEC_DEL_DEV, &req);
- ret = 1;
- }
-
- /* tncfg --attach */
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- strncpy(shc->cf_name, phys, sizeof(shc->cf_name));
- ioctl(sock, IPSEC_SET_DEV, &req);
-
- /* set ipsec addr = phys addr */
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFADDR, &req) == 0)
- {
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- ioctl(sock, SIOCSIFADDR, &req);
- }
-
- /* set ipsec mask = phys mask */
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFNETMASK, &req) == 0)
- {
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- ioctl(sock, SIOCSIFNETMASK, &req);
- }
-
- /* set other flags & addr */
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req)==0)
- {
- if (phys_flags & IFF_POINTOPOINT)
- {
- req.ifr_flags |= IFF_POINTOPOINT;
- req.ifr_flags &= ~IFF_BROADCAST;
- ioctl(sock, SIOCSIFFLAGS, &req);
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)
- {
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- ioctl(sock, SIOCSIFDSTADDR, &req);
- }
- }
- else if (phys_flags & IFF_BROADCAST)
- {
- req.ifr_flags &= ~IFF_POINTOPOINT;
- req.ifr_flags |= IFF_BROADCAST;
- ioctl(sock, SIOCSIFFLAGS, &req);
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFBRDADDR, &req) == 0)
- {
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- ioctl(sock, SIOCSIFBRDADDR, &req);
- }
- }
- else
- {
- req.ifr_flags &= ~IFF_POINTOPOINT;
- req.ifr_flags &= ~IFF_BROADCAST;
- ioctl(sock, SIOCSIFFLAGS, &req);
- }
- }
-
- /*
- * guess MTU = phys interface MTU - ESP Overhead
- *
- * ESP overhead : 10+16+7+2+12=57 -> 60 by security
- * NAT-T overhead : 20
- */
- if (mtu == 0)
- {
- strncpy(req.ifr_name, phys, IFNAMSIZ);
- ioctl(sock, SIOCGIFMTU, &req);
- mtu = req.ifr_mtu - 60;
- if (nat_t)
- mtu -= 20;
- }
- /* set MTU */
- if (mtu)
- {
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- req.ifr_mtu = mtu;
- ioctl(sock, SIOCSIFMTU, &req);
- }
-
- /* ipsec interface UP */
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
- {
- req.ifr_flags |= IFF_UP;
- ioctl(sock, SIOCSIFFLAGS, &req);
- }
-
- iface->up = 1;
- strncpy(iface->phys, phys, IFNAMSIZ);
- return ret;
-}
-
-static int
-_iface_down(int sock, struct st_ipsec_if *iface)
-{
- struct ifreq req;
- int ret = 0;
-
- iface->up = 0;
-
- strncpy(req.ifr_name, iface->name, IFNAMSIZ);
- if (ioctl(sock, SIOCGIFFLAGS, &req)!=0)
- return ret;
-
- if (req.ifr_flags & IFF_UP)
- {
- DBG(DBG_CONTROL,
- DBG_log("shutting down interface %s/%s", iface->name, iface->phys)
- )
- req.ifr_flags &= ~IFF_UP;
- ioctl(sock, SIOCSIFFLAGS, &req);
- ret = 1;
- }
-
- /* unset addr */
- memset(&req.ifr_addr, 0, sizeof(req.ifr_addr));
- req.ifr_addr.sa_family = AF_INET;
- ioctl(sock, SIOCSIFADDR, &req);
-
- /* tncfg --detach */
- ioctl(sock, IPSEC_DEL_DEV, &req);
-
- memset(iface->phys, 0, sizeof(iface->phys));
-
- return ret;
-}
-
-void
-starter_ifaces_init(void)
-{
- int i;
-
- memset(_ipsec_if, 0, sizeof(_ipsec_if));
- for (i = 0; i < N_IPSEC_IF; i++)
- snprintf(_ipsec_if[i].name, IFNAMSIZ, "ipsec%d", i);
-}
-
-void
-starter_ifaces_clear (void)
-{
- int sock;
- unsigned int i;
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0)
- return;
-
- for (i = 0; i < N_IPSEC_IF; i++)
- _iface_down (sock, &(_ipsec_if[i]));
-}
-
-int
-starter_ifaces_load(char **ifaces, unsigned int omtu, bool nat_t
-, defaultroute_t *defaultroute)
-{
- char *tmp_phys, *phys;
- int n;
- char **i;
- int sock;
- int j, found;
- int ret = 0;
- struct ifreq physreq, ipsecreq; // re-attach interface
- struct sockaddr_in *inp1, *inp2; // re-attach interface
-
- DBG(DBG_CONTROL,
- DBG_log("starter_ifaces_load()")
- )
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0)
- return -1;
-
- for (j = 0; j < N_IPSEC_IF; j++)
- {
- found = 0;
-
- for (i = ifaces; i && *i; i++)
- {
- if (valid_str(*i, &n, &tmp_phys, defaultroute)
- && tmp_phys
- && n >= 0
- && n < N_IPSEC_IF)
- {
- if (n==j)
- {
- if (found)
- {
- plog( "ignoring duplicate entry for interface ipsec%d", j);
- }
- else
- {
- found++;
- phys = _find_physical_iface(sock, tmp_phys);
-
- /* Re-attach ipsec interface if IP address changes
- * sscholz@astaro.com
- */
- if (phys)
- {
- memset ((void*)&physreq, 0, sizeof(physreq));
- memset ((void*)&ipsecreq, 0, sizeof(ipsecreq));
- strncpy(physreq.ifr_name, phys, IFNAMSIZ);
- sprintf(ipsecreq.ifr_name, "ipsec%d", j);
- ioctl(sock, SIOCGIFADDR, &physreq);
- ioctl(sock, SIOCGIFADDR, &ipsecreq);
- inp1 = (struct sockaddr_in *)&physreq.ifr_addr;
- inp2 = (struct sockaddr_in *)&ipsecreq.ifr_addr;
- if (inp1->sin_addr.s_addr != inp2->sin_addr.s_addr)
- {
- plog("IP address of physical interface changed "
- "-> reinit of ipsec interface");
- _iface_down (sock, &(_ipsec_if[n]));
- }
- ret += _iface_up (sock, &(_ipsec_if[n]), phys, omtu, nat_t);
- }
- else
- {
- ret += _iface_down (sock, &(_ipsec_if[n]));
- }
- }
- }
- }
- else if (j == 0)
- {
- /* Only log in the first loop */
- plog("ignoring invalid interface '%s'", *i);
- }
- }
- if (!found)
- ret += _iface_down (sock, &(_ipsec_if[j]));
- }
-
- close(sock);
- return ret; /* = number of changes - 'whack --listen' if > 0 */
-}
-
-/*
- * initialize a defaultroute_t struct
- */
-static void
-init_defaultroute(defaultroute_t *defaultroute)
-{
- memset(defaultroute, 0, sizeof(defaultroute_t));
-}
-
-/*
- * discover the default route via /proc/net/route
- */
-void
-get_defaultroute(defaultroute_t *defaultroute)
-{
- FILE *fd;
- char line[BUF_LEN];
- bool first = TRUE;
-
- init_defaultroute(defaultroute);
-
- fd = fopen("/proc/net/route", "r");
-
- if (!fd)
- {
- plog("could not open 'proc/net/route'");
- return;
- }
-
- while (fgets(line, sizeof(line), fd) != 0)
- {
- char iface[11];
- char destination[9];
- char gateway[11];
- char flags[5];
- char mask[9];
-
- int refcnt;
- int use;
- int metric;
- int items;
-
- /* proc/net/route returns IP addresses in host order */
- strcpy(gateway, "0h");
-
- /* skip the header line */
- if (first)
- {
- first = FALSE;
- continue;
- }
-
- /* parsing a single line of proc/net/route */
- items = sscanf(line, "%10s\t%8s\t%8s\t%5s\t%d\t%d\t%d\t%8s\t"
- , iface, destination, gateway+2, flags, &refcnt, &use, &metric, mask);
- if (items < 8)
- {
- plog("parsing error while scanning /proc/net/route");
- continue;
- }
-
- /* check for defaultroute (destination 0.0.0.0 and mask 0.0.0.0) */
- if (streq(destination, "00000000") && streq(mask, "00000000"))
- {
- if (defaultroute->defined)
- {
- plog("multiple default routes - cannot cope with %%defaultroute!!!");
- defaultroute->defined = FALSE;
- fclose(fd);
- return;
- }
- ttoaddr(gateway, strlen(gateway), AF_INET, &defaultroute->nexthop);
- strncpy(defaultroute->iface, iface, IFNAMSIZ);
- defaultroute->defined = TRUE;
- }
- }
- fclose(fd);
-
- if (!defaultroute->defined)
- {
- plog("no default route - cannot cope with %%defaultroute!!!");
- }
- else
- {
- char addr_buf[20], nexthop_buf[20];
- struct ifreq physreq;
-
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
-
- /* determine IP address of iface */
- if (sock < 0)
- {
- plog("could not open SOCK_DGRAM socket");
- defaultroute->defined = FALSE;
- return;
- }
- memset ((void*)&physreq, 0, sizeof(physreq));
- strncpy(physreq.ifr_name, defaultroute->iface, IFNAMSIZ);
- ioctl(sock, SIOCGIFADDR, &physreq);
- close(sock);
- defaultroute->addr.u.v4 = *((struct sockaddr_in *)&physreq.ifr_addr);
-
- addrtot(&defaultroute->addr, 0, addr_buf, sizeof(addr_buf));
- addrtot(&defaultroute->nexthop, 0, nexthop_buf, sizeof(nexthop_buf));
-
- DBG(DBG_CONTROL,
- DBG_log("Default route found: iface=%s, addr=%s, nexthop=%s"
- , defaultroute->iface, addr_buf, nexthop_buf)
- )
-
- /* for backwards-compatibility with the awk shell scripts
- * store the defaultroute in /var/run/ipsec.info
- */
- fd = fopen(INFO_FILE, "w");
-
- if (fd)
- {
- fprintf(fd, "defaultroutephys=%s\n", defaultroute->iface );
- fprintf(fd, "defaultroutevirt=ipsec0\n");
- fprintf(fd, "defaultrouteaddr=%s\n", addr_buf);
- fprintf(fd, "defaultroutenexthop=%s\n", nexthop_buf);
- fclose(fd);
- }
- }
- return;
-}