Example #1
0
int
sctp_listen(sctp_t *sctp)
{
	sctp_tf_t	*tf;

	RUN_SCTP(sctp);
	/*
	 * TCP handles listen() increasing the backlog, need to check
	 * if it should be handled here too
	 */
	if (sctp->sctp_state > SCTPS_BOUND) {
		WAKE_SCTP(sctp);
		return (EINVAL);
	}

	/* Do an anonymous bind for unbound socket doing listen(). */
	if (sctp->sctp_nsaddrs == 0) {
		struct sockaddr_storage ss;
		int ret;

		bzero(&ss, sizeof (ss));
		ss.ss_family = sctp->sctp_family;

		WAKE_SCTP(sctp);
		if ((ret = sctp_bind(sctp, (struct sockaddr *)&ss,
			sizeof (ss))) != 0)
			return (ret);
		RUN_SCTP(sctp)
	}

	sctp->sctp_state = SCTPS_LISTEN;
	(void) random_get_pseudo_bytes(sctp->sctp_secret, SCTP_SECRET_LEN);
	sctp->sctp_last_secret_update = lbolt64;
	bzero(sctp->sctp_old_secret, SCTP_SECRET_LEN);
	tf = &sctp_listen_fanout[SCTP_LISTEN_HASH(ntohs(sctp->sctp_lport))];
	sctp_listen_hash_insert(tf, sctp);
	WAKE_SCTP(sctp);
	return (0);
}
Example #2
0
int
sctp_listen(sctp_t *sctp)
{
	sctp_tf_t	*tf;
	sctp_stack_t	*sctps = sctp->sctp_sctps;
	conn_t		*connp = sctp->sctp_connp;

	RUN_SCTP(sctp);
	/*
	 * TCP handles listen() increasing the backlog, need to check
	 * if it should be handled here too
	 */
	if (sctp->sctp_state > SCTPS_BOUND ||
	    (sctp->sctp_connp->conn_state_flags & CONN_CLOSING)) {
		WAKE_SCTP(sctp);
		return (EINVAL);
	}

	/* Do an anonymous bind for unbound socket doing listen(). */
	if (sctp->sctp_nsaddrs == 0) {
		struct sockaddr_storage ss;
		int ret;

		bzero(&ss, sizeof (ss));
		ss.ss_family = connp->conn_family;

		WAKE_SCTP(sctp);
		if ((ret = sctp_bind(sctp, (struct sockaddr *)&ss,
		    sizeof (ss))) != 0)
			return (ret);
		RUN_SCTP(sctp)
	}

	/* Cache things in the ixa without any refhold */
	ASSERT(!(connp->conn_ixa->ixa_free_flags & IXA_FREE_CRED));
	connp->conn_ixa->ixa_cred = connp->conn_cred;
	connp->conn_ixa->ixa_cpid = connp->conn_cpid;
	if (is_system_labeled())
		connp->conn_ixa->ixa_tsl = crgetlabel(connp->conn_cred);

	sctp->sctp_state = SCTPS_LISTEN;
	(void) random_get_pseudo_bytes(sctp->sctp_secret, SCTP_SECRET_LEN);
	sctp->sctp_last_secret_update = ddi_get_lbolt64();
	bzero(sctp->sctp_old_secret, SCTP_SECRET_LEN);

	/*
	 * If there is an association limit, allocate and initialize
	 * the counter struct.  Note that since listen can be called
	 * multiple times, the struct may have been allready allocated.
	 */
	if (!list_is_empty(&sctps->sctps_listener_conf) &&
	    sctp->sctp_listen_cnt == NULL) {
		sctp_listen_cnt_t *slc;
		uint32_t ratio;

		ratio = sctp_find_listener_conf(sctps,
		    ntohs(connp->conn_lport));
		if (ratio != 0) {
			uint32_t mem_ratio, tot_buf;

			slc = kmem_alloc(sizeof (sctp_listen_cnt_t), KM_SLEEP);
			/*
			 * Calculate the connection limit based on
			 * the configured ratio and maxusers.  Maxusers
			 * are calculated based on memory size,
			 * ~ 1 user per MB.  Note that the conn_rcvbuf
			 * and conn_sndbuf may change after a
			 * connection is accepted.  So what we have
			 * is only an approximation.
			 */
			if ((tot_buf = connp->conn_rcvbuf +
			    connp->conn_sndbuf) < MB) {
				mem_ratio = MB / tot_buf;
				slc->slc_max = maxusers / ratio * mem_ratio;
			} else {
				mem_ratio = tot_buf / MB;
				slc->slc_max = maxusers / ratio / mem_ratio;
			}
			/* At least we should allow some associations! */
			if (slc->slc_max < sctp_min_assoc_listener)
				slc->slc_max = sctp_min_assoc_listener;
			slc->slc_cnt = 1;
			slc->slc_drop = 0;
			sctp->sctp_listen_cnt = slc;
		}
	}


	tf = &sctps->sctps_listen_fanout[SCTP_LISTEN_HASH(
	    ntohs(connp->conn_lport))];
	sctp_listen_hash_insert(tf, sctp);

	WAKE_SCTP(sctp);
	return (0);
}