예제 #1
0
asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
{
	struct file *filp;
	struct inode *ino;
	struct strbuf __user *ctlptr;
	struct strbuf __user *datptr;
	struct strbuf ctl, dat;
	int flags = (int) arg3;
	int error = -EBADF;
	struct fdtable *fdt;

	SOLD("entry");
	lock_kernel();
	if (fd >= sysctl_nr_open)
		goto out;

	fdt = files_fdtable(current->files);
	filp = fdt->fd[fd];
	if(!filp) goto out;

	ino = filp->f_dentry->d_inode;
	if (!ino) goto out;

	if (!S_ISSOCK(ino->i_mode) &&
		(imajor(ino) != 30 || iminor(ino) != 1))
		goto out;

	ctlptr = A(arg1);
	datptr = 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,A(ctl.buf),ctl.len,
				A(dat.buf),dat.len,flags);
out:
	unlock_kernel();
	SOLD("done");
	return error;
}
예제 #2
0
파일: timod.c 프로젝트: dduval/kernel-rhel3
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;

	read_lock(&current->files->file_lock);
	filp = fcheck(fd);
	read_unlock(&current->files->file_lock);
	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;
}
예제 #3
0
static void timod_queue(unsigned int fd, struct T_primsg *it)
{
	struct sol_socket_struct *sock;

	SOLD("queuing primsg");
	sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
	it->next = sock->pfirst;
	sock->pfirst = it;
	if (!sock->plast)
		sock->plast = it;
	timod_wake_socket(fd);
	SOLD("done");
}
예제 #4
0
static void timod_wake_socket(unsigned int fd)
{
	struct socket *sock;

	SOLD("wakeing socket");
	sock = &current->files->fd[fd]->f_dentry->d_inode->u.socket_i;
	wake_up_interruptible(&sock->wait);
	read_lock(&sock->sk->callback_lock);
	if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
		__kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
	read_unlock(&sock->sk->callback_lock);
	SOLD("done");
}
예제 #5
0
static void timod_queue_end(unsigned int fd, struct T_primsg *it)
{
	struct sol_socket_struct *sock;

	SOLD("queuing primsg at end");
	sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
	it->next = NULL;
	if (sock->plast)
		sock->plast->next = it;
	else
		sock->pfirst = it;
	sock->plast = it;
	SOLD("done");
}
예제 #6
0
static struct T_primsg *timod_mkctl(int size)
{
	struct T_primsg *it;

	SOLD("creating primsg");
	it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
	if (it) {
		SOLD("got it");
		it->pri = MSG_HIPRI;
		it->length = size;
		PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
	}
	return it;
}
예제 #7
0
파일: timod.c 프로젝트: JBTech/ralink_sdk
static void timod_wake_socket(unsigned int fd)
{
	struct socket *sock;
	struct fdtable *fdt;

	SOLD("wakeing socket");
	fdt = files_fdtable(current->files);
	sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
	wake_up_interruptible(&sock->wait);
	read_lock(&sock->sk->sk_callback_lock);
	if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
		__kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
	read_unlock(&sock->sk->sk_callback_lock);
	SOLD("done");
}
예제 #8
0
static void timod_ok(unsigned int fd, int prim)
{
	struct T_primsg *it;
	struct T_ok_ack *ok;
	
	SOLD("creating ok ack");
	it = timod_mkctl(sizeof(*ok));
	if (it) {
		SOLD("got it");
		ok = (struct T_ok_ack *)&it->type;
		ok->PRIM_type = T_OK_ACK;
		ok->CORRECT_prim = prim;
		timod_queue(fd, it);
	}
	SOLD("done");
}
예제 #9
0
static void putpage(char *p)
{
	SOLD("putting page");
	p = p - BUF_OFFSET;
	SCHECK_MAGIC(p,BUFPAGE_MAGIC);
	SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
	spin_lock(&timod_pagelock);
	if (page) {
		spin_unlock(&timod_pagelock);
		free_page((unsigned long)p);
		SOLD("freed it");
	} else {
		page = p;
		spin_unlock(&timod_pagelock);
		SOLD("cached it");
	}
}
예제 #10
0
static void timod_error(unsigned int fd, int prim, int terr, int uerr)
{
	struct T_primsg *it;
	
	SOLD("making error");
	it = timod_mkctl(sizeof(struct T_error_ack));
	if (it) {
		struct T_error_ack *err = (struct T_error_ack *)&it->type;
		
		SOLD("got it");
		err->PRIM_type = T_ERROR_ACK;
		err->ERROR_prim = prim;
		err->TLI_error = terr;
		err->UNIX_error = uerr; /* FIXME: convert this */
		timod_queue(fd, it);
	}
	SOLD("done");
}
예제 #11
0
static char *getpage( void )
{
	char *r;
	SOLD("getting page");
	spin_lock(&timod_pagelock);
	if (page) {
		r = page;
		page = NULL;
		spin_unlock(&timod_pagelock);
		SOLD("got cached");
		return r + BUF_OFFSET;
	}
	spin_unlock(&timod_pagelock);
	SOLD("getting new");
	r = (char *)__get_free_page(GFP_KERNEL);
	PUT_MAGIC(r,BUFPAGE_MAGIC);
	PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
	return r + BUF_OFFSET;
}
예제 #12
0
void * mykmalloc(size_t s, int gfp)
{
	static char * page;
	static size_t free = 0;
	void * r;
	s = ((s + 63) & ~63);
	if( s > PAGE_SIZE ) {
		SOLD("too big size, calling real kmalloc");
		return kmalloc(s, gfp);
	}
	if( s > free ) {
		/* we are wasting memory, but we don't care */
		page = (char *)__get_free_page(gfp);
		free = PAGE_SIZE;
	}
	r = page;
	page += s;
	free -= s;
	return r;
}
예제 #13
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;
}
예제 #14
0
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;
}
예제 #15
0
int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
			char *data_buf, int data_len, int flags)
{
	int ret, error, terror;
	char *buf;
	struct file *filp;
	struct inode *ino;
	struct sol_socket_struct *sock;
	mm_segment_t old_fs = get_fs();
	long args[6];
	int (*sys_socketcall)(int, unsigned long *) =
		(int (*)(int, unsigned long *))SYS(socketcall);
	int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) =
		(int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto);
	filp = current->files->fd[fd];
	ino = filp->f_dentry->d_inode;
	sock = (struct sol_socket_struct *)filp->private_data;
	SOLD("entry");
	if (get_user(ret, (int *)A(ctl_buf)))
		return -EFAULT;
	switch (ret) {
	case T_BIND_REQ:
	{
		struct T_bind_req req;
		
		SOLDD(("bind %016lx(%016lx)\n", sock, filp));
		SOLD("T_BIND_REQ");
		if (sock->state != TS_UNBND) {
			timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
			return 0;
		}
		SOLD("state ok");
		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
			timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
			return 0;
		}
		SOLD("got ctl req");
		if (req.ADDR_offset && req.ADDR_length) {
			if (req.ADDR_length > BUF_SIZE) {
				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
				return 0;
			}
			SOLD("req size ok");
			buf = getpage();
			if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
				putpage(buf);
				return 0;
			}
			SOLD("got ctl data");
			args[0] = fd;
			args[1] = (long)buf;
			args[2] = req.ADDR_length;
			SOLD("calling BIND");
			set_fs(KERNEL_DS);
			error = sys_socketcall(SYS_BIND, args);
			set_fs(old_fs);
			putpage(buf);
			SOLD("BIND returned");
		} else 
			error = 0;
		if (!error) {
			struct T_primsg *it;
			if (req.CONIND_number) {
	  			args[0] = fd;
  				args[1] = req.CONIND_number;
  				SOLD("calling LISTEN");
  				set_fs(KERNEL_DS);
	  			error = sys_socketcall(SYS_LISTEN, args);
  				set_fs(old_fs);
  				SOLD("LISTEN done");
  			}
			it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
			if (it) {
				struct T_bind_ack *ack;

				ack = (struct T_bind_ack *)&it->type;
				ack->PRIM_type = T_BIND_ACK;
				ack->ADDR_offset = sizeof(*ack);
				ack->ADDR_length = sizeof(struct sockaddr);
				ack->CONIND_number = req.CONIND_number;
				args[0] = fd;
				args[1] = (long)(ack+sizeof(*ack));
				args[2] = (long)&ack->ADDR_length;
				set_fs(KERNEL_DS);
				sys_socketcall(SYS_GETSOCKNAME,args);
				set_fs(old_fs);
				sock->state = TS_IDLE;
				timod_ok(fd, T_BIND_REQ);
				timod_queue_end(fd, it);
				SOLD("BIND done");
				return 0;
			}
		}
		SOLD("some error");
		switch (error) {
			case -EINVAL:
				terror = TOUTSTATE;
				error = 0;
				break;
			case -EACCES:
				terror = TACCES;
				error = 0;
				break;
			case -EADDRNOTAVAIL:
			case -EADDRINUSE:
				terror = TNOADDR;
				error = 0;
				break;
			default:
				terror = TSYSERR;
				break;
		}
		timod_error(fd, T_BIND_REQ, terror, -error);
		SOLD("BIND done");
		return 0;
	}
	case T_CONN_REQ:
	{
		struct T_conn_req req;
		unsigned short oldflags;
		struct T_primsg *it;
		SOLD("T_CONN_REQ");
		if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
			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");
		if (ctl_len > BUF_SIZE) {
			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
			return 0;
		}
		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;
}
예제 #16
0
static int timod_optmgmt(unsigned int fd, int flag, char *opt_buf, int opt_len, int do_ret)
{
	int error, failed;
	int ret_space, ret_len;
	long args[5];
	char *ret_pos,*ret_buf;
	int (*sys_socketcall)(int, unsigned long *) =
		(int (*)(int, unsigned long *))SYS(socketcall);
	mm_segment_t old_fs = get_fs();

	SOLD("entry");
	SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
	if (!do_ret && (!opt_buf || opt_len <= 0))
		return 0;
	SOLD("getting page");
	ret_pos = ret_buf = getpage();
	ret_space = BUF_SIZE;
	ret_len = 0;
	
	error = failed = 0;
	SOLD("looping");
	while(opt_len >= sizeof(struct opthdr)) {
		struct opthdr *opt;
		int orig_opt_len; 
		SOLD("loop start");
		opt = (struct opthdr *)ret_pos; 
		if (ret_space < sizeof(struct opthdr)) {
			failed = TSYSERR;
			break;
		}
		SOLD("getting opthdr");
		if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
			opt->len > opt_len) {
			failed = TBADOPT;
			break;
		}
		SOLD("got opthdr");
		if (flag == T_NEGOTIATE) {
			char *buf;
			
			SOLD("handling T_NEGOTIATE");
			buf = ret_pos + sizeof(struct opthdr);
			if (ret_space < opt->len + sizeof(struct opthdr) ||
				copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
				failed = TSYSERR;
				break;
			}
			SOLD("got optdata");
			args[0] = fd;
			args[1] = opt->level;
			args[2] = opt->name;
			args[3] = (long)buf;
			args[4] = opt->len;
			SOLD("calling SETSOCKOPT");
			set_fs(KERNEL_DS);
			error = sys_socketcall(SYS_SETSOCKOPT, args);
			set_fs(old_fs);
			if (error) {
				failed = TBADOPT;
				break;
			}
			SOLD("SETSOCKOPT ok");
		}
		orig_opt_len = opt->len;
		opt->len = ret_space - sizeof(struct opthdr);
		if (opt->len < 0) {
			failed = TSYSERR;
			break;
		}
		args[0] = fd;
		args[1] = opt->level;
		args[2] = opt->name;
		args[3] = (long)(ret_pos+sizeof(struct opthdr));
		args[4] = (long)&opt->len;
		SOLD("calling GETSOCKOPT");
		set_fs(KERNEL_DS);
		error = sys_socketcall(SYS_GETSOCKOPT, args);
		set_fs(old_fs);;
		if (error) {
			failed = TBADOPT;
			break;
		}
		SOLD("GETSOCKOPT ok");
		ret_space -= sizeof(struct opthdr) + opt->len;
		ret_len += sizeof(struct opthdr) + opt->len;
		ret_pos += sizeof(struct opthdr) + opt->len;
		opt_len -= sizeof(struct opthdr) + orig_opt_len;
		opt_buf += sizeof(struct opthdr) + orig_opt_len;
		SOLD("loop end");
	}
	SOLD("loop done");
	if (do_ret) {
		SOLD("generating ret msg");
		if (failed)
			timod_error(fd, T_OPTMGMT_REQ, failed, -error);
		else {
			struct T_primsg *it;
			it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
			if (it) {
				struct T_optmgmt_ack *ack =
					(struct T_optmgmt_ack *)&it->type;
				SOLD("got primsg");
				ack->PRIM_type = T_OPTMGMT_ACK;
				ack->OPT_length = ret_len;
				ack->OPT_offset = sizeof(struct T_optmgmt_ack);
				ack->MGMT_flags = (failed ? T_FAILURE : flag);
				memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
					ret_buf, ret_len);
				timod_queue(fd, it);
			}
		}
	}
	SOLDD(("put_page %p\n", ret_buf));
	putpage(ret_buf);
	SOLD("done");	
	return 0;
}
예제 #17
0
파일: ioctl.c 프로젝트: sarnobat/knoppix
static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
                                    int len, int *len_p)
{
	int ret;
		
	switch (cmd & 0xff) {
	case 141: /* TI_OPTMGMT */
	{
		int i;
		u32 prim;
		SOLD("TI_OPMGMT entry");
		ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
		SOLD("timod_putmsg() returned");
		if (ret)
			return (-ret << 8) | TSYSERR;
		i = MSG_HIPRI;
		SOLD("calling timod_getmsg()");
		ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
		SOLD("timod_getmsg() returned");
		if (ret)
			return (-ret << 8) | TSYSERR;
		SOLD("ret ok");
		if (get_user(prim, (u32 *)A(arg)))
			return (EFAULT << 8) | TSYSERR;
		SOLD("got prim");
		if (prim == T_ERROR_ACK) {
			u32 tmp, tmp2;
			SOLD("prim is T_ERROR_ACK");
			if (get_user(tmp, (u32 *)A(arg)+3) ||
			    get_user(tmp2, (u32 *)A(arg)+2))
				return (EFAULT << 8) | TSYSERR;
			return (tmp2 << 8) | tmp;
		}
		SOLD("TI_OPMGMT return 0");
		return 0;
	}
	case 142: /* TI_BIND */
	{
		int i;
		u32 prim;
		SOLD("TI_BIND entry");
		ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
		SOLD("timod_putmsg() returned");
		if (ret)
			return (-ret << 8) | TSYSERR;
		len = 1024; /* Solaris allows arbitrary return size */
		i = MSG_HIPRI;
		SOLD("calling timod_getmsg()");
		ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
		SOLD("timod_getmsg() returned");
		if (ret)
			return (-ret << 8) | TSYSERR;
		SOLD("ret ok");
		if (get_user(prim, (u32 *)A(arg)))
			return (EFAULT << 8) | TSYSERR;
		SOLD("got prim");
		if (prim == T_ERROR_ACK) {
			u32 tmp, tmp2;
			SOLD("prim is T_ERROR_ACK");
			if (get_user(tmp, (u32 *)A(arg)+3) ||
			    get_user(tmp2, (u32 *)A(arg)+2))
				return (EFAULT << 8) | TSYSERR;
			return (tmp2 << 8) | tmp;
		}
		SOLD("no ERROR_ACK requested");
		if (prim != T_OK_ACK)
			return TBADSEQ;
		SOLD("OK_ACK requested");
		i = MSG_HIPRI;
		SOLD("calling timod_getmsg()");
		ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
		SOLD("timod_getmsg() returned");
		if (ret)
			return (-ret << 8) | TSYSERR;
		SOLD("TI_BIND return ok");
		return 0;
	}
	case 140: /* TI_GETINFO */
	case 143: /* TI_UNBIND */
	case 144: /* TI_GETMYNAME */
	case 145: /* TI_GETPEERNAME */
	case 146: /* TI_SETMYNAME */
	case 147: /* TI_SETPEERNAME */
		;
	}
	return TNOTSUPPORT;
}
예제 #18
0
파일: mri_zeropad.c 프로젝트: Gilles86/afni
MRI_IMAGE * mri_valpad_2D(  int nxbot , int nxtop ,
                            int nybot , int nytop , MRI_IMAGE *fim,
                            byte val)
{
   int nxold,nyold , nxnew,nynew , nx,ny ;
   int ii,jj , iibot,iitop , jjbot,jjtop ;
   MRI_IMAGE *vim ;

ENTRY("mri_valpad_2D") ;

   /*- check for user stupidity -*/

   if( fim == NULL ) RETURN(NULL) ;

   nx = fim->nx ; ny = fim->ny ;

   /*- special case: just copy input -*/

   if( nxbot == 0 && nybot == 0 &&
       nxtop == 0 && nytop == 0    ){

      vim = mri_copy( fim ) ;
      RETURN(vim) ;
   }

   nxold = nx ; nxnew = nxold + nxbot + nxtop ;  /* dimensions */
   nyold = ny ; nynew = nyold + nybot + nytop ;

   iibot = MAX(0,-nxbot) ; iitop = MIN(nxold,nxold+nxtop) ;  /* range of data  */
   jjbot = MAX(0,-nybot) ; jjtop = MIN(nyold,nyold+nytop) ;  /* in old dataset */

   if( nxnew < 1 || iibot >= iitop ||   /* check for reasonable sizes */
       nynew < 1 || jjbot >= jjtop   ){ /* and ranges of dataset     */

      fprintf(stderr,"*** mri_zeropad: can't cut image down to nothing!\n") ;
      RETURN(NULL) ;
   }

   vim = mri_new( nxnew , nynew , fim->kind ) ;
   MRI_COPY_AUX(vim,fim) ;
   memset( mri_data_pointer(vim) , val ,
           nxnew*nynew*mri_datum_size(vim->kind) ) ;

   /* macros for computing 1D subscripts from 2D indices */

#undef  SNEW  /* in case was defined in some stupid .h file */
#undef  SOLD
#define SNEW(i,j) ((i+nxbot)+(j+nybot)*nxnew)
#define SOLD(i,j) (i+j*nxold)

   switch( fim->kind ){  /* copy rows of old into new */

      default:
         fprintf(stderr,"*** mri_zeropad: unknown input datum=%d\n",fim->kind) ;
         mri_free(vim) ;
      RETURN(NULL) ;

      case MRI_byte:{
         byte *bnew = MRI_BYTE_PTR(vim), *bold = MRI_BYTE_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

      case MRI_rgb:{
         byte *bnew = MRI_RGB_PTR(vim), *bold = MRI_RGB_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ ){
               bnew[3*SNEW(ii,jj)  ] = bold[3*SOLD(ii,jj)  ] ;
               bnew[3*SNEW(ii,jj)+1] = bold[3*SOLD(ii,jj)+1] ;
               bnew[3*SNEW(ii,jj)+2] = bold[3*SOLD(ii,jj)+2] ;
            }
      }
      break ;

      case MRI_short:{
         short *bnew = MRI_SHORT_PTR(vim), *bold = MRI_SHORT_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

      case MRI_int:{
         int *bnew = MRI_INT_PTR(vim), *bold = MRI_INT_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

      case MRI_float:{
         float *bnew = MRI_FLOAT_PTR(vim), *bold = MRI_FLOAT_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

      case MRI_double:{
         double *bnew = MRI_DOUBLE_PTR(vim), *bold = MRI_DOUBLE_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

      case MRI_complex:{
         complex *bnew = MRI_COMPLEX_PTR(vim), *bold = MRI_COMPLEX_PTR(fim) ;
         for( jj=jjbot ; jj < jjtop ; jj++ )
            for( ii=iibot ; ii < iitop ; ii++ )
               bnew[SNEW(ii,jj)] = bold[SOLD(ii,jj)] ;
      }
      break ;

   } /* end of switch on datum type */

   RETURN(vim) ;
}