示例#1
0
static int _send(struct socket *sock, const void *buff, int len)
{
	struct iovec iov;
	struct msghdr msg;
	struct scm_cookie scm;
	int err;

	iov.iov_base = (void *) buff;
	iov.iov_len = len;

	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_flags = 0;

	err = scm_send(sock, &msg, &scm);
	if (err < 0) {
		return err;
	}
	err = sock->ops->sendmsg(sock, &msg, len, &scm);
	scm_destroy(&scm);
	return err;
}
示例#2
0
int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
{
	struct cmsghdr *cmsg;
	int err;

	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg))
	{
		err = -EINVAL;

		/* Verify that cmsg_len is at least sizeof(struct cmsghdr) */
		/* The first check was omitted in <= 2.2.5. The reasoning was
		   that parser checks cmsg_len in any case, so that
		   additional check would be work duplication.
		   But if cmsg_level is not SOL_SOCKET, we do not check 
		   for too short ancillary data object at all! Oops.
		   OK, let's add it...
		 */
		if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
		    (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
				    + cmsg->cmsg_len) > msg->msg_controllen)
			goto error;

		if (cmsg->cmsg_level != SOL_SOCKET)
			continue;

		switch (cmsg->cmsg_type)
		{
		case SCM_RIGHTS:
			err=scm_fp_copy(cmsg, &p->fp);
			if (err<0)
				goto error;
			break;
		case SCM_CREDENTIALS:
			if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
				goto error;
			memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
			err = scm_check_creds(&p->creds);
			if (err)
				goto error;
			break;
		default:
			goto error;
		}
	}

	if (p->fp && !p->fp->count)
	{
		kfree(p->fp);
		p->fp = NULL;
	}
	return 0;
	
error:
	scm_destroy(p);
	return err;
}
示例#3
0
文件: scm.c 项目: ANFS/ANFS-kernel
int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
{
	struct cmsghdr *cmsg;
	int err;

	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg))
	{
		err = -EINVAL;

		/* Verify that cmsg_len is at least sizeof(struct cmsghdr) */
		/* The first check was omitted in <= 2.2.5. The reasoning was
		   that parser checks cmsg_len in any case, so that
		   additional check would be work duplication.
		   But if cmsg_level is not SOL_SOCKET, we do not check
		   for too short ancillary data object at all! Oops.
		   OK, let's add it...
		 */
		if (!CMSG_OK(msg, cmsg))
			goto error;

		if (cmsg->cmsg_level != SOL_SOCKET)
			continue;

		switch (cmsg->cmsg_type)
		{
		case SCM_RIGHTS:
			if (!sock->ops || sock->ops->family != PF_UNIX)
				goto error;
			err=scm_fp_copy(cmsg, &p->fp);
			if (err<0)
				goto error;
			break;
		case SCM_CREDENTIALS:
			if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
				goto error;
			memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
			err = scm_check_creds(&p->creds);
			if (err)
				goto error;

			if (pid_vnr(p->pid) != p->creds.pid) {
				struct pid *pid;
				err = -ESRCH;
				pid = find_get_pid(p->creds.pid);
				if (!pid)
					goto error;
				put_pid(p->pid);
				p->pid = pid;
			}

			if ((p->cred->euid != p->creds.uid) ||
				(p->cred->egid != p->creds.gid)) {
				struct cred *cred;
				err = -ENOMEM;
				cred = prepare_creds();
				if (!cred)
					goto error;

				cred->uid = cred->euid = p->creds.uid;
				cred->gid = cred->egid = p->creds.uid;
				put_cred(p->cred);
				p->cred = cred;
			}
			break;
		default:
			goto error;
		}
	}

	if (p->fp && !p->fp->count)
	{
		kfree(p->fp);
		p->fp = NULL;
	}
	return 0;

error:
	scm_destroy(p);
	return err;
}
示例#4
0
static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
		struct ncp_reply_header* reply_buf, int max_reply_size)
{
	struct file *file;
	struct socket *sock;
	int result;
	struct iovec iov[2];
	struct msghdr msg;
	struct scm_cookie scm;
	__u32 ncptcp_rcvd_hdr[2];
	__u32 ncptcp_xmit_hdr[4];
	int   datalen;

	/* We have to check the result, so store the complete header */
	struct ncp_request_header request =
	*((struct ncp_request_header *) (server->packet));

	file = server->ncp_filp;
	sock = &file->f_dentry->d_inode->u.socket_i;
	
	ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC);
	ncptcp_xmit_hdr[1] = htonl(size + 16);
	ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION);
	ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8);

	DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
		 "seq: %d",
		 request.type,
		 (request.conn_high << 8) + request.conn_low,
		 request.sequence);
	DDPRINTK(" func: %d\n",
		 request.function);

	iov[1].iov_base = (void *) server->packet;
	iov[1].iov_len = size;
	iov[0].iov_base = ncptcp_xmit_hdr;
	iov[0].iov_len = 16;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_iov = iov;
	msg.msg_iovlen = 2;
	msg.msg_flags = MSG_NOSIGNAL;

	result = scm_send(sock, &msg, &scm);
	if (result < 0) {
		return result;
	}
	result = sock->ops->sendmsg(sock, &msg, size + 16, &scm);
	scm_destroy(&scm);
	if (result < 0) {
		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
		return result;
	}
rstrcv:
	result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8);
	if (result)
		return result;
	if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) {
		printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0]));
		return -EIO;
	}
	datalen = ntohl(ncptcp_rcvd_hdr[1]);
	if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) {
		printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
		return -EIO;
	}
	datalen -= 8;
	result = do_tcp_rcv(server, reply_buf, datalen);
	if (result)
		return result;
	if (reply_buf->type != NCP_REPLY) {
		DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type);
		goto rstrcv;
	}
	if (request.type == NCP_ALLOC_SLOT_REQUEST)
		return datalen;
	if (reply_buf->sequence != request.sequence) {
		printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
		return -EIO;
	}
	if ((reply_buf->conn_low != request.conn_low) ||
	    (reply_buf->conn_high != request.conn_high)) {
		printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
		return -EIO;
	}
	return datalen;
}
示例#5
0
static int
smb_send_trans2(struct smb_sb_info *server, __u16 trans2_command,
		int ldata, unsigned char *data,
		int lparam, unsigned char *param)
{
	struct socket *sock = server_sock(server);
	struct scm_cookie scm;
	int err;

	/* I know the following is very ugly, but I want to build the
	   smb packet as efficiently as possible. */

	const int smb_parameters = 15;
	const int oparam =
		ROUND_UP(SMB_HEADER_LEN + 2 * smb_parameters + 2 + 3);
	const int odata =
		ROUND_UP(oparam + lparam);
	const int bcc =
		odata + ldata - (SMB_HEADER_LEN + 2 * smb_parameters + 2);
	const int packet_length =
		SMB_HEADER_LEN + 2 * smb_parameters + bcc + 2;

	unsigned char padding[4] = {0,};
	char *p;

	struct iovec iov[4];
	struct msghdr msg;

	/* N.B. This test isn't valid! packet_size may be < max_xmit */
	if ((bcc + oparam) > server->opt.max_xmit)
	{
		return -ENOMEM;
	}
	p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc);

	WSET(server->packet, smb_tpscnt, lparam);
	WSET(server->packet, smb_tdscnt, ldata);
	/* N.B. these values should reflect out current packet size */
	WSET(server->packet, smb_mprcnt, TRANS2_MAX_TRANSFER);
	WSET(server->packet, smb_mdrcnt, TRANS2_MAX_TRANSFER);
	WSET(server->packet, smb_msrcnt, 0);
	WSET(server->packet, smb_flags, 0);
	DSET(server->packet, smb_timeout, 0);
	WSET(server->packet, smb_pscnt, lparam);
	WSET(server->packet, smb_psoff, oparam - 4);
	WSET(server->packet, smb_dscnt, ldata);
	WSET(server->packet, smb_dsoff, odata - 4);
	WSET(server->packet, smb_suwcnt, 1);
	WSET(server->packet, smb_setup0, trans2_command);
	*p++ = 0;		/* null smb_name for trans2 */
	*p++ = 'D';		/* this was added because OS/2 does it */
	*p++ = ' ';


	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_iov = iov;
	msg.msg_iovlen = 4;
	msg.msg_flags = 0;
	
	iov[0].iov_base = (void *) server->packet;
	iov[0].iov_len = oparam;
	iov[1].iov_base = (param == NULL) ? padding : param;
	iov[1].iov_len = lparam;
	iov[2].iov_base = padding;
	iov[2].iov_len = odata - oparam - lparam;
	iov[3].iov_base = (data == NULL) ? padding : data;
	iov[3].iov_len = ldata;

	err = scm_send(sock, &msg, &scm);
        if (err >= 0)
	{
		err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
		scm_destroy(&scm);
	}
	return err;
}