Exemple #1
0
static void rtp_session_schedule_outbound_network_simulator(RtpSession *session, ortpTimeSpec *sleep_until){
	mblk_t *om;
	int count=0;
	bool_t is_rtp_packet;
	
	if (!session->net_sim_ctx)
		return;
	
	if (!session->net_sim_ctx->params.enabled)
		return;
	
	if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutbound){
		sleep_until->tv_sec=0;
		sleep_until->tv_nsec=0;
		ortp_mutex_lock(&session->net_sim_ctx->mutex);
		while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
			count++;
			ortp_mutex_unlock(&session->net_sim_ctx->mutex);
			is_rtp_packet=om->reserved1; /*it was set by _rtp_session_sendto()*/
			om=rtp_session_network_simulate(session,om, &is_rtp_packet);
			if (om){
				_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
				freemsg(om);
			}
			ortp_mutex_lock(&session->net_sim_ctx->mutex);
		}
		ortp_mutex_unlock(&session->net_sim_ctx->mutex);
		if (count==0){
			/*even if no packets were queued, we have to schedule the simulator*/
			is_rtp_packet=TRUE;
			om=rtp_session_network_simulate(session,NULL, &is_rtp_packet);
			if (om){
				_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
				freemsg(om);
			}
		}
	}else if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutboundControlled){
#if defined(ORTP_TIMESTAMP)
		ortpTimeSpec current={0};
		ortpTimeSpec packet_time;
		mblk_t *todrop=NULL;
		ortp_mutex_lock(&session->net_sim_ctx->mutex);
		while((om=peekq(&session->net_sim_ctx->send_q))!=NULL){
			ortp_mutex_unlock(&session->net_sim_ctx->mutex);
			if (todrop) {
				freemsg(todrop); /*free the last message while the mutex is not held*/
				todrop=NULL;
			}
			_ortp_get_cur_time(&current,TRUE);
			packet_time.tv_sec=om->timestamp.tv_sec;
			packet_time.tv_nsec=om->timestamp.tv_usec*1000LL;
			if (om->timestamp.tv_sec==0 && om->timestamp.tv_usec==0){
				todrop=om; /*simulate a packet loss*/
			}else if (packet_time.tv_sec<=current.tv_sec && packet_time.tv_nsec<=current.tv_nsec){
				is_rtp_packet=om->reserved1; /*it was set by _rtp_session_sendto()*/
				_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
				todrop=om;
			}else {
				/*no packet is to be sent yet; set the time at which we want to be called*/
				*sleep_until=packet_time;
				ortp_mutex_lock(&session->net_sim_ctx->mutex);
				break; 
			}
			ortp_mutex_lock(&session->net_sim_ctx->mutex);
			if (todrop) getq(&session->net_sim_ctx->send_q); /* pop the message while the mutex is held*/
		}
		ortp_mutex_unlock(&session->net_sim_ctx->mutex);
		if (todrop) freemsg(todrop);
		if (sleep_until->tv_sec==0){
			_ortp_get_cur_time(&current,TRUE);
			/*no pending packet in the queue yet, schedule a wake up not too far*/
			sleep_until->tv_sec=current.tv_sec;
			sleep_until->tv_nsec=current.tv_nsec+1000000LL; /*in 1 ms*/
		}
		
#else
		ortp_mutex_lock(&session->net_sim_ctx->mutex);
		while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
			ortp_mutex_unlock(&session->net_sim_ctx->mutex);
			freemsg(om);
			ortp_error("Network simulator is in mode OrtpNetworkSimulatorOutboundControlled but oRTP wasn't compiled with --enable-ntp-timestamp.");
			ortp_mutex_lock(&session->net_sim_ctx->mutex);
		}
		ortp_mutex_unlock(&session->net_sim_ctx->mutex);
#endif
	}
}
Exemple #2
0
void
sctp_user_abort(sctp_t *sctp, mblk_t *data)
{
	mblk_t *mp;
	int len, hdrlen;
	char *cause;
	sctp_faddr_t *fp = sctp->sctp_current;
	ip_xmit_attr_t	*ixa = fp->sf_ixa;
	sctp_stack_t	*sctps = sctp->sctp_sctps;

	/*
	 * Don't need notification if connection is not yet setup,
	 * call sctp_clean_death() to reclaim resources.
	 * Any pending connect call(s) will error out.
	 */
	if (sctp->sctp_state < SCTPS_COOKIE_WAIT) {
		sctp_clean_death(sctp, ECONNABORTED);
		return;
	}

	mp = sctp_make_mp(sctp, fp, 0);
	if (mp == NULL) {
		SCTP_KSTAT(sctps, sctp_send_user_abort_failed);
		return;
	}

	/*
	 * Create abort chunk.
	 */
	if (data) {
		if (fp->sf_isv4) {
			hdrlen = sctp->sctp_hdr_len;
		} else {
			hdrlen = sctp->sctp_hdr6_len;
		}
		hdrlen += sizeof (sctp_chunk_hdr_t) + sizeof (sctp_parm_hdr_t);
		cause = (char *)data->b_rptr;
		len = data->b_wptr - data->b_rptr;

		if (len + hdrlen > fp->sf_pmss) {
			len = fp->sf_pmss - hdrlen;
		}
	} else {
		cause = NULL;
		len = 0;
	}
	/*
	 * Since it is a user abort, we should have the sctp_t and hence
	 * the correct verification tag.  So we should not set the T-bit
	 * in the ABORT.
	 */
	if ((len = sctp_link_abort(mp, SCTP_ERR_USER_ABORT, cause, len, 0,
	    B_FALSE)) < 0) {
		freemsg(mp);
		return;
	}
	SCTPS_BUMP_MIB(sctps, sctpAborted);
	BUMP_LOCAL(sctp->sctp_opkts);
	BUMP_LOCAL(sctp->sctp_obchunks);

	sctp_set_iplen(sctp, mp, ixa);
	ASSERT(ixa->ixa_ire != NULL);
	ASSERT(ixa->ixa_cred != NULL);

	(void) conn_ip_output(mp, ixa);

	sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
	sctp_clean_death(sctp, ECONNABORTED);
}
Exemple #3
0
/*
 * function to xmit  Single packet over the wire
 *
 * wq - pointer to WQ
 * mp - Pointer to packet chain
 *
 * return pointer to the packet
 */
mblk_t *
oce_send_packet(struct oce_wq *wq, mblk_t *mp)
{
	struct oce_nic_hdr_wqe *wqeh;
	struct oce_dev *dev;
	struct ether_header *eh;
	struct ether_vlan_header *evh;
	int32_t num_wqes;
	uint16_t etype;
	uint32_t ip_offset;
	uint32_t csum_flags = 0;
	boolean_t use_copy = B_FALSE;
	boolean_t tagged   = B_FALSE;
	uint16_t  vlan_tag;
	uint32_t  reg_value = 0;
	oce_wqe_desc_t *wqed = NULL;
	mblk_t *nmp = NULL;
	mblk_t *tmp = NULL;
	uint32_t pkt_len = 0;
	int num_mblks = 0;
	int ret = 0;
	uint32_t mss = 0;
	uint32_t flags = 0;
	int len = 0;

	/* retrieve the adap priv struct ptr */
	dev = wq->parent;

	/* check if we have enough free slots */
	if (wq->wq_free < dev->tx_reclaim_threshold) {
		(void) oce_process_tx_compl(wq, B_FALSE);
	}
	if (wq->wq_free < OCE_MAX_TX_HDL) {
		return (mp);
	}

	/* check if we should copy */
	for (tmp = mp; tmp != NULL; tmp = tmp->b_cont) {
		pkt_len += MBLKL(tmp);
		num_mblks++;
	}

	if (pkt_len == 0 || num_mblks == 0) {
		freemsg(mp);
		return (NULL);
	}

	/* retrieve LSO information */
	mac_lso_get(mp, &mss, &flags);

	/* get the offload flags */
	mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &csum_flags);

	/* restrict the mapped segment to wat we support */
	if (num_mblks  > OCE_MAX_TX_HDL) {
		nmp = msgpullup(mp, -1);
		if (nmp == NULL) {
			atomic_inc_32(&wq->pkt_drops);
			freemsg(mp);
			return (NULL);
		}
		/* Reset it to new collapsed mp */
		freemsg(mp);
		mp = nmp;
	}

	/* Get the packet descriptor for Tx */
	wqed = kmem_cache_alloc(wq->wqed_cache, KM_NOSLEEP);
	if (wqed == NULL) {
		atomic_inc_32(&wq->pkt_drops);
		freemsg(mp);
		return (NULL);
	}
	eh = (struct ether_header *)(void *)mp->b_rptr;
	if (ntohs(eh->ether_type) == VLAN_TPID) {
		evh = (struct ether_vlan_header *)(void *)mp->b_rptr;
		tagged = B_TRUE;
		etype = ntohs(evh->ether_type);
		ip_offset = sizeof (struct ether_vlan_header);
		pkt_len -= VTAG_SIZE;
		vlan_tag = ntohs(evh->ether_tci);
		oce_remove_vtag(mp);
	} else {
		etype = ntohs(eh->ether_type);
		ip_offset = sizeof (struct ether_header);
	}

	/* Save the WQ pointer */
	wqed->wq = wq;
	wqed->frag_idx = 1; /* index zero is always header */
	wqed->frag_cnt = 0;
	wqed->nhdl = 0;
	wqed->mp = NULL;
	OCE_LIST_LINK_INIT(&wqed->link);

	/* If entire packet is less than the copy limit  just do copy */
	if (pkt_len < dev->tx_bcopy_limit) {
		use_copy = B_TRUE;
		ret = oce_bcopy_wqe(wq, wqed, mp, pkt_len);
	} else {
		/* copy or dma map the individual fragments */
		for (nmp = mp; nmp != NULL; nmp = nmp->b_cont) {
			len = MBLKL(nmp);
			if (len == 0) {
				continue;
			}
			if (len < dev->tx_bcopy_limit) {
				ret = oce_bcopy_wqe(wq, wqed, nmp, len);
			} else {
				ret = oce_map_wqe(wq, wqed, nmp, len);
			}
			if (ret != 0)
				break;
		}
	}

	/*
	 * Any failure other than insufficient Q entries
	 * drop the packet
	 */
	if (ret != 0) {
		oce_free_wqed(wq, wqed);
		atomic_inc_32(&wq->pkt_drops);
		freemsg(mp);
		return (NULL);
	}

	wqeh = (struct oce_nic_hdr_wqe *)&wqed->frag[0];
	bzero(wqeh, sizeof (struct oce_nic_hdr_wqe));

	/* fill rest of wqe header fields based on packet */
	if (flags & HW_LSO) {
		wqeh->u0.s.lso = B_TRUE;
		wqeh->u0.s.lso_mss = mss;
	}
	if (csum_flags & HCK_FULLCKSUM) {
		uint8_t *proto;
		if (etype == ETHERTYPE_IP) {
			proto = (uint8_t *)(void *)
			    (mp->b_rptr + ip_offset);
			if (proto[9] == 6)
				/* IPPROTO_TCP */
				wqeh->u0.s.tcpcs = B_TRUE;
			else if (proto[9] == 17)
				/* IPPROTO_UDP */
				wqeh->u0.s.udpcs = B_TRUE;
		}
	}

	if (csum_flags & HCK_IPV4_HDRCKSUM)
		wqeh->u0.s.ipcs = B_TRUE;
	if (tagged) {
		wqeh->u0.s.vlan = B_TRUE;
		wqeh->u0.s.vlan_tag = vlan_tag;
	}

	wqeh->u0.s.complete = B_TRUE;
	wqeh->u0.s.event = B_TRUE;
	wqeh->u0.s.crc = B_TRUE;
	wqeh->u0.s.total_length = pkt_len;

	num_wqes = wqed->frag_cnt + 1;

	/* h/w expects even no. of WQEs */
	if (num_wqes & 0x1) {
		bzero(&wqed->frag[num_wqes], sizeof (struct oce_nic_frag_wqe));
		num_wqes++;
	}
	wqed->wqe_cnt = (uint16_t)num_wqes;
	wqeh->u0.s.num_wqe = num_wqes;
	DW_SWAP(u32ptr(&wqed->frag[0]), (wqed->wqe_cnt * NIC_WQE_SIZE));

	mutex_enter(&wq->tx_lock);
	if (num_wqes > wq->wq_free) {
		atomic_inc_32(&wq->tx_deferd);
		mutex_exit(&wq->tx_lock);
		goto wqe_fail;
	}
	atomic_add_32(&wq->wq_free, -num_wqes);

	/* fill the wq for adapter */
	oce_fill_ring_descs(wq, wqed);

	/* Set the mp pointer in the wqe descriptor */
	if (use_copy == B_FALSE) {
		wqed->mp = mp;
	}
	/* Add the packet desc to list to be retrieved during cmpl */
	OCE_LIST_INSERT_TAIL(&wq->wqe_desc_list,  wqed);
	(void) ddi_dma_sync(wq->ring->dbuf->dma_handle, 0, 0,
	    DDI_DMA_SYNC_FORDEV);

	/* ring tx doorbell */
	reg_value = (num_wqes << 16) | wq->wq_id;
	/* Ring the door bell  */
	OCE_DB_WRITE32(dev, PD_TXULP_DB, reg_value);
	mutex_exit(&wq->tx_lock);
	if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
	}

	/* free mp if copied or packet chain collapsed */
	if (use_copy == B_TRUE) {
		freemsg(mp);
	}
	return (NULL);

wqe_fail:

	if (tagged) {
		oce_insert_vtag(mp, vlan_tag);
	}
	oce_free_wqed(wq, wqed);
	return (mp);
} /* oce_send_packet */
Exemple #4
0
static int
nd_get_reply(TIUSER *tiptr, XDR *xdrp, uint32_t call_xid, int *badmsg)
{
	static struct rpc_msg		reply_msg;
	static struct rpc_err		rpc_err;
	static struct nfsattrstat	na;
	static struct WRITE3res		wres;
	static struct t_kunitdata	rudata;
	int				uderr;
	int				type;
	int				error;

	*badmsg = 0;

	rudata.addr.maxlen = 0;
	rudata.opt.maxlen = 0;
	rudata.udata.udata_mp = (mblk_t *)NULL;

	nd_log("nfs_dump: calling t_krcvudata\n");

	if (error = t_krcvudata(tiptr, &rudata, &type, &uderr)) {
		if (error == EBADMSG) {
			cmn_err(CE_WARN, "\tnfs_dump:  received EBADMSG");
			*badmsg = 1;
			return (0);
		}
		nfs_perror(error, "\nnfs_dump: t_krcvudata failed: %m\n");
		return (EIO);
	}
	if (type != T_DATA) {
		cmn_err(CE_WARN, "\tnfs_dump:  received type %d", type);
		*badmsg = 1;
		return (0);
	}
	if (!rudata.udata.udata_mp) {
		cmn_err(CE_WARN, "\tnfs_dump: null receive");
		*badmsg = 1;
		return (0);
	}

	/*
	 * Decode results.
	 */
	xdrmblk_init(xdrp, rudata.udata.udata_mp, XDR_DECODE, 0);

	reply_msg.acpted_rply.ar_verf = _null_auth;
	switch (nfsdump_version) {
	case NFS_VERSION:
		reply_msg.acpted_rply.ar_results.where = (caddr_t)&na;
		reply_msg.acpted_rply.ar_results.proc = xdr_attrstat;
		break;
	case NFS_V3:
		reply_msg.acpted_rply.ar_results.where = (caddr_t)&wres;
		reply_msg.acpted_rply.ar_results.proc = xdr_WRITE3res;
		break;
	default:
		return (EIO);
	}

	if (!xdr_replymsg(xdrp, &reply_msg)) {
		cmn_err(CE_WARN, "\tnfs_dump: xdr_replymsg failed");
		return (EIO);
	}

	if (reply_msg.rm_xid != call_xid) {
		*badmsg = 1;
		return (0);
	}

	_seterr_reply(&reply_msg, &rpc_err);

	if (rpc_err.re_status != RPC_SUCCESS) {
		cmn_err(CE_WARN, "\tnfs_dump: RPC error %d (%s)",
		    rpc_err.re_status, clnt_sperrno(rpc_err.re_status));
		return (EIO);
	}

	switch (nfsdump_version) {
	case NFS_VERSION:
		if (na.ns_status) {
			cmn_err(CE_WARN, "\tnfs_dump: status %d", na.ns_status);
			return (EIO);
		}
		break;
	case NFS_V3:
		if (wres.status != NFS3_OK) {
			cmn_err(CE_WARN, "\tnfs_dump: status %d", wres.status);
			return (EIO);
		}
		break;
	default:
		return (EIO);
	}

	if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
		/* free auth handle */
		xdrp->x_op = XDR_FREE;
		(void) xdr_opaque_auth(xdrp, &(reply_msg.acpted_rply.ar_verf));
	}

	freemsg(rudata.udata.udata_mp);

	return (0);
}
Exemple #5
0
/*
 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
 */
void
sctp_send_abort(sctp_t *sctp, uint32_t vtag, uint16_t serror, char *details,
    size_t len, mblk_t *inmp, int iserror, boolean_t tbit, ip_recv_attr_t *ira)
{

	mblk_t		*hmp;
	uint32_t	ip_hdr_len;
	ipha_t		*iniph;
	ipha_t		*ahiph = NULL;
	ip6_t		*inip6h;
	ip6_t		*ahip6h = NULL;
	sctp_hdr_t	*sh;
	sctp_hdr_t	*insh;
	size_t		ahlen;
	uchar_t		*p;
	ssize_t		alen;
	int		isv4;
	conn_t		*connp = sctp->sctp_connp;
	sctp_stack_t	*sctps = sctp->sctp_sctps;
	ip_xmit_attr_t	*ixa;

	isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
	if (isv4) {
		ahlen = sctp->sctp_hdr_len;
	} else {
		ahlen = sctp->sctp_hdr6_len;
	}

	/*
	 * If this is a labeled system, then check to see if we're allowed to
	 * send a response to this particular sender.  If not, then just drop.
	 */
	if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
		return;

	hmp = allocb(sctps->sctps_wroff_xtra + ahlen, BPRI_MED);
	if (hmp == NULL) {
		/* XXX no resources */
		return;
	}

	/* copy in the IP / SCTP header */
	p = hmp->b_rptr + sctps->sctps_wroff_xtra;
	hmp->b_rptr = p;
	hmp->b_wptr = p + ahlen;
	if (isv4) {
		bcopy(sctp->sctp_iphc, p, sctp->sctp_hdr_len);
		/*
		 * Composite is likely incomplete at this point, so pull
		 * info from the incoming IP / SCTP headers.
		 */
		ahiph = (ipha_t *)p;
		iniph = (ipha_t *)inmp->b_rptr;
		ip_hdr_len = IPH_HDR_LENGTH(inmp->b_rptr);

		sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr_len);
		ASSERT(OK_32PTR(sh));

		insh = (sctp_hdr_t *)((uchar_t *)iniph + ip_hdr_len);
		ASSERT(OK_32PTR(insh));

		/* Copy in the peer's IP addr */
		ahiph->ipha_dst = iniph->ipha_src;
		ahiph->ipha_src = iniph->ipha_dst;
	} else {
		bcopy(sctp->sctp_iphc6, p, sctp->sctp_hdr6_len);
		ahip6h = (ip6_t *)p;
		inip6h = (ip6_t *)inmp->b_rptr;
		ip_hdr_len = ip_hdr_length_v6(inmp, inip6h);

		sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr6_len);
		ASSERT(OK_32PTR(sh));

		insh = (sctp_hdr_t *)((uchar_t *)inip6h + ip_hdr_len);
		ASSERT(OK_32PTR(insh));

		/* Copy in the peer's IP addr */
		ahip6h->ip6_dst = inip6h->ip6_src;
		ahip6h->ip6_src = inip6h->ip6_dst;
	}

	/* Fill in the holes in the SCTP common header */
	sh->sh_sport = insh->sh_dport;
	sh->sh_dport = insh->sh_sport;
	sh->sh_verf = vtag;

	/* Link in the abort chunk */
	if ((alen = sctp_link_abort(hmp, serror, details, len, iserror, tbit))
	    < 0) {
		freemsg(hmp);
		return;
	}

	/*
	 * Base the transmission on any routing-related socket options
	 * that have been set on the listener/connection.
	 */
	ixa = conn_get_ixa_exclusive(connp);
	if (ixa == NULL) {
		freemsg(hmp);
		return;
	}
	ixa->ixa_flags &= ~IXAF_VERIFY_PMTU;

	ixa->ixa_pktlen = ahlen + alen;
	if (isv4) {
		ixa->ixa_flags |= IXAF_IS_IPV4;
		ahiph->ipha_length = htons(ixa->ixa_pktlen);
		ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr_len;
	} else {
		ixa->ixa_flags &= ~IXAF_IS_IPV4;
		ahip6h->ip6_plen = htons(ixa->ixa_pktlen - IPV6_HDR_LEN);
		ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr6_len;
	}

	SCTPS_BUMP_MIB(sctps, sctpAborted);
	BUMP_LOCAL(sctp->sctp_obchunks);

	if (is_system_labeled() && ixa->ixa_tsl != NULL) {
		ASSERT(ira->ira_tsl != NULL);

		ixa->ixa_tsl = ira->ira_tsl;	/* A multi-level responder */
	}

	if (ira->ira_flags & IRAF_IPSEC_SECURE) {
		/*
		 * Apply IPsec based on how IPsec was applied to
		 * the packet that caused the abort.
		 */
		if (!ipsec_in_to_out(ira, ixa, hmp, ahiph, ahip6h)) {
			ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip;

			BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
			/* Note: mp already consumed and ip_drop_packet done */
			ixa_refrele(ixa);
			return;
		}
	} else {
		ixa->ixa_flags |= IXAF_NO_IPSEC;
	}

	BUMP_LOCAL(sctp->sctp_opkts);
	BUMP_LOCAL(sctp->sctp_obchunks);

	(void) ip_output_simple(hmp, ixa);
	ixa_refrele(ixa);
}
/*ARGSUSED*/
static int
mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
{
	struct mouse_state *state;
	minor_t	minor;

	state = (struct mouse_state *)q->q_ptr;

	/*
	 * Disable queue processing now, so that another reset cannot get in
	 * after we wait for the current reset (if any) to complete.
	 */
	qprocsoff(q);

	mutex_enter(&state->reset_mutex);
	while (state->reset_state != MSE_RESET_IDLE) {
		/*
		 * Waiting for the previous reset to finish is
		 * non-interruptible.  Some upper-level clients
		 * cannot deal with EINTR and will not close the
		 * STREAM properly, resulting in failure to reopen it
		 * within the same process.
		 */
		cv_wait(&state->reset_cv, &state->reset_mutex);
	}

	if (state->reset_tid != 0) {
		(void) quntimeout(q, state->reset_tid);
		state->reset_tid = 0;
	}

	if (state->reply_mp != NULL) {
		freemsg(state->reply_mp);
		state->reply_mp = NULL;
	}

	if (state->reset_ack_mp != NULL) {
		freemsg(state->reset_ack_mp);
		state->reset_ack_mp = NULL;
	}

	mutex_exit(&state->reset_mutex);

	mutex_enter(&state->ms_mutex);

	if (state->bc_id != 0) {
		(void) qunbufcall(q, state->bc_id);
		state->bc_id = 0;
	}

	q->q_ptr = NULL;
	WR(q)->q_ptr = NULL;
	state->ms_rqp = NULL;
	state->ms_wqp = NULL;

	state->ms_opened = B_FALSE;

	minor = state->ms_minor;

	mutex_exit(&state->ms_mutex);

	if (!MOUSE8042_INTERNAL_OPEN(minor)) {
		/*
		 * Closing physical PS/2 mouse
		 *
		 * Link it back to virtual mouse, and
		 * mouse8042_open will be called as a result
		 * of the consconfig_link call.  Do NOT try
		 * this if the mouse is about to be detached!
		 *
		 * If linking back fails, this specific mouse
		 * will not be available underneath the virtual
		 * mouse, and can only be accessed via physical
		 * open.
		 */
		consconfig_link(ddi_driver_major(mouse8042_dip),
		    MOUSE8042_INTERNAL_MINOR(minor));
	}

	return (0);
}
/*
 * Through message handle for write side stream
 *
 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
 *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
 *  -. uinst_t->u_lock : P
 *  -. uinst_t->l_lock : P
 *  -. uinst_t->c_lock : P
 */
int
oplmsu_wcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag, krw_t rw)
{
	queue_t	*usr_queue = NULL, *dst_queue = NULL;
	ctrl_t	*ctrl;

	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));

	mutex_enter(&oplmsu_uinst->c_lock);
	if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) {
		usr_queue = ctrl->queue;
		mutex_exit(&oplmsu_uinst->c_lock);
	} else {
		mutex_exit(&oplmsu_uinst->c_lock);
		if (mp->b_datap->db_type == M_IOCTL) {
			rw_exit(&oplmsu_uinst->lock);
			oplmsu_iocack(q, mp, ENODEV);
			rw_enter(&oplmsu_uinst->lock, rw);
		} else {
			freemsg(mp);
		}
		return (SUCCESS);
	}

	if (oplmsu_uinst->lower_queue != NULL) {
		dst_queue = WR(oplmsu_uinst->lower_queue);
	} else {
		cmn_err(CE_WARN, "!oplmsu: through-lwq: "
		    "Active path doesn't exist");

		if (mp->b_datap->db_type == M_IOCTL) {
			rw_exit(&oplmsu_uinst->lock);
			oplmsu_iocack(q, mp, ENODEV);
			rw_enter(&oplmsu_uinst->lock, rw);
		} else {
			freemsg(mp);
		}
		return (SUCCESS);
	}

	if ((usr_queue == WR(q)) || (usr_queue == RD(q))) {
		if (pri_flag == MSU_HIGH) {
			putq(dst_queue, mp);
		} else {
			if (canput(dst_queue)) {
				putq(dst_queue, mp);
			} else {
				oplmsu_wcmn_norm_putbq(WR(q), mp, dst_queue);
				return (FAILURE);
			}
		}
	} else {
		cmn_err(CE_WARN, "oplmsu: through-lwq: "
		    "Inappropriate message for this node");

		if (mp->b_datap->db_type == M_IOCTL) {
			rw_exit(&oplmsu_uinst->lock);
			oplmsu_iocack(q, mp, ENODEV);
			rw_enter(&oplmsu_uinst->lock, rw);
		} else {
			freemsg(mp);
		}
	}
	return (SUCCESS);
}
void rtp_session_rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_ts, struct sockaddr *addr, socklen_t addrlen)
{
	int i;
	rtp_header_t *rtp;
	int msgsize;
	RtpStream *rtpstream=&session->rtp;
	rtp_stats_t *stats=&rtpstream->stats;
	
	msgsize=mp->b_wptr-mp->b_rptr;

	if (msgsize<RTP_FIXED_HEADER_SIZE){
		ortp_warning("Packet too small to be a rtp packet (%i)!",msgsize);
		rtpstream->stats.bad++;
		ortp_global_stats.bad++;
		freemsg(mp);
		return;
	}
	rtp=(rtp_header_t*)mp->b_rptr;
	if (rtp->version!=2)
	{
		/* try to see if it is a STUN packet */
		uint16_t stunlen=*((uint16_t*)(mp->b_rptr + sizeof(uint16_t)));
		stunlen = ntohs(stunlen);
		if (stunlen+20==mp->b_wptr-mp->b_rptr){
			/* this looks like a stun packet */
			if (session->eventqs!=NULL){
				OrtpEvent *ev=ortp_event_new(ORTP_EVENT_STUN_PACKET_RECEIVED);
				OrtpEventData *ed=ortp_event_get_data(ev);
				ed->packet=mp;
				ed->ep=rtp_endpoint_new(addr,addrlen);
				rtp_session_dispatch_event(session,ev);
				return;
			}
		}
		/* discard in two case: the packet is not stun OR nobody is interested by STUN (no eventqs) */
		ortp_debug("Receiving rtp packet with version number !=2...discarded");
		stats->bad++;
		ortp_global_stats.bad++;
		freemsg(mp);
		return;
	}

	/* only count non-stun packets. */
	ortp_global_stats.packet_recv++;
	stats->packet_recv++;
	ortp_global_stats.hw_recv+=msgsize;
	stats->hw_recv+=msgsize;
	session->rtp.hwrcv_since_last_SR++;

	
	/* convert all header data from network order to host order */
	rtp->seq_number=ntohs(rtp->seq_number);
	rtp->timestamp=ntohl(rtp->timestamp);
	rtp->ssrc=ntohl(rtp->ssrc);
	/* convert csrc if necessary */
	if (rtp->cc*sizeof(uint32_t) > (uint32_t) (msgsize-RTP_FIXED_HEADER_SIZE)){
		ortp_debug("Receiving too short rtp packet.");
		stats->bad++;
		ortp_global_stats.bad++;
		freemsg(mp);
		return;
	}

#ifndef PERF
	/* Write down the last RTP/RTCP packet reception time. */
	gettimeofday(&session->last_recv_time, NULL);
#endif

	for (i=0;i<rtp->cc;i++)
		rtp->csrc[i]=ntohl(rtp->csrc[i]);
	/*the goal of the following code is to lock on an incoming SSRC to avoid
	receiving "mixed streams"*/
	if (session->ssrc_set){
		/*the ssrc is set, so we must check it */
		if (session->rcv.ssrc!=rtp->ssrc){
			if (session->inc_ssrc_candidate==rtp->ssrc){
				session->inc_same_ssrc_count++;
			}else{
				session->inc_same_ssrc_count=0;
				session->inc_ssrc_candidate=rtp->ssrc;
			}
			if (session->inc_same_ssrc_count>=session->rtp.ssrc_changed_thres){

				/* store the sender rtp address to do symmetric RTP */
				if (!session->use_connect){
					if (session->rtp.socket>0 && session->symmetric_rtp){
						/* store the sender rtp address to do symmetric RTP */
						memcpy(&session->rtp.rem_addr,addr,addrlen);
						session->rtp.rem_addrlen=addrlen;
					}
				}
				session->rtp.rcv_last_ts = rtp->timestamp;
				session->rcv.ssrc=rtp->ssrc;
				rtp_signal_table_emit(&session->on_ssrc_changed);
			}else{
				/*discard the packet*/
				ortp_debug("Receiving packet with unknown ssrc.");
				stats->bad++;
				ortp_global_stats.bad++;
				freemsg(mp);
				return;
			}
		}
    else{
			/* The SSRC change must not happen if we still receive
			ssrc from the initial source. */
			session->inc_same_ssrc_count=0;
		}

	}else{
		session->ssrc_set=TRUE;
		session->rcv.ssrc=rtp->ssrc;

		if (!session->use_connect){
			if (session->rtp.socket>0 && session->symmetric_rtp){
				/* store the sender rtp address to do symmetric RTP */
				memcpy(&session->rtp.rem_addr,addr,addrlen);
				session->rtp.rem_addrlen=addrlen;
			}
		}
	}
	
	/* update some statistics */
	{
		poly32_t *extseq=(poly32_t*)&rtpstream->hwrcv_extseq;
		if (rtp->seq_number>extseq->split.lo){
			extseq->split.lo=rtp->seq_number;
		}else if (rtp->seq_number<200 && extseq->split.lo>((1<<16) - 200)){
			/* this is a check for sequence number looping */
			extseq->split.lo=rtp->seq_number;
			extseq->split.hi++;
		}
	}
	
	/* check for possible telephone events */
	if (rtp->paytype==session->rcv.telephone_events_pt){
		queue_packet(&session->rtp.tev_rq,session->rtp.max_rq_size,mp,rtp,&i);
		stats->discarded+=i;
		ortp_global_stats.discarded+=i;
		return;
	}
	
	/* check for possible payload type change, in order to update accordingly our clock-rate dependant
	parameters */
	if (session->hw_recv_pt!=rtp->paytype){
		rtp_session_update_payload_type(session,rtp->paytype);
	}
	
	jitter_control_new_packet(&session->rtp.jittctl,rtp->timestamp,local_str_ts);

	if (session->flags & RTP_SESSION_FIRST_PACKET_DELIVERED) {
		/* detect timestamp important jumps in the future, to workaround stupid rtp senders */
		if (RTP_TIMESTAMP_IS_NEWER_THAN(rtp->timestamp,session->rtp.rcv_last_ts+session->rtp.ts_jump)){
			ortp_debug("rtp_parse: timestamp jump ?");
			rtp_signal_table_emit2(&session->on_timestamp_jump,(long)&rtp->timestamp);
		}
		else if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(session->rtp.rcv_last_ts,rtp->timestamp)){
			/* don't queue packets older than the last returned packet to the application*/
			/* Call timstamp jumb in case of
			 * large negative Ts jump or if ts is set to 0
			*/
			
			if ( RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(session->rtp.rcv_last_ts, rtp->timestamp + session->rtp.ts_jump) ){
				ortp_warning("rtp_parse: negative timestamp jump");
				rtp_signal_table_emit2(&session->on_timestamp_jump,
							(long)&rtp->timestamp);
			}
			ortp_debug("rtp_parse: discarding too old packet (ts=%i)",rtp->timestamp);
			freemsg(mp);
			stats->outoftime++;
			ortp_global_stats.outoftime++;
			return;
		}
	}
	
	queue_packet(&session->rtp.rq,session->rtp.max_rq_size,mp,rtp,&i);
	stats->discarded+=i;
	ortp_global_stats.discarded+=i;
}
Exemple #9
0
static void dec_process(MSFilter *f) {
	mblk_t *im;
	DecState *s=(DecState*)f->data;

	while( (im=ms_queue_get(f->inputs[0]))!=0) {
		mblk_t *m;

		dec_unpacketize(f, s, im, &s->q);

		while((m=ms_queue_get(&s->q))!=NULL){
			vpx_codec_err_t err;
			vpx_codec_iter_t  iter = NULL;
			vpx_image_t *img;

			err = vpx_codec_decode(&s->codec, m->b_rptr, m->b_wptr - m->b_rptr, NULL, 0);
			if (err) {
				ms_warning("vpx_codec_decode failed : %d %s (%s)\n", err, vpx_codec_err_to_string(err), vpx_codec_error_detail(&s->codec));

				if ((f->ticker->time - s->last_error_reported_time)>5000 || s->last_error_reported_time==0) {
					s->last_error_reported_time=f->ticker->time;
					ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
				}
				if (s->first_image_decoded == FALSE) {
					/* if no frames have been decoded yet, do not try to browse decoded frames */
					freemsg(m);
					continue;
				}
			}


			/* browse decoded frames */
			while((img = vpx_codec_get_frame(&s->codec, &iter))) {
				int i,j;

				if (s->yuv_width != img->d_w || s->yuv_height != img->d_h) {
					if (s->yuv_msg)
						freemsg(s->yuv_msg);
					s->yuv_msg = ms_yuv_buf_alloc(&s->outbuf, img->d_w, img->d_h);
					s->yuv_width = img->d_w;
					s->yuv_height = img->d_h;
				}

				/* scale/copy frame to destination mblk_t */
				for(i=0; i<3; i++) {
					uint8_t* dest = s->outbuf.planes[i];
					uint8_t* src = img->planes[i];
					int h = img->d_h >> ((i>0)?1:0);

					for(j=0; j<h; j++) {
						memcpy(dest, src, s->outbuf.strides[i]);

						dest += s->outbuf.strides[i];
						src += img->stride[i];
					}
				}
				ms_queue_put(f->outputs[0], dupmsg(s->yuv_msg));

				if (ms_video_update_average_fps(&s->fps, f->ticker->time)) {
					ms_message("VP8 decoder: Frame size: %dx%d", s->yuv_width, s->yuv_height);
				}
				if (!s->first_image_decoded) {
					s->first_image_decoded = TRUE;
					ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
				}
			}
			freemsg(m);
		}
	}
}
/*
 * Process a DLPI protocol message.
 * The primitives DL_BIND_REQ, DL_ENABMULTI_REQ, DL_PROMISCON_REQ,
 * DL_SET_PHYS_ADDR_REQ put the data link below our dld_str_t into an
 * 'active' state. The primitive DL_PASSIVE_REQ marks our dld_str_t
 * as 'passive' and forbids it from being subsequently made 'active'
 * by the above primitives.
 */
void
dld_proto(dld_str_t *dsp, mblk_t *mp)
{
	t_uscalar_t		prim;

	if (MBLKL(mp) < sizeof (t_uscalar_t)) {
		freemsg(mp);
		return;
	}
	prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive;

	switch (prim) {
	case DL_INFO_REQ:
		proto_info_req(dsp, mp);
		break;
	case DL_BIND_REQ:
		proto_bind_req(dsp, mp);
		break;
	case DL_UNBIND_REQ:
		proto_unbind_req(dsp, mp);
		break;
	case DL_UNITDATA_REQ:
		proto_unitdata_req(dsp, mp);
		break;
	case DL_UDQOS_REQ:
		proto_udqos_req(dsp, mp);
		break;
	case DL_ATTACH_REQ:
		proto_attach_req(dsp, mp);
		break;
	case DL_DETACH_REQ:
		proto_detach_req(dsp, mp);
		break;
	case DL_ENABMULTI_REQ:
		proto_enabmulti_req(dsp, mp);
		break;
	case DL_DISABMULTI_REQ:
		proto_disabmulti_req(dsp, mp);
		break;
	case DL_PROMISCON_REQ:
		proto_promiscon_req(dsp, mp);
		break;
	case DL_PROMISCOFF_REQ:
		proto_promiscoff_req(dsp, mp);
		break;
	case DL_PHYS_ADDR_REQ:
		proto_physaddr_req(dsp, mp);
		break;
	case DL_SET_PHYS_ADDR_REQ:
		proto_setphysaddr_req(dsp, mp);
		break;
	case DL_NOTIFY_REQ:
		proto_notify_req(dsp, mp);
		break;
	case DL_CAPABILITY_REQ:
		proto_capability_req(dsp, mp);
		break;
	case DL_PASSIVE_REQ:
		proto_passive_req(dsp, mp);
		break;
	default:
		proto_req(dsp, mp);
		break;
	}
}
Exemple #11
0
int
efe_send(efe_t *efep, mblk_t *mp)
{
	efe_ring_t *rp;
	uint16_t len;
	efe_desc_t *dp;
	uint16_t status;
	efe_buf_t *bp;

	ASSERT(mutex_owned(&efep->efe_txlock));

	rp = efep->efe_tx_ring;

	len = msgsize(mp);

	if (len > ETHERMAX + VLAN_TAGSZ) {
		efep->efe_oerrors++;
		efep->efe_macxmt_errors++;
		freemsg(mp);
		return (DDI_SUCCESS);
	}

	dp = GETDESC(rp, efep->efe_tx_desc);
	SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORKERNEL);

	status = GETDESC16(efep->efe_tx_ring, &dp->d_status);

	/* Stop if device owns descriptor */
	if (status & TXSTAT_OWNER) {
		return (DDI_FAILURE);
	}

	bp = GETBUF(rp, efep->efe_tx_desc);

	mcopymsg(mp, bp->b_kaddr);

	/*
	 * Packets must contain at least ETHERMIN octets.
	 * Padded octets are zeroed out prior to sending.
	 */
	if (len < ETHERMIN) {
		bzero(bp->b_kaddr + len, ETHERMIN - len);
		len = ETHERMIN;
	}

	SYNCBUF(bp, DDI_DMA_SYNC_FORDEV);

	PUTDESC16(rp, &dp->d_status, TXSTAT_OWNER);
	PUTDESC16(rp, &dp->d_len, len);
	PUTDESC16(rp, &dp->d_control, TXCTL_LASTDESCR);

	SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORDEV);

	efep->efe_opackets++;
	efep->efe_obytes += len;

	if (*bp->b_kaddr & 0x01) {
		if (bcmp(bp->b_kaddr, efe_broadcast, ETHERADDRL) == 0) {
			efep->efe_brdcstxmt++;
		} else {
			efep->efe_multixmt++;
		}
	}

	efep->efe_tx_desc = NEXTDESC(rp, efep->efe_tx_desc);

	return (DDI_SUCCESS);
}
Exemple #12
0
static void dec_process(MSFilter *f) {
	DecState *s = (DecState *)f->data;
	mblk_t *im;
	vpx_codec_err_t err;
	vpx_image_t *img;
	vpx_codec_iter_t iter = NULL;
	MSQueue frame;
	MSQueue mtofree_queue;
	Vp8RtpFmtFrameInfo frame_info;
	
	ms_filter_lock(f);

	ms_queue_init(&frame);
	ms_queue_init(&mtofree_queue);

	/* Unpack RTP payload format for VP8. */
	vp8rtpfmt_unpacker_feed(&s->unpacker, f->inputs[0]);

	/* Decode unpacked VP8 frames. */
	while (vp8rtpfmt_unpacker_get_frame(&s->unpacker, &frame, &frame_info) == 0) {
		while ((im = ms_queue_get(&frame)) != NULL) {
			err = vpx_codec_decode(&s->codec, im->b_rptr, im->b_wptr - im->b_rptr, NULL, 0);
			if ((s->flags & VPX_CODEC_USE_INPUT_FRAGMENTS) && (!err && mblk_get_marker_info(im))) {
				err = vpx_codec_decode(&s->codec, NULL, 0, NULL, 0);
			}
			if (err) {
				ms_warning("vp8 decode failed : %d %s (%s)\n", err, vpx_codec_err_to_string(err), vpx_codec_error_detail(&s->codec)?vpx_codec_error_detail(&s->codec):"no details");
			}
			ms_queue_put(&mtofree_queue, im);
		}

		/* Get decoded frame */
		if ((img = vpx_codec_get_frame(&s->codec, &iter))) {
			int i, j;
			int reference_updates = 0;

			if (vpx_codec_control(&s->codec, VP8D_GET_LAST_REF_UPDATES, &reference_updates) == 0) {
				if (frame_info.pictureid_present && ((reference_updates & VP8_GOLD_FRAME) || (reference_updates & VP8_ALTR_FRAME))) {
					vp8rtpfmt_send_rpsi(&s->unpacker, frame_info.pictureid);
				}
			}

			if (s->yuv_width != img->d_w || s->yuv_height != img->d_h) {
				if (s->yuv_msg) freemsg(s->yuv_msg);
				s->yuv_msg = ms_yuv_buf_alloc(&s->outbuf, img->d_w, img->d_h);
				s->yuv_width = img->d_w;
				s->yuv_height = img->d_h;
				ms_filter_notify_no_arg(f, MS_FILTER_OUTPUT_FMT_CHANGED);
			}

			/* scale/copy frame to destination mblk_t */
			for (i = 0; i < 3; i++) {
				uint8_t *dest = s->outbuf.planes[i];
				uint8_t *src = img->planes[i];
				int h = img->d_h >> ((i > 0) ? 1 : 0);

				for (j = 0; j < h; j++) {
					memcpy(dest, src, s->outbuf.strides[i]);
					dest += s->outbuf.strides[i];
					src += img->stride[i];
				}
			}
			ms_queue_put(f->outputs[0], dupmsg(s->yuv_msg));

			if (ms_average_fps_update(&s->fps, f->ticker->time)) {
				ms_message("VP8 decoder: Frame size: %dx%d", s->yuv_width, s->yuv_height);
			}
			if (!s->first_image_decoded) {
				s->first_image_decoded = TRUE;
				ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
			}
		}

		while ((im = ms_queue_get(&mtofree_queue)) != NULL) {
			freemsg(im);
		}
	}
static int
softmac_capab_send(softmac_lower_t *slp, boolean_t enable)
{
	softmac_t		*softmac;
	dl_capability_req_t	*capb;
	dl_capability_sub_t	*subcapb;
	mblk_t			*reqmp, *ackmp;
	int			err;
	size_t			size = 0;

	softmac = slp->sl_softmac;

	if (enable) {
		/* No need to enable DL_CAPAB_ZEROCOPY */
		if (softmac->smac_capab_flags & MAC_CAPAB_HCKSUM)
			size += sizeof (dl_capability_sub_t) +
			    sizeof (dl_capab_hcksum_t);

		if (softmac->smac_mdt) {
			if (!(softmac->smac_mdt_capab.mdt_flags &
			    DL_CAPAB_MDT_ENABLE)) {
				/*
				 * The MDT capability was not enabled for the
				 * first time, enable it now.
				 */
				size += sizeof (dl_capability_sub_t) +
				    sizeof (dl_capab_mdt_t);
			}
		}

		if (size == 0)
			return (0);
	}

	/*
	 * Create DL_CAPABILITY_REQ message and send it down
	 */
	reqmp = allocb(sizeof (dl_capability_req_t) + size, BPRI_MED);
	if (reqmp == NULL)
		return (ENOMEM);

	bzero(reqmp->b_rptr, sizeof (dl_capability_req_t) + size);

	DB_TYPE(reqmp) = M_PROTO;
	reqmp->b_wptr = reqmp->b_rptr + sizeof (dl_capability_req_t) + size;

	capb = (dl_capability_req_t *)reqmp->b_rptr;
	capb->dl_primitive = DL_CAPABILITY_REQ;

	if (!enable)
		goto output;

	capb->dl_sub_offset = sizeof (dl_capability_req_t);

	if (softmac->smac_capab_flags & MAC_CAPAB_HCKSUM) {
		dl_capab_hcksum_t *hck_subcapp;

		size = sizeof (dl_capability_sub_t) +
		    sizeof (dl_capab_hcksum_t);
		capb->dl_sub_length += size;

		subcapb = (dl_capability_sub_t *)(capb + 1);
		subcapb->dl_cap = DL_CAPAB_HCKSUM;
		subcapb->dl_length = sizeof (dl_capab_hcksum_t);
		hck_subcapp = (dl_capab_hcksum_t *)(subcapb + 1);
		hck_subcapp->hcksum_version = HCKSUM_VERSION_1;
		hck_subcapp->hcksum_txflags =
		    softmac->smac_hcksum_txflags | HCKSUM_ENABLE;
	}

	if (softmac->smac_mdt) {
		if (!(softmac->smac_mdt_capab.mdt_flags &
		    DL_CAPAB_MDT_ENABLE)) {
			dl_capab_mdt_t *mdt_subcapp;

			size = sizeof (dl_capability_sub_t) +
			    sizeof (dl_capab_mdt_t);
			capb->dl_sub_length += size;

			subcapb = (dl_capability_sub_t *)
			    ((uint8_t *)(subcapb + 1) + subcapb->dl_length);

			subcapb->dl_cap = DL_CAPAB_MDT;
			subcapb->dl_length = sizeof (dl_capab_mdt_t);
			mdt_subcapp = (dl_capab_mdt_t *)(subcapb + 1);
			mdt_subcapp->mdt_version = MDT_VERSION_2;
			mdt_subcapp->mdt_flags =
			    (softmac->smac_mdt_capab.mdt_flags |
			    DL_CAPAB_MDT_ENABLE);
			mdt_subcapp->mdt_hdr_head =
			    softmac->smac_mdt_capab.mdt_hdr_head;
			mdt_subcapp->mdt_hdr_tail =
			    softmac->smac_mdt_capab.mdt_hdr_tail;
			mdt_subcapp->mdt_max_pld =
			    softmac->smac_mdt_capab.mdt_max_pld;
			mdt_subcapp->mdt_span_limit =
			    softmac->smac_mdt_capab.mdt_span_limit;
		}
	}

output:
	err = softmac_proto_tx(slp, reqmp, &ackmp);
	if (err == 0) {
		if (enable) {
			err = i_capab_ack(ackmp, NULL,
			    &softmac_enable_capab_ops, softmac);
		} else {
			err = i_capab_ack(ackmp, NULL,
			    &softmac_adv_capab_ops, softmac);
		}
	}
	freemsg(ackmp);

	return (err);
}
/* ARGSUSED */
void
aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
    boolean_t loopback)
{
	aggr_port_t *port = (aggr_port_t *)arg;
	aggr_grp_t *grp = port->lp_grp;

	if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
		aggr_mac_rx(grp->lg_mh, mrh, mp);
	} else {
		mblk_t *cmp, *last, *head;
		struct ether_header *ehp;
		uint16_t sap;

		/* filter out slow protocol packets (LACP & Marker) */
		last = NULL;
		head = cmp = mp;
		while (cmp != NULL) {
			if (MBLKL(cmp) < sizeof (struct ether_header)) {
				/* packet too short */
				if (head == cmp) {
					/* no packets accumulated */
					head = cmp->b_next;
					cmp->b_next = NULL;
					freemsg(cmp);
					cmp = head;
				} else {
					/* send up accumulated packets */
					last->b_next = NULL;
					if (port->lp_collector_enabled) {
						aggr_mac_rx(grp->lg_mh, mrh,
						    head);
					} else {
						freemsgchain(head);
					}
					head = cmp->b_next;
					cmp->b_next = NULL;
					freemsg(cmp);
					cmp = head;
					last = NULL;
				}
				continue;
			}
			ehp = (struct ether_header *)cmp->b_rptr;

			sap = ntohs(ehp->ether_type);
			if (sap == ETHERTYPE_SLOW) {
				/*
				 * LACP or Marker packet. Send up pending
				 * chain, and send LACP/Marker packet
				 * to LACP subsystem.
				 */
				if (head == cmp) {
					/* first packet of chain */
					ASSERT(last == NULL);
					head = cmp->b_next;
					cmp->b_next = NULL;
					aggr_recv_lacp(port, mrh, cmp);
					cmp = head;
				} else {
					/* previously accumulated packets */
					ASSERT(last != NULL);
					/* send up non-LACP packets */
					last->b_next = NULL;
					if (port->lp_collector_enabled) {
						aggr_mac_rx(grp->lg_mh, mrh,
						    head);
					} else {
						freemsgchain(head);
					}
					/* unlink and pass up LACP packets */
					head = cmp->b_next;
					cmp->b_next = NULL;
					aggr_recv_lacp(port, mrh, cmp);
					cmp = head;
					last = NULL;
				}
			} else {
				last = cmp;
				cmp = cmp->b_next;
			}
		}
		if (head != NULL) {
			if (port->lp_collector_enabled)
				aggr_mac_rx(grp->lg_mh, mrh, head);
			else
				freemsgchain(head);
		}
	}
}
Exemple #15
0
/*
 * cvc_wput()
 *	cn driver does a strwrite of console output data to rconsvp which has
 *	been set by consconfig. The data enters the cvc stream at the streamhead
 *	and flows thru ttycompat and ldterm which have been pushed on the
 *	stream.  Console output data gets sent out either to cvcredir, if the
 *	network path is available and selected, or to IOSRAM otherwise.  Data is
 *	sent to cvcredir via its read queue (cvcoutput_q, which gets set in
 *	cvc_register()).  If the IOSRAM path is selected, or if previous mblks
 *	are currently queued up for processing, the new mblk will be queued
 *	and handled later on by cvc_wsrv.
 */
static int
cvc_wput(queue_t *q, mblk_t *mp)
{
	int		error = 0;

	rw_enter(&cvclock, RW_READER);

	CVC_DBG2(CVC_DBG_WPUT, "mp 0x%x db_type 0x%x",
	    mp, mp->b_datap->db_type);

	switch (mp->b_datap->db_type) {

		case M_IOCTL:
		case M_CTL: {
			struct iocblk *iocp = (struct iocblk *)mp->b_rptr;

			switch (iocp->ioc_cmd) {
				/*
				 * These ioctls are only supposed to be
				 * processed after everything else that is
				 * already queued awaiting processing, so throw
				 * them on the queue and let cvc_wsrv handle
				 * them.
				 */
				case TCSETSW:
				case TCSETSF:
				case TCSETAW:
				case TCSETAF:
				case TCSBRK:
					(void) putq(q, mp);
					break;

				default:
					cvc_ioctl(q, mp);
			}
			break;
		}

		case M_FLUSH:
			if (*mp->b_rptr & FLUSHW) {
				/*
				 * Flush our write queue.
				 */
				flushq(q, FLUSHDATA);
				*mp->b_rptr &= ~FLUSHW;
			}
			if (*mp->b_rptr & FLUSHR) {
				flushq(RD(q), FLUSHDATA);
				qreply(q, mp);
			} else
				freemsg(mp);
			break;

		case M_STOP:
			cvc_stopped = 1;
			freemsg(mp);
			break;

		case M_START:
			cvc_stopped = 0;
			freemsg(mp);
			qenable(q);  /* Start up delayed messages */
			break;

		case M_READ:
			/*
			 * ldterm handles this (VMIN/VTIME processing).
			 */
			freemsg(mp);
			break;

		default:
			cmn_err(CE_WARN, "cvc_wput: unexpected mblk type - mp ="
			    " 0x%p, type = 0x%x", (void *)mp,
			    mp->b_datap->db_type);
			freemsg(mp);
			break;

		case M_DATA:
			/*
			 * If there are other mblks queued up for transmission,
			 * or we're using IOSRAM either because cvcredir hasn't
			 * registered yet or because we were configured that
			 * way, or cvc has been stopped or suspended, place this
			 * mblk on the input queue for future processing.
			 * Otherwise, hand it off to cvcredir for transmission
			 * via the network.
			 */
			if (q->q_first != NULL || cvcoutput_q == NULL ||
			    via_iosram || cvc_stopped == 1 ||
			    cvc_suspended == 1) {
				(void) putq(q, mp);
			} else {
				/*
				 * XXX - should canputnext be called here?
				 * Starfire's cvc doesn't do that, and it
				 * appears to work anyway.
				 */
				(void) putnext(cvcoutput_q, mp);
			}
			break;

	}
	rw_exit(&cvclock);
	return (error);
}
static void discard_well_choosed_samples(mblk_t *m, int nsamples, int todrop)
{
    int i;
    int16_t *samples = (int16_t *) m->b_rptr;
    int min_diff = 32768;
    int pos = 0;


#ifdef TWO_SAMPLES_CRITERIA
    for (i = 0; i < nsamples - 1; ++i) {
        int tmp = abs((int) samples[i] - (int) samples[i + 1]);
#else
    for (i = 0; i < nsamples - 2; ++i) {
        int tmp = abs((int) samples[i] - (int) samples[i + 1]) + abs((int) samples[i + 1] - (int) samples[i + 2]);
#endif
        if (tmp <= min_diff) {
            pos = i;
            min_diff = tmp;
        }
    }
    /*ms_message("min_diff=%i at pos %i",min_diff, pos);*/
#ifdef TWO_SAMPLES_CRITERIA
    memmove(samples + pos, samples + pos + 1, (nsamples - pos - 1) * 2);
#else
    memmove(samples + pos + 1, samples + pos + 2, (nsamples - pos - 2) * 2);
#endif

    todrop--;
    m->b_wptr -= 2;
    nsamples--;
    if (todrop > 0) {
        /*repeat the same process again*/
        discard_well_choosed_samples(m, nsamples, todrop);
    }
}

mblk_t *ms_audio_flow_controller_process(MSAudioFlowController *ctl, mblk_t *m) {
    if (ctl->total_samples > 0 && ctl->target_samples > 0) {
        int nsamples = (int)((m->b_wptr - m->b_rptr) / 2);
        int th_dropped;
        int todrop;

        ctl->current_pos += nsamples;
        th_dropped = (ctl->target_samples * ctl->current_pos) / ctl->total_samples;
        todrop = th_dropped - ctl->current_dropped;
        if (todrop > 0) {
            if (todrop*8<nsamples) {
                discard_well_choosed_samples(m, nsamples, todrop);
            } else {
                ms_warning("Too many samples to drop, dropping entire frame.");
                freemsg(m);
                m=NULL;
                todrop=nsamples;
            }
            /*ms_message("th_dropped=%i, current_dropped=%i, %i samples dropped.",th_dropped,ctl->current_dropped,todrop);*/
            ctl->current_dropped += todrop;
        }
        if (ctl->current_pos >= ctl->total_samples) ctl->target_samples = 0; /*stop discarding*/
    }
    return m;
}
Exemple #17
0
/*
 * cvc_send_to_iosram()
 *	Flush as much data as possible to the CONO chunk.  If successful, free
 *	any mblks that were completely transmitted, update the b_rptr field in
 *	the first remaining mblk if it was partially transmitted, and update the
 *	caller's pointer to the new head of the mblk chain.  Since the software
 *	that will be pulling this data out of IOSRAM (dxs on the SC) is just
 *	polling at some frequency, we avoid attempts to flush data to IOSRAM any
 *	faster than a large divisor of that polling frequency.
 *
 *	Note that "cvc_buf_t out" is only declared "static" to keep it from
 *	being allocated on the stack.  Allocating 1K+ structures on the stack
 *	seems rather antisocial.
 */
static void
cvc_send_to_iosram(mblk_t **chainpp)
{
	int			rval;
	uint8_t			dvalid;
	uchar_t			*cp;
	mblk_t			*mp;
	mblk_t			*last_empty_mp;
	static clock_t		last_flush = (clock_t)-1;
	static cvc_buf_t	out;   /* see note above about static */

	ASSERT(chainpp != NULL);

	/*
	 * We _do_ have something to do, right?
	 */
	if (*chainpp == NULL) {
		return;
	}

	/*
	 * We can actually increase throughput by throttling back on attempts to
	 * flush data to IOSRAM, since trying to write every little bit of data
	 * as it shows up will actually generate more delays waiting for the SC
	 * to pick up each of those bits.  Instead, we'll avoid attempting to
	 * write data to IOSRAM any faster than half of the polling frequency we
	 * expect the SC to be using.
	 */
	if (ddi_get_lbolt() - last_flush <
	    drv_usectohz(CVC_IOSRAM_POLL_USECS / 2)) {
		return;
	}

	/*
	 * If IOSRAM is inaccessible or the CONO chunk still holds data that
	 * hasn't been picked up by the SC, there's nothing we can do right now.
	 */
	rval = iosram_get_flag(IOSRAM_KEY_CONO, &dvalid, NULL);
	if ((rval != 0) || (dvalid == IOSRAM_DATA_VALID)) {
		if ((rval != 0) && (rval != EAGAIN)) {
			cmn_err(CE_WARN, "cvc_send_to_iosram: get_flag ret %d",
			    rval);
		}
		return;
	}

	/*
	 * Copy up to MAX_XFER_COUTPUT chars from the mblk chain into a buffer.
	 * Don't change any of the mblks just yet, since we can't be certain
	 * that we'll be successful in writing data to the CONO chunk.
	 */
	out.count = 0;
	mp = *chainpp;
	cp = mp->b_rptr;
	last_empty_mp = NULL;
	while ((mp != NULL) && (out.count < MAX_XFER_COUTPUT)) {
		/*
		 * Process as many of the characters in the current mblk as
		 * possible.
		 */
		while ((cp != mp->b_wptr) && (out.count < MAX_XFER_COUTPUT)) {
			out.buffer[out.count++] = *cp++;
		}

		/*
		 * Did we process that entire mblk?  If so, move on to the next
		 * one.  If not, we're done filling the buffer even if there's
		 * space left, because apparently there wasn't room to process
		 * the next character.
		 */
		if (cp != mp->b_wptr) {
			break;
		}

		/*
		 * When this loop terminates, last_empty_mp will point to the
		 * last mblk that was completely processed, mp will point to the
		 * following mblk (or NULL if no more mblks exist), and cp will
		 * point to the first untransmitted character in the mblk
		 * pointed to by mp.  We'll need this data to update the mblk
		 * chain if all of the data is successfully transmitted.
		 */
		last_empty_mp = mp;
		mp = mp->b_cont;
		cp = (mp != NULL) ? mp->b_rptr : NULL;
	}

	/*
	 * If we succeeded in preparing some data, try to transmit it through
	 * IOSRAM.  First write the count and the data, which can be done in a
	 * single operation thanks to the buffer structure we use, then set the
	 * data_valid flag if the first step succeeded.
	 */
	if (out.count != 0) {
		rval = iosram_wr(IOSRAM_KEY_CONO, COUNT_OFFSET,
		    CONSBUF_COUNT_SIZE + out.count, (caddr_t)&out);
		if ((rval != 0) && (rval != EAGAIN)) {
			cmn_err(CE_WARN, "cvc_putc: write ret %d", rval);
		}

		/* if the data write succeeded, set the data_valid flag */
		if (rval == 0) {
			rval = iosram_set_flag(IOSRAM_KEY_CONO,
			    IOSRAM_DATA_VALID, IOSRAM_INT_NONE);
			if ((rval != 0) && (rval != EAGAIN)) {
				cmn_err(CE_WARN,
				    "cvc_putc: set flags for outbuf ret %d",
				    rval);
			}
		}

		/*
		 * If we successfully transmitted any data, modify the caller's
		 * mblk chain to remove the data that was transmitted, freeing
		 * all mblks that were completely processed.
		 */
		if (rval == 0) {
			last_flush = ddi_get_lbolt();

			/*
			 * If any data is left over, update the b_rptr field of
			 * the first remaining mblk in case some of its data was
			 * processed.
			 */
			if (mp != NULL) {
				mp->b_rptr = cp;
			}

			/*
			 * If any mblks have been emptied, unlink them from the
			 * residual chain, free them, and update the caller's
			 * mblk pointer.
			 */
			if (last_empty_mp != NULL) {
				last_empty_mp->b_cont = NULL;
				freemsg(*chainpp);
				*chainpp = mp;
			}
		}
	}
}
Exemple #18
0
/*
 * Receive rpc requests.
 * Pulls a request in off the socket, checks if the packet is intact,
 * and deserializes the call packet.
 */
static bool_t
svc_clts_krecv(SVCXPRT *clone_xprt, mblk_t *mp, struct rpc_msg *msg)
{
	/* LINTED pointer alignment */
	struct udp_data *ud = (struct udp_data *)clone_xprt->xp_p2buf;
	XDR *xdrs = &clone_xprt->xp_xdrin;
	struct rpc_clts_server *stats = CLONE2STATS(clone_xprt);
	union T_primitives *pptr;
	int hdrsz;

	TRACE_0(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_START,
	    "svc_clts_krecv_start:");

	RSSTAT_INCR(stats, rscalls);

	/*
	 * The incoming request should start with an M_PROTO message.
	 */
	if (mp->b_datap->db_type != M_PROTO) {
		goto bad;
	}

	/*
	 * The incoming request should be an T_UNITDTA_IND.  There
	 * might be other messages coming up the stream, but we can
	 * ignore them.
	 */
	pptr = (union T_primitives *)mp->b_rptr;
	if (pptr->type != T_UNITDATA_IND) {
		goto bad;
	}
	/*
	 * Do some checking to make sure that the header at least looks okay.
	 */
	hdrsz = (int)(mp->b_wptr - mp->b_rptr);
	if (hdrsz < TUNITDATAINDSZ ||
	    hdrsz < (pptr->unitdata_ind.OPT_offset +
		    pptr->unitdata_ind.OPT_length) ||
	    hdrsz < (pptr->unitdata_ind.SRC_offset +
		    pptr->unitdata_ind.SRC_length)) {
		goto bad;
	}

	/*
	 * Make sure that the transport provided a usable address.
	 */
	if (pptr->unitdata_ind.SRC_length <= 0) {
		goto bad;
	}
	/*
	 * Point the remote transport address in the service_transport
	 * handle at the address in the request.
	 */
	clone_xprt->xp_rtaddr.buf = (char *)mp->b_rptr +
	    pptr->unitdata_ind.SRC_offset;
	clone_xprt->xp_rtaddr.len = pptr->unitdata_ind.SRC_length;

	/*
	 * Save the first mblk which contains the T_unidata_ind in
	 * ud_resp.  It will be used to generate the T_unitdata_req
	 * during the reply.
	 */
	if (ud->ud_resp) {
		if (ud->ud_resp->b_cont != NULL) {
			cmn_err(CE_WARN, "svc_clts_krecv: ud_resp %p, "
			    "b_cont %p", (void *)ud->ud_resp,
			    (void *)ud->ud_resp->b_cont);
		}
		freeb(ud->ud_resp);
	}
	ud->ud_resp = mp;
	mp = mp->b_cont;
	ud->ud_resp->b_cont = NULL;

	xdrmblk_init(xdrs, mp, XDR_DECODE, 0);

	TRACE_0(TR_FAC_KRPC, TR_XDR_CALLMSG_START,
	    "xdr_callmsg_start:");
	if (! xdr_callmsg(xdrs, msg)) {
		TRACE_1(TR_FAC_KRPC, TR_XDR_CALLMSG_END,
		    "xdr_callmsg_end:(%S)", "bad");
		RSSTAT_INCR(stats, rsxdrcall);
		goto bad;
	}
	TRACE_1(TR_FAC_KRPC, TR_XDR_CALLMSG_END,
	    "xdr_callmsg_end:(%S)", "good");

	clone_xprt->xp_xid = msg->rm_xid;
	ud->ud_inmp = mp;

	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_END,
	    "svc_clts_krecv_end:(%S)", "good");
	return (TRUE);

bad:
	if (mp)
		freemsg(mp);
	if (ud->ud_resp) {
		/*
		 * There should not be any left over results buffer.
		 */
		ASSERT(ud->ud_resp->b_cont == NULL);
		freeb(ud->ud_resp);
		ud->ud_resp = NULL;
	}

	RSSTAT_INCR(stats, rsbadcalls);
	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_END,
	    "svc_clts_krecv_end:(%S)", "bad");
	return (FALSE);
}
static uint_t
mouse8042_intr(caddr_t arg)
{
	unsigned char    mdata;
	mblk_t *mp;
	struct mouse_state *state = (struct mouse_state *)arg;
	int rc;

	mutex_enter(&state->ms_mutex);

	rc = DDI_INTR_UNCLAIMED;

	for (;;) {

		if (ddi_get8(state->ms_handle,
		    state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) {
			break;
		}

		mdata = ddi_get8(state->ms_handle,
		    state->ms_addr + I8042_INT_INPUT_DATA);

		rc = DDI_INTR_CLAIMED;

		/*
		 * If we're not ready for this data, discard it.
		 */
		if (!state->ready)
			continue;

		mutex_enter(&state->reset_mutex);
		if (state->reset_state != MSE_RESET_IDLE) {

			if (mdata == MSEERROR || mdata == MSERESET) {
				state->reset_state = MSE_RESET_FAILED;
			} else {
				state->reset_state =
				    mouse8042_reset_fsm(state->reset_state,
				    mdata);
			}

			if (state->reset_state == MSE_RESET_ACK) {

			/*
			 * We received an ACK from the mouse, so
			 * send it upstream immediately so that
			 * consumers depending on the immediate
			 * ACK don't time out.
			 */
				if (state->reset_ack_mp != NULL) {

					mp = state->reset_ack_mp;

					state->reset_ack_mp = NULL;

					if (state->ms_rqp != NULL) {
						*mp->b_wptr++ = MSE_ACK;
						putnext(state->ms_rqp, mp);
					} else
						freemsg(mp);
				}

				if (state->ms_wqp != NULL) {
					enableok(state->ms_wqp);
					qenable(state->ms_wqp);
				}

			} else if (state->reset_state == MSE_RESET_IDLE ||
			    state->reset_state == MSE_RESET_FAILED) {

			/*
			 * If we transitioned back to the idle reset state (or
			 * the reset failed), disable the timeout, release the
			 * 8042 exclusive-access lock, then send the response
			 * the the upper-level modules. Finally, enable the
			 * queue and schedule queue service procedures so that
			 * upper-level modules can process the response.
			 * Otherwise, if we're still in the middle of the
			 * reset sequence, do not send the data up (since the
			 * response is sent at the end of the sequence, or
			 * on timeout/error).
			 */

				mutex_exit(&state->reset_mutex);
				(void) quntimeout(state->ms_wqp,
				    state->reset_tid);
				mutex_enter(&state->reset_mutex);

				(void) ddi_get8(state->ms_handle,
				    state->ms_addr + I8042_UNLOCK);

				state->reset_tid = 0;
				if (state->reply_mp != NULL) {
					mp = state->reply_mp;
					if (state->reset_state ==
					    MSE_RESET_FAILED) {
						*mp->b_wptr++ = mdata;
					} else {
						*mp->b_wptr++ = MSE_AA;
						*mp->b_wptr++ = MSE_00;
					}
					state->reply_mp = NULL;
				} else {
					mp = NULL;
				}

				state->reset_state = MSE_RESET_IDLE;
				cv_signal(&state->reset_cv);

				if (mp != NULL) {
					if (state->ms_rqp != NULL)
						putnext(state->ms_rqp, mp);
					else
						freemsg(mp);
				}

				if (state->ms_wqp != NULL) {
					enableok(state->ms_wqp);
					qenable(state->ms_wqp);
				}
			}

			mutex_exit(&state->reset_mutex);
			mutex_exit(&state->ms_mutex);
			return (rc);
		}
		mutex_exit(&state->reset_mutex);

		if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) {
			*mp->b_wptr++ = mdata;
			putnext(state->ms_rqp, mp);
		}
	}
	mutex_exit(&state->ms_mutex);

	return (rc);
}
Exemple #20
0
/*
 * Send rpc reply.
 * Serialize the reply packet into the output buffer then
 * call t_ksndudata to send it.
 */
static bool_t
svc_clts_ksend(SVCXPRT *clone_xprt, struct rpc_msg *msg)
{
	/* LINTED pointer alignment */
	struct udp_data *ud = (struct udp_data *)clone_xprt->xp_p2buf;
	XDR *xdrs = &clone_xprt->xp_xdrout;
	int stat = FALSE;
	mblk_t *mp;
	int msgsz;
	struct T_unitdata_req *udreq;
	xdrproc_t xdr_results;
	caddr_t xdr_location;
	bool_t has_args;

	TRACE_0(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_START,
	    "svc_clts_ksend_start:");

	ASSERT(ud->ud_resp != NULL);

	/*
	 * If there is a result procedure specified in the reply message,
	 * it will be processed in the xdr_replymsg and SVCAUTH_WRAP.
	 * We need to make sure it won't be processed twice, so we null
	 * it for xdr_replymsg here.
	 */
	has_args = FALSE;
	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
		msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
		if ((xdr_results = msg->acpted_rply.ar_results.proc) != NULL) {
			has_args = TRUE;
			xdr_location = msg->acpted_rply.ar_results.where;
			msg->acpted_rply.ar_results.proc = xdr_void;
			msg->acpted_rply.ar_results.where = NULL;
		}
	}

	if (ud->ud_resp->b_cont == NULL) {
		/*
		 * Allocate an initial mblk for the response data.
		 */
		while ((mp = allocb(UD_INITSIZE, BPRI_LO)) == NULL) {
			if (strwaitbuf(UD_INITSIZE, BPRI_LO)) {
				TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_END,
				    "svc_clts_ksend_end:(%S)", "strwaitbuf");
				return (FALSE);
			}
		}

		/*
		 * Initialize the XDR decode stream.  Additional mblks
		 * will be allocated if necessary.  They will be UD_MAXSIZE
		 * sized.
		 */
		xdrmblk_init(xdrs, mp, XDR_ENCODE, UD_MAXSIZE);

		/*
		 * Leave some space for protocol headers.
		 */
		(void) XDR_SETPOS(xdrs, 512);
		mp->b_rptr += 512;

		msg->rm_xid = clone_xprt->xp_xid;

		ud->ud_resp->b_cont = mp;

		TRACE_0(TR_FAC_KRPC, TR_XDR_REPLYMSG_START,
		    "xdr_replymsg_start:");
		if (!(xdr_replymsg(xdrs, msg) &&
			(!has_args || SVCAUTH_WRAP(&clone_xprt->xp_auth, xdrs,
				xdr_results, xdr_location)))) {
			TRACE_1(TR_FAC_KRPC, TR_XDR_REPLYMSG_END,
			    "xdr_replymsg_end:(%S)", "bad");
			RPCLOG0(1, "xdr_replymsg/SVCAUTH_WRAP failed\n");
			goto out;
		}
		TRACE_1(TR_FAC_KRPC, TR_XDR_REPLYMSG_END,
		    "xdr_replymsg_end:(%S)", "good");

	} else if (!(xdr_replymsg_body(xdrs, msg) &&
		    (!has_args || SVCAUTH_WRAP(&clone_xprt->xp_auth, xdrs,
				xdr_results, xdr_location)))) {
		RPCLOG0(1, "xdr_replymsg_body/SVCAUTH_WRAP failed\n");
		goto out;
	}

	msgsz = (int)xmsgsize(ud->ud_resp->b_cont);

	if (msgsz <= 0 || (clone_xprt->xp_msg_size != -1 &&
	    msgsz > clone_xprt->xp_msg_size)) {
#ifdef	DEBUG
		cmn_err(CE_NOTE,
"KRPC: server response message of %d bytes; transport limits are [0, %d]",
			msgsz, clone_xprt->xp_msg_size);
#endif
		goto out;
	}

	/*
	 * Construct the T_unitdata_req.  We take advantage
	 * of the fact that T_unitdata_ind looks just like
	 * T_unitdata_req, except for the primitive type.
	 */
	udreq = (struct T_unitdata_req *)ud->ud_resp->b_rptr;
	udreq->PRIM_type = T_UNITDATA_REQ;

	put(clone_xprt->xp_wq, ud->ud_resp);
	stat = TRUE;
	ud->ud_resp = NULL;

out:
	if (stat == FALSE) {
		freemsg(ud->ud_resp);
		ud->ud_resp = NULL;
	}

	/*
	 * This is completely disgusting.  If public is set it is
	 * a pointer to a structure whose first field is the address
	 * of the function to free that structure and any related
	 * stuff.  (see rrokfree in nfs_xdr.c).
	 */
	if (xdrs->x_public) {
		/* LINTED pointer alignment */
		(**((int (**)())xdrs->x_public))(xdrs->x_public);
	}

	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_END,
	    "svc_clts_ksend_end:(%S)", "done");
	return (stat);
}
Exemple #21
0
static void resample_process_ms2(MSFilter *obj){
	ResampleData *dt=(ResampleData*)obj->data;
	mblk_t *im, *om = NULL, *om_chan = NULL;
	
	if (dt->output_rate==dt->input_rate){
		while((im=ms_queue_get(obj->inputs[0]))!=NULL){
			if (resample_channel_adapt(dt->in_nchannels, dt->out_nchannels, im, &om) == 0) {
				ms_queue_put(obj->outputs[0], im);
			} else {
				ms_queue_put(obj->outputs[0], om);
				freemsg(im);
			}
		}
		return;
	}
	ms_filter_lock(obj);
	if (dt->handle!=NULL){
		unsigned int inrate=0, outrate=0;
		speex_resampler_get_rate(dt->handle,&inrate,&outrate);
		if (inrate!=dt->input_rate || outrate!=dt->output_rate){
			speex_resampler_destroy(dt->handle);
			dt->handle=0;
		}
	}
	if (dt->handle==NULL){
		int err=0;
		dt->handle=speex_resampler_init(dt->in_nchannels, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err);
	}

	
	while((im=ms_queue_get(obj->inputs[0]))!=NULL){
		unsigned int inlen=(im->b_wptr-im->b_rptr)/(2*dt->in_nchannels);
		unsigned int outlen=((inlen*dt->output_rate)/dt->input_rate)+1;
		unsigned int inlen_orig=inlen;
		om=allocb(outlen*2*dt->in_nchannels,0);
		mblk_meta_copy(im, om);
		if (dt->in_nchannels==1){
			speex_resampler_process_int(dt->handle, 
					0, 
					(int16_t*)im->b_rptr, 
					&inlen, 
					(int16_t*)om->b_wptr, 
					&outlen);
		}else{
			speex_resampler_process_interleaved_int(dt->handle, 
					(int16_t*)im->b_rptr, 
					&inlen, 
					(int16_t*)om->b_wptr, 
					&outlen);
		}
		if (inlen_orig!=inlen){
			ms_error("Bug in resampler ! only %u samples consumed instead of %u, out=%u",
				inlen,inlen_orig,outlen);
		}
		om->b_wptr+=outlen*2*dt->in_nchannels;
		mblk_set_timestamp_info(om,dt->ts);
		dt->ts+=outlen;
		if (resample_channel_adapt(dt->in_nchannels, dt->out_nchannels, om, &om_chan) == 0) {
			ms_queue_put(obj->outputs[0], om);
		} else {
			ms_queue_put(obj->outputs[0], om_chan);
			freemsg(om);
		}
		freemsg(im);
	}
	ms_filter_unlock(obj);
}
static void update_sps(DecData *d, mblk_t *sps){
	if (d->sps)
		freemsg(d->sps);
	d->sps=dupb(sps);
}
/* for high level telephony event callback */
void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0)
{
	telephone_event_t *events,*evbuf;
	int num;
	int i;
	mblk_t *mp;
	rtp_header_t *hdr;
	mblk_t *cur_tev;
	
	hdr=(rtp_header_t*)m0->b_rptr;
	mp=m0->b_cont;
	
	num=(mp->b_wptr-mp->b_rptr)/sizeof(telephone_event_t);
	events=(telephone_event_t*)mp->b_rptr;
	
	
	if (hdr->markbit==1)
	{
		/* this is a start of new events. Store the event buffer for later use*/
		if (session->current_tev!=NULL) {
			freemsg(session->current_tev);
			session->current_tev=NULL;
		}
		session->current_tev=copymsg(m0);
		/* handle the case where the events are short enough to end within the packet that has the marker bit*/
		notify_events_ended(session,events,num);
	}
	/* whatever there is a markbit set or not, we parse the packet and compare it to previously received one */
	cur_tev=session->current_tev;
	if (cur_tev!=NULL)
	{
		/* first compare timestamp, they must be identical */
		if (((rtp_header_t*)cur_tev->b_rptr)->timestamp==
			((rtp_header_t*)m0->b_rptr)->timestamp)
		{
			evbuf=(telephone_event_t*)cur_tev->b_cont;
			for (i=0;i<num;i++)
			{
				if (events[i].E==1)
				{
					/* update events that have ended */
					if (evbuf[i].E==0){
						evbuf[i].E=1;
						/* this is a end of event, report it */
						rtp_signal_table_emit2(&session->on_telephone_event,(gpointer)(long)events[i].event);
					}
				}
			}
		}
		else
		{
			/* timestamp are not identical: this is not the same events*/
			if (session->current_tev!=NULL) {
				freemsg(session->current_tev);
				session->current_tev=NULL;
			}
			session->current_tev=dupmsg(m0);
		}
	}
	else
	{
		/* there is no pending events, but we did not received marked bit packet
		either the sending implementation is not compliant, either it has been lost, 
		we must deal with it anyway.*/
		session->current_tev=copymsg(m0);
		/* inform the application if there are tone ends */
		notify_events_ended(session,events,num);
	}
}
static void update_pps(DecData *d, mblk_t *pps){
	if (d->pps)
		freemsg(d->pps);
	if (pps) d->pps=dupb(pps);
	else d->pps=NULL;
}
Exemple #25
0
/*
 * OOTB version of the above.
 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
 */
void
sctp_ootb_send_abort(uint32_t vtag, uint16_t serror, char *details,
    size_t len, const mblk_t *inmp, int iserror, boolean_t tbit,
    ip_recv_attr_t *ira, ip_stack_t *ipst)
{
	uint32_t	ip_hdr_len;
	size_t		ahlen;
	ipha_t		*ipha = NULL;
	ip6_t		*ip6h = NULL;
	sctp_hdr_t	*insctph;
	int		i;
	uint16_t	port;
	ssize_t		alen;
	int		isv4;
	mblk_t		*mp;
	netstack_t	*ns = ipst->ips_netstack;
	sctp_stack_t	*sctps = ns->netstack_sctp;
	ip_xmit_attr_t	ixas;

	bzero(&ixas, sizeof (ixas));

	isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
	ip_hdr_len = ira->ira_ip_hdr_length;
	ahlen = ip_hdr_len + sizeof (sctp_hdr_t);

	/*
	 * If this is a labeled system, then check to see if we're allowed to
	 * send a response to this particular sender.  If not, then just drop.
	 */
	if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
		return;

	mp = allocb(ahlen + sctps->sctps_wroff_xtra, BPRI_MED);
	if (mp == NULL) {
		return;
	}
	mp->b_rptr += sctps->sctps_wroff_xtra;
	mp->b_wptr = mp->b_rptr + ahlen;
	bcopy(inmp->b_rptr, mp->b_rptr, ahlen);

	/*
	 * We follow the logic in tcp_xmit_early_reset() in that we skip
	 * reversing source route (i.e. replace all IP options with EOL).
	 */
	if (isv4) {
		ipaddr_t	v4addr;

		ipha = (ipha_t *)mp->b_rptr;
		for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++)
			mp->b_rptr[i] = IPOPT_EOL;
		/* Swap addresses */
		ipha->ipha_length = htons(ahlen);
		v4addr = ipha->ipha_src;
		ipha->ipha_src = ipha->ipha_dst;
		ipha->ipha_dst = v4addr;
		ipha->ipha_ident = 0;
		ipha->ipha_ttl = (uchar_t)sctps->sctps_ipv4_ttl;

		ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4;
	} else {
		in6_addr_t	v6addr;

		ip6h = (ip6_t *)mp->b_rptr;
		/* Remove any extension headers assuming partial overlay */
		if (ip_hdr_len > IPV6_HDR_LEN) {
			uint8_t	*to;

			to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN;
			ovbcopy(ip6h, to, IPV6_HDR_LEN);
			mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN;
			ip_hdr_len = IPV6_HDR_LEN;
			ip6h = (ip6_t *)mp->b_rptr;
			ip6h->ip6_nxt = IPPROTO_SCTP;
			ahlen = ip_hdr_len + sizeof (sctp_hdr_t);
		}
		ip6h->ip6_plen = htons(ahlen - IPV6_HDR_LEN);
		v6addr = ip6h->ip6_src;
		ip6h->ip6_src = ip6h->ip6_dst;
		ip6h->ip6_dst = v6addr;
		ip6h->ip6_hops = (uchar_t)sctps->sctps_ipv6_hoplimit;

		ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6;
		if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_dst)) {
			ixas.ixa_flags |= IXAF_SCOPEID_SET;
			ixas.ixa_scopeid = ira->ira_ruifindex;
		}
	}
	insctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_len);

	/* Swap ports.  Verification tag is reused. */
	port = insctph->sh_sport;
	insctph->sh_sport = insctph->sh_dport;
	insctph->sh_dport = port;
	insctph->sh_verf = vtag;

	/* Link in the abort chunk */
	if ((alen = sctp_link_abort(mp, serror, details, len, iserror, tbit))
	    < 0) {
		freemsg(mp);
		return;
	}

	ixas.ixa_pktlen = ahlen + alen;
	ixas.ixa_ip_hdr_length = ip_hdr_len;

	if (isv4) {
		ipha->ipha_length = htons(ixas.ixa_pktlen);
	} else {
		ip6h->ip6_plen = htons(ixas.ixa_pktlen - IPV6_HDR_LEN);
	}

	ixas.ixa_protocol = IPPROTO_SCTP;
	ixas.ixa_zoneid = ira->ira_zoneid;
	ixas.ixa_ipst = ipst;
	ixas.ixa_ifindex = 0;

	SCTPS_BUMP_MIB(sctps, sctpAborted);

	if (is_system_labeled()) {
		ASSERT(ira->ira_tsl != NULL);

		ixas.ixa_tsl = ira->ira_tsl;	/* A multi-level responder */
	}

	if (ira->ira_flags & IRAF_IPSEC_SECURE) {
		/*
		 * Apply IPsec based on how IPsec was applied to
		 * the packet that was out of the blue.
		 */
		if (!ipsec_in_to_out(ira, &ixas, mp, ipha, ip6h)) {
			BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
			/* Note: mp already consumed and ip_drop_packet done */
			return;
		}
	} else {
		/*
		 * This is in clear. The abort message we are building
		 * here should go out in clear, independent of our policy.
		 */
		ixas.ixa_flags |= IXAF_NO_IPSEC;
	}

	(void) ip_output_simple(mp, &ixas);
	ixa_cleanup(&ixas);
}
Exemple #26
0
static void sdl_out_process(MSFilter *f){
	SdlOut *obj=(SdlOut*)f->data;
	mblk_t *inm0=NULL;
	mblk_t *inm1=NULL;
	int err;
	SDL_Rect smallrect;
	SDL_Rect rect;
	bool_t got_preview=FALSE;
	
#if defined(WIN32) || defined(__APPLE__)
	if (!sdl_initialized){

		/* Initialize the SDL library */
		if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
			ms_error("Couldn't initialize SDL: %s", SDL_GetError());
			return;
		}
		/* Clean up on exit */
		atexit(SDL_Quit);
		sdl_initialized=TRUE;
	}
#endif

	if (obj->screen==NULL){
		sdl_create_window(obj);
	}

	rect.w=obj->size.width;
	rect.h=obj->size.height;
	rect.x=0;
	rect.y=0;
	smallrect.w=obj->size.width/SCALE_FACTOR;
	smallrect.h=obj->size.height/SCALE_FACTOR;
	smallrect.x=obj->size.width - smallrect.w ;
	smallrect.y=obj->size.height -smallrect.h;
	
	
	while (f->inputs[0]!=NULL && (inm0=ms_queue_get(f->inputs[0]))!=NULL){
		SDL_Surface *surf;
		if  (obj->format==MS_YUV420P){
			fill_overlay(obj->overlay,inm0);
		}else {
			surf=SDL_CreateRGBSurfaceFrom(inm0->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);

			err=SDL_BlitSurface(surf,NULL,obj->screen,NULL);
			if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError());
			SDL_FreeSurface(surf);
		}
		freemsg(inm0);
	}
	while (f->inputs[1]!=NULL && (inm1=ms_queue_get(f->inputs[1]))!=NULL){
		/* this message is blitted on the right,bottom corner of the screen */
		SDL_Surface *surf;
		got_preview=TRUE;
		if (!obj->lsize_init){
			/*attempt to guess the video size of the local preview buffer*/
			int bsize=msgdsize(inm1);
			if (bsize<(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3/2)){
				/*surely qcif ?*/
				obj->local_size.width=MS_VIDEO_SIZE_QCIF_W;
				obj->local_size.height=MS_VIDEO_SIZE_QCIF_H;
				ms_message("preview is in QCIF.");
				obj->scale_factor=SCALE_FACTOR/2;
			}
			obj->lsize_init=TRUE;
		}
		if  (obj->format==MS_YUV420P){
			if (obj->smallb!=NULL) {
				freemsg(obj->smallb);
			}
			obj->smallb=resize_yuv_small(inm1->b_rptr,obj->local_size.width,obj->local_size.height,obj->scale_factor);
			fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h);
			freemsg(inm1);
		}else {
			surf=SDL_CreateRGBSurfaceFrom(inm1->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);

			err=SDL_BlitSurface(surf,NULL,obj->screen,&smallrect);
			if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError());
			SDL_FreeSurface(surf);
		}
	}
	if (!got_preview){
		/* this is the case were we have only inm0, we have to redisplay inm1 */
		if  (obj->format==MS_YUV420P){
			if (obj->smallb!=NULL){
				fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h);
			}
		}
	}
	
	if (obj->format==MS_YUV420P) SDL_DisplayYUVOverlay(obj->overlay,&rect);
	else SDL_UpdateRect(obj->screen,0,0,obj->size.width,obj->size.height);
	
#if defined(WIN32) || defined(__APPLE__)
	{
		SDL_Event event;
		SDL_PollEvent(&event);
	}
#endif
}
static void * alsa_write_thread(void *p){
	AlsaReadData *ad=(AlsaReadData*)p;
	int samples=(160*ad->rate)/8000;
	int err;
	int count=0;
	mblk_t *om=NULL;
	struct timeval timeout;
	if (ad->handle==NULL && ad->pcmdev!=NULL){
		ad->handle=alsa_open_r(ad->pcmdev,16,ad->nchannels==2,ad->rate);
	}
	if (ad->handle==NULL) return NULL;

	while (ad->read_started)
	  {
	    count = alsa_can_read(ad->handle,samples);
	    if (count==24)
	      { /* keep this value for this driver */ }
	    else if (count<=0)
	      {
		count = samples;
	      }
	    else if (count>0)
	      {
		//ms_warning("%i count", count);
		//count = samples;
	      }

	    int size=count*2;
	    om=allocb(size,0);

	    if ((err=alsa_read(ad->handle,om->b_wptr,count))<=0)
	      {
		ms_warning("nothing to read");
		//ms_warning("Fail to read samples %i", count);
		freemsg(om); /* leak fixed */
		continue;
	      }
	    //ms_warning(" read %i", err);
	    
	    size=err*2;
	    om->b_wptr+=size;

	    ms_mutex_lock(&ad->mutex);
	    ms_bufferizer_put(ad->bufferizer,om);
	    ms_mutex_unlock(&ad->mutex);

	    if (count==24)
	      {
		timeout.tv_sec = 0;
		timeout.tv_usec = 2000;
		select(0, 0, NULL, NULL, &timeout );
	      }
	    else
	      {
		/* select will be less active than locking on "read" */
		timeout.tv_sec = 0;
		timeout.tv_usec = 5000;
		select(0, 0, NULL, NULL, &timeout );
	      }
	  }

	if (ad->handle!=NULL) snd_pcm_close(ad->handle);
	ad->handle=NULL;
	return NULL;
}
Exemple #28
0
static void sdl_out_uninit(MSFilter *f){
	SdlOut *s=(SdlOut*)f->data;
	sdl_destroy_window(s);
	if (s->smallb!=NULL) freemsg(s->smallb);
	ms_free(s);
}
/*
 * Add a new message to the socket
 */
int
rds_deliver_new_msg(mblk_t *mp, ipaddr_t local_addr, ipaddr_t rem_addr,
    in_port_t local_port, in_port_t rem_port, zoneid_t zoneid)
{
	rds_t *rds;
	struct  T_unitdata_ind  *tudi;
	int	udi_size;	/* Size of T_unitdata_ind */
	mblk_t *mp1;
	sin_t	*sin;
	int error = 0;

	local_port = htons(local_port);
	rem_port = htons(rem_port);

	ASSERT(mp->b_datap->db_type == M_DATA);
	rds = rds_fanout(local_addr, rem_addr, local_port, rem_port, zoneid);
	if (rds == NULL) {
		dprint(2, ("%s: rds_fanout failed: (0x%x 0x%x %d %d)", LABEL,
		    local_addr, rem_addr, ntohs(local_port), ntohs(rem_port)));
		freemsg(mp);
		return (error);
	}

	udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t);

	/* Allocate a message block for the T_UNITDATA_IND structure. */
	mp1 = allocb(udi_size, BPRI_MED);
	if (mp1 == NULL) {
		dprint(2, ("%s: allocb failed", LABEL));
		freemsg(mp);
		return (ENOMEM);
	}

	mp1->b_cont = mp;
	mp = mp1;
	mp->b_datap->db_type = M_PROTO;
	tudi = (struct T_unitdata_ind *)(uintptr_t)mp->b_rptr;
	mp->b_wptr = (uchar_t *)tudi + udi_size;
	tudi->PRIM_type = T_UNITDATA_IND;
	tudi->SRC_length = sizeof (sin_t);
	tudi->SRC_offset = sizeof (struct T_unitdata_ind);
	tudi->OPT_offset = sizeof (struct T_unitdata_ind) + sizeof (sin_t);
	udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t));
	tudi->OPT_length = udi_size;
	sin = (sin_t *)&tudi[1];
	sin->sin_addr.s_addr = rem_addr;
	sin->sin_port = ntohs(rem_port);
	sin->sin_family = rds->rds_family;
	*(uint32_t *)(uintptr_t)&sin->sin_zero[0] = 0;
	*(uint32_t *)(uintptr_t)&sin->sin_zero[4] = 0;

	putnext(rds->rds_ulpd, mp);

	/* check port quota */
	if (RDS_GET_RXPKTS_PEND() > rds_rx_pkts_pending_hwm) {
		ulong_t current_port_quota = RDS_GET_PORT_QUOTA();
		if (rds->rds_port_quota > current_port_quota) {
			/* this may result in stalling the port */
			rds->rds_port_quota = current_port_quota;
			(void) proto_set_rx_hiwat(rds->rds_ulpd, NULL,
			    rds->rds_port_quota * UserBufferSize);
			RDS_INCR_PORT_QUOTA_ADJUSTED();
		}
	}

	/*
	 * canputnext() check is done after putnext as the protocol does
	 * not allow dropping any received packet.
	 */
	if (!canputnext(rds->rds_ulpd)) {
		error = ENOSPC;
	}

	RDS_DEC_REF_CNT(rds);
	return (error);
}
/*
 * Read-side put procedure.  It's responsible for applying the
 * packet filter and passing upstream message on or discarding it
 * depending upon the results.
 *
 * Upstream messages can start with zero or more M_PROTO mblks
 * which are skipped over before executing the packet filter
 * on any remaining M_DATA mblks.
 */
static void
pfrput(queue_t *rq, mblk_t *mp)
{
	struct	epacketfilt	*pfp = (struct epacketfilt *)rq->q_ptr;
	mblk_t	*mbp, *mpp;
	struct	packdesc	pd;
	int	need;

	ASSERT(pfp);

	switch (DB_TYPE(mp)) {
	case M_PROTO:
	case M_DATA:
		/*
		 * Skip over protocol information and find the start
		 * of the message body, saving the overall message
		 * start in mpp.
		 */
		for (mpp = mp; mp && (DB_TYPE(mp) == M_PROTO); mp = mp->b_cont)
			;

		/*
		 * Null body (exclusive of M_PROTO blocks) ==> accept.
		 * Note that a null body is not the same as an empty body.
		 */
		if (mp == NULL) {
			putnext(rq, mpp);
			break;
		}

		/*
		 * Pull the packet up to the length required by
		 * the filter.  Note that doing so destroys sharing
		 * relationships, which is unfortunate, since the
		 * results of pulling up here are likely to be useful
		 * for shared messages applied to a filter on a sibling
		 * stream.
		 *
		 * Most packet sources will provide the packet in two
		 * logical pieces: an initial header in a single mblk,
		 * and a body in a sequence of mblks hooked to the
		 * header.  We're prepared to deal with variant forms,
		 * but in any case, the pullup applies only to the body
		 * part.
		 */
		mbp = mp->b_cont;
		need = pfp->pf_PByteLen;
		if (mbp && (MBLKL(mbp) < need)) {
			int len = msgdsize(mbp);

			/* XXX discard silently on pullupmsg failure */
			if (pullupmsg(mbp, MIN(need, len)) == 0) {
				freemsg(mpp);
				break;
			}
		}

		/*
		 * Misalignment (not on short boundary) ==> reject.
		 */
		if (((uintptr_t)mp->b_rptr & (sizeof (ushort_t) - 1)) ||
		    (mbp != NULL &&
		    ((uintptr_t)mbp->b_rptr & (sizeof (ushort_t) - 1)))) {
			freemsg(mpp);
			break;
		}

		/*
		 * These assignments are distasteful, but necessary,
		 * since the packet filter wants to work in terms of
		 * shorts.  Odd bytes at the end of header or data can't
		 * participate in the filtering operation.
		 */
		pd.pd_hdr = (ushort_t *)mp->b_rptr;
		pd.pd_hdrlen = (mp->b_wptr - mp->b_rptr) / sizeof (ushort_t);
		if (mbp) {
			pd.pd_body = (ushort_t *)mbp->b_rptr;
			pd.pd_bodylen = (mbp->b_wptr - mbp->b_rptr) /
							sizeof (ushort_t);
		} else {
			pd.pd_body = NULL;
			pd.pd_bodylen = 0;
		}

		/*
		 * Apply the filter.
		 */
		if (FilterPacket(&pd, pfp))
			putnext(rq, mpp);
		else
			freemsg(mpp);

		break;

	default:
		putnext(rq, mp);
		break;
	}

}