Exemplo n.º 1
0
/*
 * Find an empty file descriptor entry, and mark it busy.
 */
int get_unused_fd(void)
{
	struct files_struct * files = current->files;
	int fd, error;

  	error = -EMFILE;
	write_lock(&files->file_lock);

repeat:
 	fd = find_next_zero_bit(files->open_fds, 
				files->max_fdset, 
				files->next_fd);

	/*
	 * N.B. For clone tasks sharing a files structure, this test
	 * will limit the total number of files that can be opened.
	 */
	if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
		goto out;

	/* Do we need to expand the fdset array? */
	if (fd >= files->max_fdset) {
		error = expand_fdset(files, fd);
		if (!error) {
			error = -EMFILE;
			goto repeat;
		}
		goto out;
	}
	
	/* 
	 * Check whether we need to expand the fd array.
	 */
	if (fd >= files->max_fds) {
		error = expand_fd_array(files, fd);
		if (!error) {
			error = -EMFILE;
			goto repeat;
		}
		goto out;
	}

	FD_SET(fd, files->open_fds);
	FD_CLR(fd, files->close_on_exec);
	files->next_fd = fd + 1;
#if 1
	/* Sanity check */
	if (files->fd[fd] != NULL) {
		printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
		files->fd[fd] = NULL;
	}
#endif
	error = fd;

out:
	write_unlock(&files->file_lock);
	return error;
}
Exemplo n.º 2
0
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
{
	struct files_struct *oldf, *newf;
	struct file **old_fds, **new_fds;
	int open_files, nfds, size, i, error = 0;

	/*
	 * A background process may not have any files ...
	 */
	oldf = current->files;
	if (!oldf)
		goto out;

	if (clone_flags & CLONE_FILES) {
		atomic_inc(&oldf->count);
		goto out;
	}

	/*
	 * Note: we may be using current for both targets (See exec.c)
	 * This works because we cache current->files (old) as oldf. Don't
	 * break this.
	 */
	tsk->files = NULL;
	error = -ENOMEM;
	newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
	if (!newf) 
		goto out;

	atomic_set(&newf->count, 1);

	newf->file_lock	    = SPIN_LOCK_UNLOCKED;
	newf->next_fd	    = 0;
	newf->max_fds	    = NR_OPEN_DEFAULT;
	newf->max_fdset	    = __FD_SETSIZE;
	newf->close_on_exec = &newf->close_on_exec_init;
	newf->open_fds	    = &newf->open_fds_init;
	newf->fd	    = &newf->fd_array[0];

	/* We don't yet have the oldf readlock, but even if the old
           fdset gets grown now, we'll only copy up to "size" fds */
	size = oldf->max_fdset;
	if (size > __FD_SETSIZE) {
		newf->max_fdset = 0;
		spin_lock(&newf->file_lock);
		error = expand_fdset(newf, size-1);
		spin_unlock(&newf->file_lock);
		if (error)
			goto out_release;
	}
	spin_lock(&oldf->file_lock);

	open_files = count_open_files(oldf, size);

	/*
	 * Check whether we need to allocate a larger fd array.
	 * Note: we're not a clone task, so the open count won't
	 * change.
	 */
	nfds = NR_OPEN_DEFAULT;
	if (open_files > nfds) {
		spin_unlock(&oldf->file_lock);
		newf->max_fds = 0;
		spin_lock(&newf->file_lock);
		error = expand_fd_array(newf, open_files-1);
		spin_unlock(&newf->file_lock);
		if (error) 
			goto out_release;
		nfds = newf->max_fds;
		spin_lock(&oldf->file_lock);
	}

	old_fds = oldf->fd;
	new_fds = newf->fd;

	memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8);
	memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8);

	for (i = open_files; i != 0; i--) {
		struct file *f = *old_fds++;
		if (f)
			get_file(f);
		*new_fds++ = f;
	}
	spin_unlock(&oldf->file_lock);

	/* compute the remainder to be cleared */
	size = (newf->max_fds - open_files) * sizeof(struct file *);

	/* This is long word aligned thus could use a optimized version */ 
	memset(new_fds, 0, size); 

	if (newf->max_fdset > open_files) {
		int left = (newf->max_fdset-open_files)/8;
		int start = open_files / (8 * sizeof(unsigned long));

		memset(&newf->open_fds->fds_bits[start], 0, left);
		memset(&newf->close_on_exec->fds_bits[start], 0, left);
	}

	tsk->files = newf;
	error = 0;
out:
	return error;

out_release:
	free_fdset (newf->close_on_exec, newf->max_fdset);
	free_fdset (newf->open_fds, newf->max_fdset);
	kmem_cache_free(files_cachep, newf);
	goto out;
}
Exemplo n.º 3
0
void udp_relayX(Connection *Conn,int csc,int csv[])
{	int svsock;
	int sockv[1024],readyv[1024],sx; /* must be lt/eq FD_SESIZE */
	int nsock; /* number of clients */
	CStr(buff,0x8000);
	int rcc,wcc;
	int nready;
	CStr(ihost,64);
	int iport;
	CStr(svhost,64);
	int svport;
	const char *clhost;
	int clport;
	UDP_Assoc *ua;
	UDP_Assoc *udpav[MAXASSOC*4]; /**/
	int udpxv[MAXASSOC*4];
	int lastrelay,idle;
	const char *aaddr;
	int svportmap;
	int portnumv[64];
	int csi;
	int istcp[MAXASSOC];
	int ccc = 0; /* tcp clients */
	int usocks = 0; /* UDP SOCKS */
	int update = 0;
	int ai;

	/* is this necessary or effective ? */
	socks_addservers();

	if( MAXASSOC < UDPRELAY_MAXASSOC ){
		UDPRELAY_MAXASSOC = MAXASSOC;
	}
	sv1log("MAXIMA=udprelay:%d (max. udp assoc.)\n",UDPRELAY_MAXASSOC);

	if( (aaddr = gethostaddr(DST_HOST)) == NULL ){
		sv1log("#### ERROR: bad destination host [%s]\n",DST_HOST);
		return;
	}
	strcpy(svhost,aaddr);
	svport = DST_PORT;
	svportmap = DFLT_PORTMAP;
	if( svportmap ){
		/* get port numbers of incoming ports ... */
		for( csi = 0; csi < csc; csi++ ){
			portnumv[csi] = sockPort(csv[csi]) + svportmap;
			portnumv[csi] &= ~0x40000000; /* clear IS_PORTMAP */
		}
	}

	expand_fdset(MAXASSOC);
	uassocv = (UDP_Assoc**)calloc(MAXASSOC+1,sizeof(UDP_Assoc*));
	for( csi = 0; csi < csc; csi++ )
		sockv[csi] = csv[csi];
	for( csi = 0; csi < csc; csi++ )
		istcp[csi] = !isUDPsock(sockv[csi]);
	nsock = 0;
	lastrelay = 0;

	for(;;){
UPDATE:
		if( update ){
			int ai;
			update = 0;
			ccc = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				if( ua->ua_clpriv ){
				udpxv[csc + ccc] = ai;
				udpav[csc + ccc] = ua;
				sockv[csc + ccc++] = ua->ua_clsock;
				}
			}
			nsock = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				udpxv[csc+ccc + nsock] = ai;
				udpav[csc+ccc + nsock] = ua;
				sockv[csc+ccc + nsock++] = ua->ua_svsock;
			}
			usocks = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				int ns = csc+ccc+nsock;
				if( 0 <= ua->ua_svSOCKS ){
					udpxv[ns+usocks] = ai;
					udpav[ns+usocks] = ua;
					sockv[ns+usocks] = ua->ua_svSOCKS;
					usocks++;
				}
			}
		}
		/*
		nready = PollIns(10*1000,csc+nsock+ccc,sockv,readyv);
		*/
		nready = PollIns(10*1000,csc+ccc+nsock+usocks,sockv,readyv);
		if( nready < 0 ){
			/*
			sv1log("UDPRELAY: ABORT PollIns(%d) = %d\n",nready);
			*/
			sv1log("UDPRELAY: ABORT PollIns(%d+%d+%d+%d)=%d\n",
				csc,ccc,nsock,usocks,nready);
			for( ai = 0; ai < csc+ccc+nsock+usocks; ai++ ){
				sv1log("[%2d] %d\n",ai,sockv[ai]);
			}
			break;
		}
		if( nready == 0 ){
			idle = time(0) - lastrelay;
			if( SERVER_TIMEOUT && lastrelay )
			if( SERVER_TIMEOUT < idle){
				sv1log("UDPRELAY: SERVER TIMEOUT (idle %ds)\n",
					idle);
				break;
			}
			killTimeouts(uassocv);
			/*
			nsock = getsocks(uassocv,&sockv[csc]);
			*/
			update = 1;
			continue;
		}
		lastrelay = time(0);

		for( sx = 0; sx < csc; sx++ )
		if( 0 < readyv[sx] && istcp[sx] ){
			CStr(local,256);
			CStr(remote,256);
			int clsk;
			strcpy(remote,"*:*");
			strcpy(local,"*:*");
			clsk = VSocket(Conn,"ACPT/",sockv[sx],AVStr(local),AVStr(remote),"");
/*
			setNonblockingIO("UDPRELAY-CL",clsk,1);
*/
			SetNonblockingIO("UDPRELAY-CL",clsk,1);
			iport = getpeerAddr(clsk,AVStr(ihost));
			if( clsk <= 0 || iport <= 0 ){
				sv1log("UDPRELAY: accept() errno=%d\n",errno);
				continue;
			}
			if( svportmap ){
				svport = portnumv[sx];
			}
			ua = newUA(Conn,uassocv,ihost,iport,svhost,svport);
			ua->ua_clsock = clsk;
			ua->ua_clpriv = 1;
			update = 1;
		}else
		if( 0 < readyv[sx] ){
			rcc = recvFromA(sockv[sx],AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport);
			if( rcc <= 0 ){
				sv1log("UDPRELAY: recv() == 0, errno=%d\n",errno);
				break;
			}
			if( svportmap ){
				svport = portnumv[sx];
			}
			ua = findUAbysrc(uassocv,ihost,iport,svhost,svport);
			if( ua == NULL ){
				ua = newUA(Conn,uassocv,ihost,iport,svhost,svport);
				if( ua == NULL ){
					continue;
				}
				ua->ua_clsock = sockv[sx];
				if( ua->ua_svsock < 0 )
					continue;
				/*
				nsock = getsocks(uassocv,&sockv[csc]);
				*/
				update = 1;
			}
			toServ(ua,buff,rcc,svhost,svport,ihost,iport);
			/*
			ua->ua_mtime = time(0);
			ua->ua_upcnt++;
			ua->ua_upbytes += rcc;
			if( UDPRELAY_RPORT_FIX )
				wcc = Send(ua->ua_svsock,buff,rcc);
			else	wcc = SendTo(ua->ua_svsock,buff,rcc,svhost,svport);
			Verbose("TO SERV#%d: %s:%d %3d> %s:%d\n",
				ua->ua_id,ihost,iport,rcc,svhost,svport);
			*/
			if( nready == 1 )
				continue;
		}

		for( sx = csc; sx < csc+ccc; sx++ )
		if( 0 < readyv[sx] ){
			rcc = recv(sockv[sx],buff,sizeof(buff),0);
			if( rcc <= 0 ){
				int ux = getUAx(uassocv,udpav[sx]);
				if( ux < 0 ){
					sv1log("## delUA-CL(%d)?\n",ux);
					continue;
				}
				delUA(uassocv,ux,"TCPreset-CL",1);
				/* here udpxv[] becomes inconsistent */
				update = 1;
			}else{
				ua = udpav[sx];
				toServ(ua,buff,rcc,svhost,svport,NULL,0);
			}
		}

		/*
		for( sx = csc; sx < csc+nsock; sx++ ){
		*/
		for( sx = csc+ccc; sx < csc+ccc+nsock; sx++ ){
			if( readyv[sx] <= 0 )
				continue;
			ua = udpav[sx];
			svsock = sockv[sx];

			if( 0 <= ua->ua_svSOCKS )
			rcc = RecvFrom(svsock,buff,sizeof(buff),AVStr(ihost),&iport);
			else
			rcc = recvFromA(svsock,AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport);

			if( rcc <= 0 ){
				if( ua->ua_svtcp ){
					int ux = getUAx(uassocv,udpav[sx]);
					if( ux < 0 ){
						sv1log("## delUA-SV(%d)?\n",ux);
						continue;
					}
					delUA(uassocv,ux,"TCPreset-SV",1);
					update = 1;
				}
				readyv[sx] = -1;
				continue;
			}

			/*
			ua = findUAbysock(uassocv,svsock);
			*/
			ua->ua_mtime = time(0);
			ua->ua_downcnt++;
			ua->ua_downbytes += rcc;
			clhost = ua->ua_clhost;
			clport = ua->ua_clport;
			/*
			wcc = SendTo(ua->ua_clsock,buff,rcc,clhost,clport);
			*/
			wcc = sendToA(ua->ua_clsock,buff,rcc,0,clhost,clport);

			Verbose("TO CLNT#%d: %s:%d <%-3d %s:%d\n",
				ua->ua_id,clhost,clport,rcc,ihost,iport);
		}
		for( sx = csc+ccc+nsock; sx < csc+ccc+nsock+usocks; sx++ ){
			int ux;
			if( readyv[sx] <= 0 )
				continue;
			ua = udpav[sx];
			ux = getUAx(uassocv,udpav[sx]);
			if( ux < 0 ){
				sv1log("## delUA-CTL(%d)?\n",ux);
				continue;
			}
			sv1log("## detected disconn. by SOCKS CTL [%d]\n",ux);
			delUA(uassocv,ux,"SOCKSCTLreset-SV",1);
			update = 1;
		}
	}
}