Esempio n. 1
0
/*
 * to do a socketpair, we make just connect the two datas, easy! since we
 * always wait on the socket inode, they're no contention for a wait area,
 * and deadlock prevention in the case of a process writing to itself is,
 * ignored, in true unix fashion!
 */
static int
unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
{
	struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);

	unix_data_ref(upd1);
	unix_data_ref(upd2);
	upd1->peerupd = upd2;
	upd2->peerupd = upd1;
	return 0;
}
Esempio n. 2
0
/*
 * perform a connection. we can only connect to unix sockets (i can't for
 * the life of me find an application where that wouldn't be the case!)
 */
static int
unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
		   int sockaddr_len)
{
	int i;
	struct unix_proto_data *serv_upd;
	struct sockaddr_un sockun;

	PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
	       sockaddr_len);
	if (sockaddr_len <= UN_PATH_OFFSET ||
	    sockaddr_len >= sizeof(struct sockaddr_un)) {
		PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
		return -EINVAL;
	}
	verify_area(uservaddr, sockaddr_len);
	memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
	if (sockun.sun_family != AF_UNIX) {
		PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
		       sockun.sun_family, AF_UNIX);
		return -EINVAL;
	}
	if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
		PRINTK("unix_proto_connect: can't locate peer\n");
		return -EINVAL;
	}
	if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
		PRINTK("unix_proto_connect: can't await connection\n");
		return i;
	}
	unix_data_ref(UN_DATA(sock->conn));
	UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
	return 0;
}
Esempio n. 3
0
static int unix_connect(struct socket *sock,
			struct sockaddr *uservaddr,
			int sockaddr_len, int flags)
{
    char fname[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
    struct sockaddr_un sockun;
    struct unix_proto_data *serv_upd;
    struct inode *inode;
    unsigned short old_ds;
    int i;

    if (sockaddr_len <= 0 || sockaddr_len > sizeof(struct sockaddr_un))
	return -EINVAL;

    if (sock->state == SS_CONNECTING)
	return -EINPROGRESS;

    if (sock->state == SS_CONNECTED)
	return -EISCONN;

    memcpy(&sockun, uservaddr, sockaddr_len);
    sockun.sun_path[sockaddr_len] = '\0';

    if (sockun.sun_family != AF_UNIX)
	return -EINVAL;
/*
 * Try to open the name in the filesystem - this is how we identify ourselves
 * and our server. Note that we don't hold onto the inode much, just enough to
 * find our server. When we're connected, we mooch off the server.
 */

    memcpy(fname, sockun.sun_path, sockaddr_len);
    fname[sockaddr_len] = '\0';

    old_ds = current->t_regs.ds;
    current->t_regs.ds = get_ds();

    i = open_namei(fname, 2, S_IFSOCK, &inode, NULL);
    current->t_regs.ds = old_ds;

    if (i < 0)
	return i;

    serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
    iput(inode);

    if (!serv_upd)
	return -EINVAL;

    if ((i = sock_awaitconn(sock, serv_upd->socket, flags)) < 0)
	return i;

    if (sock->conn) {
	unix_data_ref(UN_DATA(sock->conn));
	UN_DATA(sock)->peerupd = UN_DATA(sock->conn);	/* ref server */
    }

    return 0;
}
Esempio n. 4
0
/*
 * on accept, we ref the peer's data for safe writes
 */
static int
unix_proto_accept(struct socket *sock, struct socket *newsock)
{
	PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
	       sock, newsock);
	unix_data_ref(UN_DATA(newsock->conn));
	UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
	return 0;
}
Esempio n. 5
0
static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
{
    struct socket *clientsock;

/*
 * If there aren't any sockets awaiting connection,
 * then wait for one, unless nonblocking.
 */

    while (!(clientsock = sock->iconn)) {
	if (flags & O_NONBLOCK)
	    return -EAGAIN;

	sock->flags |= SO_WAITDATA;
	interruptible_sleep_on(sock->wait);
	sock->flags &= ~SO_WAITDATA;

	if (current->signal /* & ~current->blocked */ )
	    return -ERESTARTSYS;
    }

/*
 * Great. Finish the connection relative to server and client,
 * wake up the client and return the new fd to the server.
 */

    sock->iconn = clientsock->next;
    clientsock->next = NULL;
    newsock->conn = clientsock;
    clientsock->conn = newsock;
    clientsock->state = SS_CONNECTED;
    newsock->state = SS_CONNECTED;
    unix_data_ref(UN_DATA(clientsock));
    UN_DATA(newsock)->peerupd = UN_DATA(clientsock);
    UN_DATA(newsock)->sockaddr_un = UN_DATA(sock)->sockaddr_un;
    UN_DATA(newsock)->sockaddr_len = UN_DATA(sock)->sockaddr_len;
    wake_up_interruptible(clientsock->wait);

#if 0
    sock_wake_async(clientsock, 0);	/* Don't need */
#endif

    return 0;
}
Esempio n. 6
0
/*
 * on accept, we ref the peer's data for safe writes
 */
static int
unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
{
   struct socket *clientsock;

	PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
	       sock, newsock);

	/*
	 * if there aren't any sockets awaiting connection, then wait for
	 * one, unless nonblocking
	 */
	while (!(clientsock = sock->iconn)) {
		if (flags & O_NONBLOCK)
			return -EAGAIN;
		interruptible_sleep_on(sock->wait);
		if (current->signal & ~current->blocked) {
			PRINTK("sys_accept: sleep was interrupted\n");
			return -ERESTARTSYS;
		}
	}

	/*
	 * great. finish the connection relative to server and client,
	 * wake up the client and return the new fd to the server
	 */
	sock->iconn = clientsock->next;
	clientsock->next = NULL;
	newsock->conn = clientsock;
	clientsock->conn = newsock;
	clientsock->state = SS_CONNECTED;
	newsock->state = SS_CONNECTED;
	wake_up(clientsock->wait);
        unix_data_ref (UN_DATA(newsock->conn));
	UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
	return 0;
}