Example #1
0
int
soconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
	int error;

	if (so->so_options & SO_ACCEPTCONN)
		return (EOPNOTSUPP);
	/*
	 * If protocol is connection-based, can only connect once.
	 * Otherwise, if connected, try to disconnect first.
	 * This allows user to disconnect by connecting to, e.g.,
	 * a null address.
	 */
	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
	    ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
	    (error = sodisconnect(so)))) {
		error = EISCONN;
	} else {
		/*
		 * Prevent accumulated error from previous connection
		 * from biting us.
		 */
		so->so_error = 0;
		error = so_pru_connect(so, nam, td);
	}
	return (error);
}
Example #2
0
int
so_pru_connect_async(struct socket *so, struct sockaddr *nam, struct thread *td)
{
	struct netmsg_pru_connect *msg;
	int error, flags;

	KASSERT(so->so_proto->pr_usrreqs->pru_preconnect != NULL,
	    ("async pru_connect is not supported"));

	/* NOTE: sockaddr immediately follows netmsg */
	msg = kmalloc(sizeof(*msg) + nam->sa_len, M_LWKTMSG,
	    M_WAITOK | M_NULLOK);
	if (msg == NULL) {
		/*
		 * Fail to allocate message; fallback to
		 * synchronized pru_connect.
		 */
		return so_pru_connect(so, nam, td);
	}

	error = so->so_proto->pr_usrreqs->pru_preconnect(so, nam, td);
	if (error) {
		kfree(msg, M_LWKTMSG);
		return error;
	}

	flags = PRUC_ASYNC;
	if (td != NULL && (so->so_proto->pr_flags & PR_ACONN_HOLDTD)) {
		lwkt_hold(td);
		flags |= PRUC_HELDTD;
	}

	netmsg_init(&msg->base, so, &netisr_afree_rport, 0,
	    so->so_proto->pr_usrreqs->pru_connect);
	msg->nm_nam = (struct sockaddr *)(msg + 1);
	memcpy(msg->nm_nam, nam, nam->sa_len);
	msg->nm_td = td;
	msg->nm_m = NULL;
	msg->nm_sndflags = 0;
	msg->nm_flags = flags;
	lwkt_sendmsg(so->so_port, &msg->base.lmsg);
	return 0;
}