Beispiel #1
0
static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
{
	struct sk_buff *skb;
	struct cdc_mbim_state *info = (void *)&dev->data;
	struct cdc_ncm_ctx *ctx = info->ctx;
	int len;
	int nframes;
	int x;
	int offset;
	struct usb_cdc_ncm_ndp16 *ndp16;
	struct usb_cdc_ncm_dpe16 *dpe16;
	int ndpoffset;
	int loopcount = 50; /* arbitrary max preventing infinite loop */
	u8 *c;
	u16 tci;

	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
	if (ndpoffset < 0)
		goto error;

next_ndp:
	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
	if (nframes < 0)
		goto error;

	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);

	switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
	case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
		c = (u8 *)&ndp16->dwSignature;
		tci = c[3];
		break;
	case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
		c = (u8 *)&ndp16->dwSignature;
		tci = c[3] + 256;
		break;
	default:
		netif_dbg(dev, rx_err, dev->net,
			  "unsupported NDP signature <0x%08x>\n",
			  le32_to_cpu(ndp16->dwSignature));
		goto err_ndp;

	}

	dpe16 = ndp16->dpe16;
	for (x = 0; x < nframes; x++, dpe16++) {
		offset = le16_to_cpu(dpe16->wDatagramIndex);
		len = le16_to_cpu(dpe16->wDatagramLength);

		/*
		 * CDC NCM ch. 3.7
		 * All entries after first NULL entry are to be ignored
		 */
		if ((offset == 0) || (len == 0)) {
			if (!x)
				goto err_ndp; /* empty NTB */
			break;
		}

		/* sanity checking */
		if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
			netif_dbg(dev, rx_err, dev->net,
				  "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
				  x, offset, len, skb_in);
			if (!x)
				goto err_ndp;
			break;
		} else {
			skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
			if (!skb)
				goto error;
			usbnet_skb_return(dev, skb);
		}
	}
err_ndp:
	/* are there more NDPs to process? */
	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	if (ndpoffset && loopcount--)
		goto next_ndp;

	return 1;
error:
	return 0;
}
Beispiel #2
0
static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
{
	struct sk_buff *skb;
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
	int len;
	int nframes;
	int x;
	int offset;
	struct usb_cdc_ncm_ndp16 *ndp16;
	struct usb_cdc_ncm_dpe16 *dpe16;
	int ndpoffset;
	int loopcount = 50; /* arbitrary max preventing infinite loop */

	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
	if (ndpoffset < 0)
		goto error;

next_ndp:
	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
	if (nframes < 0)
		goto error;

	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);

	if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
		pr_debug("invalid DPT16 signature <%u>\n",
			 le32_to_cpu(ndp16->dwSignature));
		goto err_ndp;
	}
	dpe16 = ndp16->dpe16;

	for (x = 0; x < nframes; x++, dpe16++) {
		offset = le16_to_cpu(dpe16->wDatagramIndex);
		len = le16_to_cpu(dpe16->wDatagramLength);

		/*
		 * CDC NCM ch. 3.7
		 * All entries after first NULL entry are to be ignored
		 */
		if ((offset == 0) || (len == 0)) {
			if (!x)
				goto err_ndp; /* empty NTB */
			break;
		}

		/* sanity checking */
		if (((offset + len) > skb_in->len) ||
				(len > ctx->rx_max) || (len < ETH_HLEN)) {
			pr_debug("invalid frame detected (ignored)"
					"offset[%u]=%u, length=%u, skb=%p\n",
					x, offset, len, skb_in);
			if (!x)
				goto err_ndp;
			break;

		} else {
			skb = skb_clone(skb_in, GFP_ATOMIC);
			if (!skb)
				goto error;
			skb->len = len;
			skb->data = ((u8 *)skb_in->data) + offset;
			skb_set_tail_pointer(skb, len);
			usbnet_skb_return(dev, skb);
		}
	}
err_ndp:
	/* are there more NDPs to process? */
	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	if (ndpoffset && loopcount--)
		goto next_ndp;

	return 1;
error:
	return 0;
}
BOOLEAN cdc_ncm_rx_fixup(PMP_ADAPTER Adapter, PRCB prcb)
{
	NTSTATUS NtStatus=STATUS_SUCCESS;
	PMP_USBPIPE usbpipe=Adapter->UsbPipeForNIC;
	NCMDWORD len;
	int nframes;
	int x;
	int offset;
	PUSB_CDC_NCM_NDP16 ndp16;
	PUSB_CDC_NCM_DPE16 dpe16;
	int ndpoffset,ndeoffset;
	int currentFrame;
	int indexArray=0;
	int loopcount = 50; /* arbitrary max preventing infinite loop */

	if(prcb->bIsOver) return TRUE;

	ndpoffset=prcb->nextndpoffset;
	ndeoffset=prcb->nextndeoffset;

	if (0==ndpoffset)
	{
		NtStatus=cdc_ncm_rx_verify_nth16(Adapter, prcb,&ndpoffset);
		if (!NT_SUCCESS(NtStatus))
			goto error;
	}

next_ndp:
	NtStatus = cdc_ncm_rx_verify_ndp16(prcb, ndpoffset,&nframes);
	if (!NT_SUCCESS(NtStatus))
		goto error;

	ndp16 = (PUSB_CDC_NCM_NDP16)(prcb->pDataForNTB + ndpoffset);

	if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
		DEBUGP(MP_ERROR,("invalid DPT16 signature <%#010x>\n",le32_to_cpu(ndp16->dwSignature)) );
		goto err_ndp;
	}
	if(0==ndeoffset)
	   dpe16 = ndp16->dpe16;
	else
	   dpe16=(PUSB_CDC_NCM_DPE16)((PUCHAR)ndp16+ndeoffset);

     currentFrame=(int)((dpe16-ndp16->dpe16)/sizeof(USB_CDC_NCM_DPE16));

	for (x = currentFrame; x < nframes; x++, dpe16++) {
		offset = le16_to_cpu(dpe16->wDatagramIndex);
		len = le16_to_cpu(dpe16->wDatagramLength);

		/*
		* CDC NCM ch. 3.7
		* All entries after first NULL entry are to be ignored
		*/
		if ((offset == 0) || (len == 0)) {
			if (!x)
				goto err_ndp; /* empty NTB */
			break;
		}

		/* sanity checking */
		if (((offset + len) > prcb->ulSize) ||
			(len > usbpipe->rx_max) || (len < ETH_HEADER_SIZE)) {
				DEBUGP(MP_ERROR,("invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
					x, offset, len, prcb) );
				if (!x)
					goto err_ndp;
				break;

		} else { 
			if(indexArray>=RCB_BUFFERARRAY_SIZE)
			{
				prcb->nextndpoffset=ndpoffset;
				prcb->nextndeoffset=(NCMDWORD)((PUCHAR)dpe16-(PUCHAR)ndp16);
				return FALSE;
			}
			else{
			 NICIndicateReceivedPacket(prcb,offset,len,indexArray); 
			 Adapter->GoodReceives++;
			 indexArray++;
			}
		}
	}
err_ndp:
	/* are there more NDPs to process? */
	ndpoffset = le16_to_cpu(ndp16->wNextFpIndex);
	if (ndpoffset && loopcount--)
		goto next_ndp;
	else
	{
		prcb->bIsOver=TRUE;
	}
error:
	if (!NT_SUCCESS(NtStatus))
	{
		prcb->bIsOver=TRUE;
	}
	return prcb->bIsOver;
}