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

📄 timod.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		SOLD("req size ok");		buf = getpage();		if (copy_from_user(buf, ctl_buf, ctl_len)) {			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);			putpage(buf);			return 0;		}#ifdef DEBUG_SOLARIS				{			char * ptr = buf;			int len = ctl_len;			printk("returned data (%d bytes): ",len);			while( len-- ) {				if (!(len & 7))					printk(" ");				printk("%02x",(unsigned char)*ptr++);			}			printk("\n");		}#endif		SOLD("got ctl data");		args[0] = fd;		args[1] = (long)buf+req.DEST_offset;		args[2] = req.DEST_length;		oldflags = filp->f_flags;		filp->f_flags &= ~O_NONBLOCK;		SOLD("calling CONNECT");		set_fs(KERNEL_DS);		error = sys_socketcall(SYS_CONNECT, args);		set_fs(old_fs);		filp->f_flags = oldflags;		SOLD("CONNECT done");		if (!error) {			struct T_conn_con *con;			SOLD("no error");			it = timod_mkctl(ctl_len);			if (!it) {				putpage(buf);				return -ENOMEM;			}			con = (struct T_conn_con *)&it->type;#ifdef DEBUG_SOLARIS						{				char * ptr = buf;				int len = ctl_len;				printk("returned data (%d bytes): ",len);				while( len-- ) {					if (!(len & 7))						printk(" ");					printk("%02x",(unsigned char)*ptr++);				}				printk("\n");			}#endif			memcpy(con, buf, ctl_len);			SOLD("copied ctl_buf");			con->PRIM_type = T_CONN_CON;			sock->state = TS_DATA_XFER;		} else {			struct T_discon_ind *dis;			SOLD("some error");			it = timod_mkctl(sizeof(*dis));			if (!it) {				putpage(buf);				return -ENOMEM;			}			SOLD("got primsg");			dis = (struct T_discon_ind *)&it->type;			dis->PRIM_type = T_DISCON_IND;			dis->DISCON_reason = -error;	/* FIXME: convert this as in iABI_errors() */			dis->SEQ_number = 0;		}		putpage(buf);		timod_ok(fd, T_CONN_REQ);		it->pri = 0;		timod_queue_end(fd, it);		SOLD("CONNECT done");		return 0;	}	case T_OPTMGMT_REQ:	{		struct T_optmgmt_req req;		SOLD("OPTMGMT_REQ");		if (copy_from_user(&req, ctl_buf, sizeof(req)))			return -EFAULT;		SOLD("got req");		return timod_optmgmt(fd, req.MGMT_flags,				req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,				req.OPT_length, 1);	}	case T_UNITDATA_REQ:	{		struct T_unitdata_req req;				int err;		SOLD("T_UNITDATA_REQ");		if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {			timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);			return 0;		}		SOLD("state ok");		if (copy_from_user(&req, ctl_buf, sizeof(req))) {			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);			return 0;		}		SOLD("got ctl req");#ifdef DEBUG_SOLARIS				{			char * ptr = ctl_buf+req.DEST_offset;			int len = req.DEST_length;			printk("socket address (%d bytes): ",len);			while( len-- ) {				char c;				if (get_user(c,ptr))					printk("??");				else					printk("%02x",(unsigned char)c);				ptr++;			}			printk("\n");		}#endif				err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr*)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);		if (err == data_len)			return 0;		if(err >= 0) {			printk("timod: sendto failed to send all the data\n");			return 0;		}		timod_error(fd, T_CONN_REQ, TSYSERR, -err);		return 0;	}	default:		printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);		break;	}	return -EINVAL;}int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len,			char *data_buf, int data_maxlen, s32 *data_len, int *flags_p){	int error;	int oldflags;	struct file *filp;	struct inode *ino;	struct sol_socket_struct *sock;	struct T_unitdata_ind udi;	mm_segment_t old_fs = get_fs();	long args[6];	char *tmpbuf;	int tmplen;	int (*sys_socketcall)(int, unsigned long *) =		(int (*)(int, unsigned long *))SYS(socketcall);	int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *);		SOLD("entry");	SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));	filp = current->files->fd[fd];	ino = filp->f_dentry->d_inode;	sock = (struct sol_socket_struct *)filp->private_data;	SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));	if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM		&& sock->state == TS_IDLE) {		SOLD("calling LISTEN");		args[0] = fd;		args[1] = -1;		set_fs(KERNEL_DS);		sys_socketcall(SYS_LISTEN, args);		set_fs(old_fs);		SOLD("LISTEN done");	}	if (!(filp->f_flags & O_NONBLOCK)) {		poll_table wait_table, *wait;		poll_initwait(&wait_table);		wait = &wait_table;		for(;;) {			SOLD("loop");			set_current_state(TASK_INTERRUPTIBLE);			/* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 			/* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 			/* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 			/* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ 			/* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ 			/* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ 			if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))				break;			SOLD("cond 1 passed");			if (			#if 1				*flags_p != MSG_HIPRI &&			#endif				((filp->f_op->poll(filp, wait) & POLLIN) ||				(filp->f_op->poll(filp, NULL) & POLLIN) ||				signal_pending(current))			) {				break;			}			if( *flags_p == MSG_HIPRI ) {				SOLD("avoiding lockup");				break ;			}			if(wait_table.error) {				SOLD("wait-table error");				poll_freewait(&wait_table);				return wait_table.error;			}			SOLD("scheduling");			schedule();		}		SOLD("loop done");		current->state = TASK_RUNNING;		poll_freewait(&wait_table);		if (signal_pending(current)) {			SOLD("signal pending");			return -EINTR;		}	}	if (ctl_maxlen >= 0 && sock->pfirst) {		struct T_primsg *it = sock->pfirst;		int l = min_t(int, ctl_maxlen, it->length);		SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);		SOLD("purting ctl data");		if(copy_to_user(ctl_buf,			(char*)&it->type + sock->offset, l))			return -EFAULT;		SOLD("pur it");		if(put_user(l, ctl_len))			return -EFAULT;		SOLD("set ctl_len");		*flags_p = it->pri;		it->length -= l;		if (it->length) {			SOLD("more ctl");			sock->offset += l;			return MORECTL;		} else {			SOLD("removing message");			sock->pfirst = it->next;			if (!sock->pfirst)				sock->plast = NULL;			SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));			mykfree(it);			sock->offset = 0;			SOLD("ctl done");			return 0;		}	}	*flags_p = 0;	if (ctl_maxlen >= 0) {		SOLD("ACCEPT perhaps?");		if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) {			struct T_conn_ind ind;			char *buf = getpage();			int len = BUF_SIZE;			SOLD("trying ACCEPT");			if (put_user(ctl_maxlen - sizeof(ind), ctl_len))				return -EFAULT;			args[0] = fd;			args[1] = (long)buf;			args[2] = (long)&len;			oldflags = filp->f_flags;			filp->f_flags |= O_NONBLOCK;			SOLD("calling ACCEPT");			set_fs(KERNEL_DS);			error = sys_socketcall(SYS_ACCEPT, args);			set_fs(old_fs);			filp->f_flags = oldflags;			if (error < 0) {				SOLD("some error");				putpage(buf);				return error;			}			if (error) {				SOLD("connect");				putpage(buf);				if (sizeof(ind) > ctl_maxlen) {					SOLD("generating CONN_IND");					ind.PRIM_type = T_CONN_IND;					ind.SRC_length = len;					ind.SRC_offset = sizeof(ind);					ind.OPT_length = ind.OPT_offset = 0;					ind.SEQ_number = error;					if(copy_to_user(ctl_buf, &ind, sizeof(ind))||					   put_user(sizeof(ind)+ind.SRC_length,ctl_len))						return -EFAULT;					SOLD("CONN_IND created");				}				if (data_maxlen >= 0)					put_user(0, data_len);				SOLD("CONN_IND done");				return 0;			}			if (len>ctl_maxlen) {				SOLD("data don't fit");				putpage(buf);				return -EFAULT;		/* XXX - is this ok ? */			}			if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){				SOLD("can't copy data");				putpage(buf);				return -EFAULT;			}			SOLD("ACCEPT done");			putpage(buf);		}	}	SOLD("checking data req");	if (data_maxlen <= 0) {		if (data_maxlen == 0)			put_user(0, data_len);		if (ctl_maxlen >= 0)			put_user(0, ctl_len);		return -EAGAIN;	}	SOLD("wants data");	if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {		SOLD("udi fits");		tmpbuf = ctl_buf + sizeof(udi);		tmplen = ctl_maxlen - sizeof(udi);	} else {		SOLD("udi does not fit");		tmpbuf = NULL;		tmplen = 0;	}	if (put_user(tmplen, ctl_len))		return -EFAULT;	SOLD("set ctl_len");	oldflags = filp->f_flags;	filp->f_flags |= O_NONBLOCK;	SOLD("calling recvfrom");	sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);	error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr*)tmpbuf, ctl_len);	filp->f_flags = oldflags;	if (error < 0)		return error;	SOLD("error >= 0" ) ;	if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {		SOLD("generating udi");		udi.PRIM_type = T_UNITDATA_IND;		get_user(udi.SRC_length, ctl_len);		udi.SRC_offset = sizeof(udi);		udi.OPT_length = udi.OPT_offset = 0;		copy_to_user(ctl_buf, &udi, sizeof(udi));		put_user(sizeof(udi)+udi.SRC_length, ctl_len);		SOLD("udi done");	} else		put_user(0, ctl_len);	put_user(error, data_len);	SOLD("done");	return 0;}asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3){	struct file *filp;	struct inode *ino;	struct strbuf *ctlptr, *datptr;	struct strbuf ctl, dat;	int *flgptr;	int flags;	int error = -EBADF;	SOLD("entry");	lock_kernel();	if(fd >= NR_OPEN) goto out;	filp = current->files->fd[fd];	if(!filp) goto out;	ino = filp->f_dentry->d_inode;	if (!ino) goto out;	if (!ino->i_sock)		goto out;	ctlptr = (struct strbuf *)A(arg1);	datptr = (struct strbuf *)A(arg2);	flgptr = (int *)A(arg3);	error = -EFAULT;	if (ctlptr) {		if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || 		    put_user(-1,&ctlptr->len))			goto out;	} else		ctl.maxlen = -1;	if (datptr) {		if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || 		    put_user(-1,&datptr->len))			goto out;	} else		dat.maxlen = -1;	if (get_user(flags,flgptr))		goto out;	switch (flags) {	case 0:	case MSG_HIPRI:	case MSG_ANY:	case MSG_BAND:		break;	default:		error = -EINVAL;		goto out;	}	error = timod_getmsg(fd,(char*)A(ctl.buf),ctl.maxlen,&ctlptr->len,				(char*)A(dat.buf),dat.maxlen,&datptr->len,&flags);	if (!error && put_user(flags,flgptr))		error = -EFAULT;out:	unlock_kernel();	SOLD("done");	return error;}asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3){	struct file *filp;	struct inode *ino;	struct strbuf *ctlptr, *datptr;	struct strbuf ctl, dat;	int flags = (int) arg3;	int error = -EBADF;	SOLD("entry");	lock_kernel();	if(fd >= NR_OPEN) goto out;	filp = current->files->fd[fd];	if(!filp) goto out;	ino = filp->f_dentry->d_inode;	if (!ino) goto out;	if (!ino->i_sock &&		(MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1))		goto out;	ctlptr = (struct strbuf *)A(arg1);	datptr = (struct strbuf *)A(arg2);	error = -EFAULT;	if (ctlptr) {		if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))			goto out;		if (ctl.len < 0 && flags) {			error = -EINVAL;			goto out;		}	} else {		ctl.len = 0;		ctl.buf = 0;	}	if (datptr) {		if (copy_from_user(&dat,datptr,sizeof(dat)))			goto out;	} else {		dat.len = 0;		dat.buf = 0;	}	error = timod_putmsg(fd,(char*)A(ctl.buf),ctl.len,				(char*)A(dat.buf),dat.len,flags);out:	unlock_kernel();	SOLD("done");	return error;}

⌨️ 快捷键说明

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