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

📄 server.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
	    log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));	    close(fd);	    return -1;	}	policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;	if (setsockopt(fd, level, opt	  , &policy, sizeof(policy)) < 0)	{	    log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));	    close(fd);	    return -1;	}    }#endif    setportof(htons(port), &ifp->addr);    if (bind(fd, sockaddrof(&ifp->addr), sockaddrlenof(&ifp->addr)) < 0)    {	log_errno((e, "bind() for %s/%s %s:%u in process_raw_ifaces()"	    , ifp->name, v_name	    , ip_str(&ifp->addr), (unsigned) port));	close(fd);	return -1;    }    setportof(htons(pluto_port), &ifp->addr);    return fd;}static voidprocess_raw_ifaces(struct raw_iface *rifaces){    struct raw_iface *ifp;    /* Find all virtual/real interface pairs.     * For each real interface...     */    for (ifp = rifaces; ifp != NULL; ifp = ifp->next)    {	struct raw_iface *v = NULL;	/* matching ipsecX interface */	struct raw_iface fake_v;	bool after = FALSE; /* has vfp passed ifp on the list? */	bool bad = FALSE;	struct raw_iface *vfp;	/* ignore if virtual (ipsec*) interface */	if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)	    continue;	for (vfp = rifaces; vfp != NULL; vfp = vfp->next)	{	    if (vfp == ifp)	    {		after = TRUE;	    }	    else if (sameaddr(&ifp->addr, &vfp->addr))	    {		/* Different entries with matching IP addresses.		 * Many interesting cases.		 */		if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)		{		    if (v != NULL)		    {			loglog(RC_LOG_SERIOUS			    , "ipsec interfaces %s and %s share same address %s"			    , v->name, vfp->name, ip_str(&ifp->addr));			bad = TRUE;		    }		    else		    {			v = vfp;	/* current winner */		    }		}		else		{		    /* ugh: a second real interface with the same IP address		     * "after" allows us to avoid double reporting.		     */#if defined(linux) && defined(KERNEL26_SUPPORT)		    if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)		    {			if (after)			{			    bad = TRUE;			    break;			}			continue;		    }#endif		    if (after)		    {			loglog(RC_LOG_SERIOUS			    , "IP interfaces %s and %s share address %s!"			    , ifp->name, vfp->name, ip_str(&ifp->addr));		    }		    bad = TRUE;		}	    }	}	if (bad)	    continue;#if defined(linux) && defined(KERNEL26_SUPPORT)	if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX)	{	    v = ifp;	    goto add_entry;	}#endif	/* what if we didn't find a virtual interface? */	if (v == NULL)	{	    if (no_klips)	    {		/* kludge for testing: invent a virtual device */		static const char fvp[] = "virtual";		fake_v = *ifp;		passert(sizeof(fake_v.name) > sizeof(fvp));		strcpy(fake_v.name, fvp);		addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1		    , sizeof(fake_v.name) - (sizeof(fvp) - 1));		v = &fake_v;	    }	    else	    {		DBG(DBG_CONTROL,			DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored"			    , ifp->name, ip_str(&ifp->addr)));		continue;	    }	}	/* We've got all we need; see if this is a new thing:	 * search old interfaces list.	 */#if defined(linux) && defined(KERNEL26_SUPPORT)add_entry:#endif	{	    struct iface **p = &interfaces;	    for (;;)	    {		struct iface *q = *p;		/* search is over if at end of list */		if (q == NULL)		{		    /* matches nothing -- create a new entry */		    int fd = create_socket(ifp, v->name, pluto_port);		    if (fd < 0)			break;#ifdef NAT_TRAVERSAL		    if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET)		    {			nat_traversal_espinudp_socket(fd, "IPv4", ESPINUDP_WITH_NON_IKE);		    }#endif		    q = alloc_thing(struct iface, "struct iface");		    q->rname = clone_str(ifp->name, "real device name");		    q->vname = clone_str(v->name, "virtual device name");		    q->addr = ifp->addr;		    q->fd = fd;		    q->next = interfaces;		    q->change = IFN_ADD;		    interfaces = q;		    openswan_log("adding interface %s/%s %s"			, q->vname, q->rname, ip_str(&q->addr));#ifdef NAT_TRAVERSAL		    if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) {			fd = create_socket(ifp, v->name, NAT_T_IKE_FLOAT_PORT);			if (fd < 0) 			    break;			nat_traversal_espinudp_socket(fd, "IPv4"						      , ESPINUDP_WITH_NON_ESP);			q = alloc_thing(struct iface, "struct iface");			q->rname = clone_str(ifp->name, "real device name");			q->vname = clone_str(v->name, "virtual device name");			q->addr = ifp->addr;			setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->addr);			q->fd = fd;			q->next = interfaces;			q->change = IFN_ADD;			q->ike_float = TRUE;			interfaces = q;			openswan_log("adding interface %s/%s %s:%d",			q->vname, q->rname, ip_str(&q->addr), NAT_T_IKE_FLOAT_PORT);		    }#endif		    break;		}		/* search over if matching old entry found */		if (streq(q->rname, ifp->name)		&& streq(q->vname, v->name)		&& sameaddr(&q->addr, &ifp->addr))		{		    /* matches -- rejuvinate old entry */		    q->change = IFN_KEEP;#ifdef NAT_TRAVERSAL		    /* look for other interfaces to keep (due to NAT-T) */		    for (q = q->next ; q ; q = q->next) {			if (streq(q->rname, ifp->name)			    && streq(q->vname, v->name)			    && sameaddr(&q->addr, &ifp->addr)) {				q->change = IFN_KEEP;			}		    }#endif		    break;		}		/* try again */		p = &q->next;	    } /* for (;;) */	}    }    /* delete the raw interfaces list */    while (rifaces != NULL)    {	struct raw_iface *t = rifaces;	rifaces = t->next;	pfree(t);    }}voidfind_ifaces(void){    mark_ifaces_dead();    process_raw_ifaces(find_raw_ifaces4());    process_raw_ifaces(find_raw_ifaces6());    free_dead_ifaces();	    /* ditch remaining old entries */    if (interfaces == NULL)	loglog(RC_LOG_SERIOUS, "no public interfaces found");}voidshow_ifaces_status(void){    struct iface *p;    for (p = interfaces; p != NULL; p = p->next)	whack_log(RC_COMMENT, "interface %s/%s %s"	    , p->vname, p->rname, ip_str(&p->addr));}voidshow_debug_status(void){#ifdef DEBUG    whack_log(RC_COMMENT, "debug %s"	, bitnamesof(debug_bit_names, cur_debugging));#endif}static volatile sig_atomic_t sighupflag = FALSE;static voidhuphandler(int sig UNUSED){    sighupflag = TRUE;}static volatile sig_atomic_t sigtermflag = FALSE;static voidtermhandler(int sig UNUSED){    sigtermflag = TRUE;}static volatile sig_atomic_t sigchildflag = FALSE;static voidchildhandler(int sig UNUSED){    sigchildflag = TRUE;}/* perform wait4() on all children */static voidreapchildren(void){    pid_t child;    int status;    struct rusage r;    sigchildflag = FALSE;    while((child = wait3(&status, WNOHANG, &r)) != 0) {	/* got a child to reap */	if(adns_reapchild(child, status)) continue;	if(pluto_crypt_handle_dead_child(child, status)) continue;		openswan_log("child pid=%d (status=%d) is not my child!", child, status);    }}/* call_server listens for incoming ISAKMP packets and Whack messages, * and handles timer events. */voidcall_server(void){    struct iface *ifp;    /* catch SIGHUP and SIGTERM */    {	int r;	struct sigaction act;	act.sa_handler = &huphandler;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	/* no SA_ONESHOT, no SA_RESTART, no nothing */	r = sigaction(SIGHUP, &act, NULL);	passert(r == 0);	act.sa_handler = &termhandler;	r = sigaction(SIGTERM, &act, NULL);	passert(r == 0);	act.sa_handler = &childhandler;	act.sa_flags   = SA_RESTART;	r = sigaction(SIGCHLD, &act, NULL);	passert(r == 0);    }    for (;;)    {	fd_set readfds;	fd_set writefds;	int ndes;	/* wait for next interesting thing */	for (;;)	{	    long next_time = next_event();   /* time to any pending timer event */	    int maxfd = ctl_fd;	    if (sigtermflag)		exit_pluto(0);	    if (sighupflag)	    {		/* Ignorant folks think poking any daemon with SIGHUP		 * is polite.  We catch it and tell them otherwise.		 * There is one use: unsticking a hung recvfrom.		 * This sticking happens sometimes -- kernel bug?		 */		sighupflag = FALSE;		openswan_log("Pluto ignores SIGHUP -- perhaps you want \"whack --listen\"");	    }	    if(sigchildflag) {		reapchildren();	    }	    FD_ZERO(&readfds);	    FD_ZERO(&writefds);	    FD_SET(ctl_fd, &readfds);#ifdef IPSECPOLICY	    FD_SET(info_fd, &readfds);	    if (maxfd < info_fd)		maxfd = info_fd;#endif	    /* the only write file-descriptor of interest */	    if (adns_qfd != NULL_FD && unsent_ADNS_queries)	    {		if (maxfd < adns_qfd)		    maxfd = adns_qfd;		FD_SET(adns_qfd, &writefds);	    }	    if (adns_afd != NULL_FD)	    {		if (maxfd < adns_afd)		    maxfd = adns_afd;		FD_SET(adns_afd, &readfds);	    }#ifdef KLIPS	    if (!no_klips)	    {		int fd = *kernel_ops->async_fdp;		if (kernel_ops->process_queue)		    kernel_ops->process_queue();		if (maxfd < fd)		    maxfd = fd;		passert(!FD_ISSET(fd, &readfds));		FD_SET(fd, &readfds);	    }#endif	    if (listening)	    {		for (ifp = interfaces; ifp != NULL; ifp = ifp->next)		{		    if (maxfd < ifp->fd)			maxfd = ifp->fd;		    passert(!FD_ISSET(ifp->fd, &readfds));		    FD_SET(ifp->fd, &readfds);		}	    }	    /* see if helpers need attention */	    pluto_crypto_helper_sockets(&readfds);	    if (no_retransmits || next_time < 0)	    {		/* select without timer */		ndes = select(maxfd + 1, &readfds, &writefds, NULL, NULL);	    }	    else if (next_time == 0)	    {		/* timer without select: there is a timer event pending,		 * and it should fire now so don't bother to do the select.		 */		ndes = 0;	/* signify timer expiration */	    }	    else	    {		/* select with timer */		struct timeval tm;		tm.tv_sec = next_time;		tm.tv_usec = 0;		ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm);	    }	    if (ndes != -1)		break;	/* success */	    if (errno != EINTR)		exit_log_errno((e, "select() failed in call_server()"));	    /* retry if terminated by signal */	}	/* figure out what is interesting */	if (ndes == 0)	{	    /* timer event */	    if(!no_retransmits)	    {		DBG(DBG_CONTROL,		    DBG_log(BLANK_FORMAT);		    DBG_log("*time to handle event"));				handle_timer_event();		passert(GLOBALS_ARE_RESET());	    }	}	else	{	    /* at least one file descriptor is ready */	    if (adns_qfd != NULL_FD && FD_ISSET(adns_qfd, &writefds))	    {		passert(ndes > 0);		send_unsent_ADNS_queries();		passert(GLOBALS_ARE_RESET());		ndes--;	    }	    if (adns_afd != NULL_FD && FD_ISSET(adns_afd, &readfds))	    {		passert(ndes > 0);		DBG(DBG_CONTROL,		    DBG_log(BLANK_FORMAT);		    DBG_log("*received adns message"));		handle_adns_answer();		passert(GLOBALS_ARE_RESET());		ndes--;	    }#ifdef KLIPS	    if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds))	    {		passert(ndes > 0);		DBG(DBG_CONTROL,		    DBG_log(BLANK_FORMAT);		    DBG_log("*received kernel message"));		kernel_ops->process_msg();		passert(GLOBALS_ARE_RESET());		ndes--;	    }#endif	    for (ifp = interfaces; ifp != NULL; ifp = ifp->next)	    {		if (FD_ISSET(ifp->fd, &readfds))		{		    /* comm_handle will print DBG_CONTROL intro,		     * with more info than we have here.		     */		    passert(ndes > 0);		    comm_handle(ifp);		    passert(GLOBALS_ARE_RESET());		    ndes--;		}	    }	    if (FD_ISSET(ctl_fd, &readfds))	    {		passert(ndes > 0);		DBG(DBG_CONTROL,		    DBG_log(BLANK_FORMAT);		    DBG_log("*received whack message"));		whack_handle(ctl_fd);		passert(GLOBALS_ARE_RESET());		ndes--;	    }#ifdef IPSECPOLICY	    if (FD_ISSET(info_fd, &readfds))	    {		passert(ndes > 0);		DBG(DBG_CONTROL,		    DBG_log(BLANK_FORMAT);		    DBG_log("*received info message"));		info_handle(info_fd);		passert(GLOBALS_ARE_RESET());		ndes--;	    }#endif	    /* note we process helper things last on purpose */	    ndes -= pluto_crypto_helper_ready(&readfds);	    passert(ndes == 0);	}    }}/* * Local Variables: * c-basic-offset: 4 * End Variables: */

⌨️ 快捷键说明

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