⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interfaces.c

📁 ipsec vpn
💻 C
字号:
/* FreeS/WAN interfaces management (interfaces.c) * 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.5 2005/01/11 17:52:51 ken 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 <openswan.h>#include "openswan/ipsec_tunnel.h"#include "interfaces.h"#include "exec.h"#include "files.h"#include "starterlog.h"#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) )#define N_IPSEC_IF      4struct st_ipsec_if {	char name[IFNAMSIZ+1];	char phys[IFNAMSIZ+1];	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+1];	char *b;	struct ifreq req;	FILE *f;	char line[256];	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/pluto/dynip/<iface>, look if we		 * can get interface name from there (IP_PHYS)		 */		b = (char *)malloc(strlen(DYNIP_DIR)+strlen(iface)+10);		if (b) {			sprintf(b, "%s/%s", DYNIP_DIR, iface);			f = fopen(b, "r");			free(b);			if (f) {				memset(_if, 0, sizeof(_if));				memset(line, 0, sizeof(line));				while (fgets(line, sizeof(line)-1, f)!=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(f);				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){	if (!str) return 0;	if (strlen(str)<8) return 0;	if ((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;	if (pn) *pn = str[5] - '0';	if (pphys) *pphys = &(str[7]);	return 1;}static int _iface_up (int sock,  struct st_ipsec_if *iface, char *phys,	unsigned int mtu, int 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)) {		starter_log(LOG_LEVEL_INFO, "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) {		starter_log(LOG_LEVEL_INFO, "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, int nat_t){	char *tmp_phys, *phys;	int n;	char **i;	int sock;	int j, found;	int ret = 0;	starter_log(LOG_LEVEL_DEBUG, "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)) && (tmp_phys) &&			(n>=0) && (n<N_IPSEC_IF)) {				if (n==j) {					if (found) {						starter_log(LOG_LEVEL_ERR,							"ignoring duplicate entry for interface ipsec%d",							j);					}					else {						found++;						phys = _find_physical_iface(sock, tmp_phys);						if (phys) {							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				 */				starter_log(LOG_LEVEL_ERR, "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 */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -