|
From: Orjan F. <or...@us...> - 2003-03-30 17:14:20
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Tag Comment
---- ----------- ----------- --- -------
bnep.c 1.16 1.17=20=20=20=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
(On behalf of anderstj.) Added support for forwarding unknown extension
headers.
The diff of the modified file(s):
--- bnep.c 9 Jan 2003 09:56:19 -0000 1.16
+++ bnep.c 30 Mar 2003 17:13:31 -0000 1.17
@@ -112,6 +112,7 @@
#endif
=20
#define BNEP_INTERFACES 7
+#define MAX_EHEADERS 20
=20
/****************** TYPE DEFINITION SECTION ******************************=
***/
=20
@@ -708,6 +709,9 @@
struct net_device *dev;
struct net_local *local;
struct ethhdr *eth, eth_header;
+ bt_tx_buf *tx_buf;
+ u8 *unknown_eheaders[MAX_EHEADERS];
+ u8 eheader_count =3D 0;
u8 type;
u8 eheaders;
int blen,skblen;
@@ -847,8 +851,13 @@
break;
=20
default:
- D_ERR(__FUNCTION__": Unknown extension header %02x length %i\n",
+ D_ERR(__FUNCTION__": Unknown extension header %02x length %i, store tem=
porarily for receiving PANU\n",
type, eheader->length);
+ if (eheader_count < MAX_EHEADERS) {
+ unknown_eheaders[eheader_count++] =3D data=
+ pos;
+ } else {
+ D_ERR(__FUNCTION__": Too many extension he=
aders\n");
+ }
}
=20
pos +=3D eheader->length + 2;
@@ -858,6 +867,109 @@
}
}
=20
+ /* If we found any unknown eheaders we must forward them if the destinati=
on
+ address belongs to a PANU currently connected to us */
+ if(eheader_count && eth_frame) {
+ struct net_local *remote;
+ int i, j;
+ for (i =3D 0; i < BNEP_INTERFACES; i++) {
+ remote =3D dev_bnep[i].priv;
+ if (remote !=3D NULL && remote->l2cap !=3D NULL && remote->l2cap->remot=
e_bd !=3D NULL) {
+ for(j =3D 0 ; j < 6 ; j++) {
+ if(eth->h_dest[j] !=3D remote->l2cap->remote_bd[5 - j]) {
+ break;
+ }
+ }
+=09=09=09=09
+ if(j =3D=3D 6) {
+ break;
+ }
+ }
+ }
+=09=09
+ if(i !=3D BNEP_INTERFACES) {
+ /* OK, this PANU is connected to us, let's forward
+ all data with the unknown extentionheaders to
+ the PANU */
+ struct bnep_compressed_ethernet_source_only bnep_c_s;
+ struct bnep_eheader *eheader;
+ u16 totallen;
+
+ bnep_c_s.bnep_type =3D BNEP_COMPRESSED_ETHERNET_SOURCE_ONLY | 0x80;
+ bnep_c_s.type =3D eth->h_proto;
+ for ( i =3D 0 ; i < 6; i++) {
+ bnep_c_s.saddr[i] =3D eth->h_source[i];
+ }
+
+ totallen =3D sizeof(struct bnep_compressed_ethernet_source_only);
+=09=09=09
+ /* Calculate length for all eheaders and make sure eheader-bit is set */
+ for(i =3D 0 ; i < eheader_count ; i++)
+ {
+ totallen +=3D sizeof(struct bnep_eheader);
+ eheader =3D (struct bnep_eheader *)unknown_eheaders[i];
+ totallen +=3D eheader->length;
+ eheader->bnep_type |=3D 0x80;
+ }
+=09=09=09
+ /* Clear last extension bit in eheaders */
+ eheader->bnep_type &=3D 0x7f;
+
+ /* Calculate length for the payload data */
+ totallen +=3D (len - pos);
+=09=09=09
+ /* Subscribe from memorybuffer */
+ if (buf_write_room() < totallen) {
+ D_XMIT(__FUNCTION__": not enough room for a %d byte bt_tx_buf\n", skb-=
>len);
+ /* don't necessarily need to discard the buffer; could set dev->tbusy =
=3D 1
+ and then start a timer to check for free buffer space */
+ local->stats.tx_dropped++;
+ return;
+=09=09=09=09
+ } else {
+ int header_len =3D sizeof(struct bnep_compressed_ethernet_source_only);
+ /* subscribe to a bt_tx_buf */
+ D_XMIT("New bt buf length %i \n", totallen);
+ if ((tx_buf =3D subscribe_bt_buf(totallen + sizeof(bnep_tx_buf))) =3D=
=3D NULL) {
+ D_ERR(__FUNCTION__": failed to subscribe %d bytes\n",=20
+ totallen);
+ remote->stats.tx_dropped++;
+ return;
+=09=09=09=09=09
+ } else {
+ /* copy the header to the bt_tx_buf */
+ memcpy(tx_buf->data + sizeof(bnep_tx_buf),=20
+ &bnep_c_s,=20
+ header_len);
+=09=09=09=09=09
+ /* copy all extension headers into buffer */
+ j =3D 0;
+ for(i =3D 0 ; i < eheader_count ; i++) {
+ eheader =3D (struct bnep_eheader *)unknown_eheaders[i];
+ printk("Copy eheader val: %02x, len %02x\n", eheader->bnep_type, ehe=
ader->length);
+ memcpy(tx_buf->data + sizeof(bnep_tx_buf) + header_len + j,=20
+ unknown_eheaders[i], eheader->length + sizeof(struct bnep_ehe=
ader));
+ j +=3D eheader->length + sizeof(struct bnep_eheader);
+ }
+=09=09=09=09=09
+ /* copy rest of the payload data */
+ memcpy(tx_buf->data + sizeof(bnep_tx_buf) + header_len + j,
+ data + pos,
+ len - pos);
+=09
+ tx_buf->cur_len =3D header_len + j + (len - pos);
+ /* transmit the packet */
+ D_XMIT("bnep: tx packet\n");
+ /* update the device statistics */
+ remote->stats.tx_packets++;
+ remote->stats.tx_bytes +=3D totallen;
+ l2cap_send_data(tx_buf, remote->l2cap);
+ return;
+ }
+ }
+ }
+ }=09=09
+
if (eth_frame =3D=3D 1) {
D_REC("eth header src %02x.%02x.%02x.%02x.%02x.%02x "
"dst %02x.%02x.%02x.%02x.%02x.%02x type %04x\n",=20
@@ -1255,7 +1367,7 @@
(void*)&rsp,
sizeof(struct bnep_control_command_not_understood));
tx_buf->cur_len =3D sizeof(struct bnep_control_command_not_understood);
- D_MISC("BNEP send filter response msg\n");
+ D_MISC("BNEP send command not understood response msg\n");
l2cap_send_data(tx_buf, local->l2cap);
}
}
|