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

📄 pluto_crypt.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
		passert(w->pcw_pid != -1);	passert(w->pcw_pipe != -1);	passert(w->pcw_work > 0);    	DBG(DBG_CONTROL	    , DBG_log("asking helper %d to do %s op on seq: %u"		      , w->pcw_helpernum		      , enum_show(&pluto_cryptoop_names, r->pcr_type)		      , r->pcr_id));		/* send the request, and then mark the work as having more work */	cnt = write(w->pcw_pipe, r, r->pcr_len);	if(cnt == -1) {	    /* XXX invoke callback with failure */	    passert(0);	    return;	} 		w->pcw_work++;    }}bool pluto_crypt_handle_dead_child(int pid, int status UNUSED){    int cnt;    struct pluto_crypto_worker *w = pc_workers;    for(cnt = 0; cnt < pc_workers_cnt; cnt++, w++) {	if(w->pcw_pid == pid) {	    w->pcw_reaped = TRUE;	    	    if(w->pcw_dead == TRUE) {		cleanup_crypto_helper(w);	    }	    return TRUE;	}    }    return FALSE;}    	/* * this function is called when there is a helper pipe that is ready. * we read the request from the pipe, and find the associated continuation, * and dispatch to that continuation. * * this function should process only a single answer, and then go back * to the select call to get called again. This is not most efficient, * but is is most fair. * */void handle_helper_comm(struct pluto_crypto_worker *w){    char reqbuf[PCR_REQ_SIZE];    struct pluto_crypto_req *r;    int restlen;    int actlen;    struct pluto_crypto_req_cont *cn, **cnp;    /* we can accept more work now that we are about to read from the pipe */    w->pcw_work--;    DBG(DBG_CRYPT, DBG_log("helper %u has work (cnt now %d)"			   ,w->pcw_helpernum			   ,w->pcw_work));    /* read from the pipe */    actlen = read(w->pcw_pipe, reqbuf, sizeof(r->pcr_len));    if(actlen != sizeof(r->pcr_len)) {	if(actlen != 0) {	    loglog(RC_LOG_SERIOUS, "read failed with %d: %s"		   , actlen, strerror(errno));	}	/*	 * eof, mark worker as dead. If already reaped, then free.	 */	w->pcw_dead = TRUE;	if(w->pcw_reaped) {	    cleanup_crypto_helper(w);	}	return;    }    r = (struct pluto_crypto_req *)reqbuf;    if(r->pcr_len > sizeof(reqbuf)) {	loglog(RC_LOG_SERIOUS, "helper(%d) pid=%d screwed up length: %lu > %lu, killing it"	       , w->pcw_helpernum	       , w->pcw_pid, (unsigned long)r->pcr_len               , (unsigned long)sizeof(reqbuf));	kill(w->pcw_pid, SIGTERM);	w->pcw_dead = TRUE;	return;    }    restlen = r->pcr_len-sizeof(r->pcr_len);	    /* okay, got a basic size, read the rest of it */    if((actlen= read(w->pcw_pipe		     , reqbuf+sizeof(r->pcr_len)		     , restlen)) != restlen) {	/* faulty read. die, parent will restart us */		loglog(RC_LOG_SERIOUS	       , "cryptographic handler(%d) read(%d)=%d failed: %s\n"	       , w->pcw_pipe, restlen, actlen, strerror(errno));	return;    }    DBG(DBG_CRYPT, DBG_log("helper %u replies to sequence %u"			   ,w->pcw_helpernum			   ,r->pcr_id));    /*     * if there is work queued, then send it off after reading, since this     * avoids the most deadlocks     */    crypto_send_backlog(w);    /* now match up request to continuation, and invoke it */    cn = w->pcw_cont;    cnp = &w->pcw_cont;    while(cn && r->pcr_id != cn->pcrc_id) {	cnp = &cn->pcrc_next;	cn = cn->pcrc_next;    }    if(cn == NULL) {	loglog(RC_LOG_SERIOUS	       , "failed to find continuation associated with req %u\n",	       (unsigned int)r->pcr_id);	return;    }    /* unlink it */    *cnp = cn->pcrc_next;    cn->pcrc_next = NULL;     passert(cn->pcrc_func != NULL);    DBG(DBG_CRYPT, DBG_log("calling callback function %p"			   ,cn->pcrc_func));    /* call the continuation */    (*cn->pcrc_func)(cn, r, NULL);    /* now free up the continuation */    pfree(cn);}/* * initialize a helper. */static void init_crypto_helper(struct pluto_crypto_worker *w, int n){    int fds[2];    int errno2;    /* reset this */    w->pcw_pid = -1;    if(socketpair(PF_UNIX, SOCK_STREAM, 0, fds) != 0) {	loglog(RC_LOG_SERIOUS, "could not create socketpair for helpers: %s",	       strerror(errno));	return;    }    w->pcw_helpernum = n;    w->pcw_pipe = fds[0];    w->pcw_maxbasicwork  = 2;    w->pcw_maxcritwork   = 4;    w->pcw_work     = 0;    w->pcw_reaped = FALSE;    w->pcw_dead   = FALSE;    /* set the send/received queue length to be at least maxcritwork     * times sizeof(pluto_crypto_req) in size     */    {	int qlen = w->pcw_maxcritwork * sizeof(struct pluto_crypto_req) + 10;		if(setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF,&qlen, sizeof(qlen))==-1	   || setsockopt(fds[0],SOL_SOCKET,SO_SNDBUF,&qlen,sizeof(qlen))==-1	   || setsockopt(fds[1],SOL_SOCKET,SO_RCVBUF,&qlen,sizeof(qlen))==-1	   || setsockopt(fds[1],SOL_SOCKET,SO_RCVBUF,&qlen,sizeof(qlen))==-1) {	    loglog(RC_LOG_SERIOUS, "could not set socket queue to %d", qlen);	    return;	}    }    /* flush various descriptors so that they don't get written twice */    fflush(stdout);    fflush(stderr);    close_log();    close_peerlog();    w->pcw_pid = fork();    errno2 = errno;    if(w->pcw_pid == 0) { 	/* this is the CHILD */	int fd;	int maxfd;	struct rlimit nf;	int i;	/* diddle with our proc title */	memset(global_argv[0], '\0', strlen(global_argv[0])+1);	sprintf(global_argv[0], "pluto helper %s #%3d   ", pluto_ifn_inst, n);	for(i = 1; i < global_argc; i++) {	    if(global_argv[i]) {		int l = strlen(global_argv[i]);		memset(global_argv[i], '\0', l);	    }	    global_argv[i]=NULL;	}	if(getenv("PLUTO_CRYPTO_HELPER_DEBUG")) {	    sprintf(global_argv[0], "pluto helper %s #%3d (waiting for GDB) "		    , pluto_ifn_inst, n);	    sleep(60); /* for debugger to attach */	    sprintf(global_argv[0], "pluto helper %s #%3d                   "		    , pluto_ifn_inst, n);	}	if(getrlimit(RLIMIT_NOFILE, &nf) == -1) {	    maxfd = 256;	} else {	    maxfd = nf.rlim_max;	}	/* in child process, close all non-essential fds */	for(fd = 3; fd < maxfd; fd++) {	    if(fd != fds[1]) close(fd);	}		pluto_init_log();	init_rnd_pool();	free_preshared_secrets();	openswan_passert_fail = helper_passert_fail;	debug_prefix='!';	pluto_crypto_helper(fds[1], n);	exit(0);	/* NOTREACHED */    }    /* open the log files again */    pluto_init_log();	    if(w->pcw_pid == -1) {	loglog(RC_LOG_SERIOUS, "failed to start child, error = %s"	       , strerror(errno2));	close(fds[1]);	close(fds[0]);	w->pcw_dead   = TRUE;	return;    }    /* PARENT */    openswan_log("started helper pid=%d (fd:%d)", w->pcw_pid,  w->pcw_pipe);        /* close client side of socket pair in parent */    close(fds[1]);}/* * clean up after a crypto helper */static void cleanup_crypto_helper(struct pluto_crypto_worker *w){    w->pcw_pid = -1;    if(w->pcw_pipe) {	loglog(RC_LOG_SERIOUS, "closing helper(%u) pid=%d fd=%d"	       , w->pcw_helpernum, w->pcw_pid, w->pcw_pipe);	close(w->pcw_pipe);    }    w->pcw_reaped = FALSE;    w->pcw_dead   = FALSE;   /* marking is not dead lets it live again */}/* * initialize the helpers. * * Later we will have to make provisions for helpers that have hardware * underneath them, in which case, they may be able to accept many * more requests than average. * */void init_crypto_helpers(int nhelpers){    int i;    pc_workers = NULL;    pc_workers_cnt = 0;    pcw_id = 1;    /* find out how many CPUs there are, if nhelpers is -1 */    /* if nhelpers == 0, then we do all the work ourselves */    if(nhelpers == -1) {	int ncpu_online = sysconf(_SC_NPROCESSORS_ONLN);	if(ncpu_online > 2) {	    nhelpers = ncpu_online - 1;	} else {	    /*	     * if we have 2 CPUs or less, then create 1 helper, since	     * we still want to deal with head-of-queue problem.	     */	    nhelpers = 1;	}    }    if(nhelpers > 0) {	openswan_log("starting up %d cryptographic helpers", nhelpers);	pc_workers = alloc_bytes(sizeof(*pc_workers)*nhelpers				 , "pluto helpers");	pc_workers_cnt = nhelpers;		for(i=0; i<nhelpers; i++) {	    init_crypto_helper(&pc_workers[i], i);	}    } else {	openswan_log("no helpers will be started, all cryptographic operations will be done inline");    }	    pc_worker_num = 0;}void pluto_crypto_helper_sockets(fd_set *readfds){    int cnt;    struct pluto_crypto_worker *w = pc_workers;    for(cnt = 0; cnt < pc_workers_cnt; cnt++, w++) {	if(w->pcw_pid != -1 && !w->pcw_dead) {	    passert(w->pcw_pipe > 0);	    FD_SET(w->pcw_pipe, readfds);	}    }}int pluto_crypto_helper_ready(fd_set *readfds){    int cnt;    struct pluto_crypto_worker *w = pc_workers;    int ndes;    ndes = 0;    for(cnt = 0; cnt < pc_workers_cnt; cnt++, w++) {	if(w->pcw_pid != -1 && !w->pcw_dead) {	    passert(w->pcw_pipe > 0);	    if(FD_ISSET(w->pcw_pipe, readfds)) {		handle_helper_comm(w);		ndes++;	    }	}    }        return ndes;}/* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */

⌨️ 快捷键说明

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