Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}