[governance] Batteries Not Included - Some Assembly Required
Jim Fleming
JimFleming at ameritech.net
Sat Dec 24 09:09:50 EST 2005
As noted in another message, all of the LAN packets are converted to a
common format
with 64-bit addressing. That also includes the packets that are being routed
between two
boxes connected to the local bridge. That helps to test the transparency of
the tunnel code
and it makes it easy to toss the routing header on the front, to send to a
remote site.
Also note, the IP addresses are always 0.0.0.1 for source and destination.
Only the low
4 bits are preserved. That of course includes the 1. The 48-bit MAC address
provides most
of the address bits. The user can change that via their TV interface to
match an ISP's specs.
[Note: 4 bytes of overhead are now sent, rather than 3 to preserve all of
the Port bits.]
local_mac:
local = 1;
/* Analyze non-LAN parts of packet */
p = &U8in[20];
/* Must be UDP */
if(p[9]==0x11){
src_port=(p[20]<<8)+p[21];
dst_port=(p[22]<<8)+p[23];
udp_len=(p[24]<<8)+p[25];
//printk("udp_len=%d\n",udp_len);
}
else{
goto done;
}
/* Only look at C02 Port */
if(!((src_port==LAN_PORT)&&(dst_port==LAN_PORT))){
goto done;
}
/* Dig out the useless IP addresses */
src_ip=(p[12]<<24)+(p[13]<<16)+(p[14]<<8)+p[15];
dst_ip=(p[16]<<24)+(p[17]<<16)+(p[18]<<8)+p[19];
//printk("src_ip=%x\n",src_ip);
//printk("dst_ip=%x\n",dst_ip);
/* IP is 0.0.0.1 at least for source */
if(src_ip!=1){
//printk("RAWE: Skipping IP=%x\n",src_ip);
goto done;
}
tos = p[1];
//printk("tos=%02X\n",tos);
ident=(p[4]<<8)+p[5];
//printk("ident=%04X\n",ident);
/* Check for true broadcast packets */
if((dst_ip==0xFFFFFFFF) && (dst_mac==0x0000FFFFFFFFFFFF)){
global=1;
//dst_mac = 0xFFFFFFFFFFFFFFFF;
}
else{
global=0;
}
/* Build the Uni.X version of the packet */
u = &U8out[20];
/* Header(20)+TOS(1)+ID(2)+UDP_DATA-UDP_HDR(8) */
length = 20+1+2+udp_len-8;
/* collect stats */
if(length > maxlen){
maxlen = length;
//printk("RAWE: new maxlen=%d\n",maxlen);
}
if(length > 1023){
//printk("RAWE: Uni.X dropped %d\n",length);
rawe_exit();
goto done;
}
SET_V16_global(u,global);
SET_V16_hops(u,7);
SET_V16_protocol(u,UDP_11);
//printk("set length=%d\n",length);
SET_V16_length(u,length);
/* Use 12 bits of the UDP port */
Saddr_set(u,(((U64)src_port&0x0FFF)<<52)|((src_mac&0x0000FFFFFFFFFFFF)<<4)|(
src_ip&0x0F));
Daddr_set(u,(((U64)dst_port&0x0FFF)<<52)|((dst_mac&0x0000FFFFFFFFFFFF)<<4)|(
dst_ip&0x0F));
/* just in case burn 3 bytes and send original tos and ident */
******* NOTE this is now 4 bytes - all of the Port Bits are Preserved
*******
u[20]=tos;
u[21]=ident>>8;
u[22]=ident;
p += 20+8;
for(i=0; i<(udp_len-8); i++){
//printk("%02X:",*p);
compress2[i]=compress1[i];
compress1[i]=*p;
printk("%02X:",compress1[i]^compress2[i]);
u[23+i]=*p++;
}
//printk("\n");
SET_V16_checksum(u,0);
SET_V16_checksum(u,Checksum_of(u,length,0));
Msg_dump(u);
//Msg_printhex_length(u,60);
if(router_dev == 0){
goto mixer2;
}
/* build routing header */
U8out[0]=0x45;
U8out[1]=0x00;
length=20+GET_V16_length(u);
//printk("pre-length=%d\n",length);
U8out[2]=length>>8;
U8out[3]=length;
rawe_ident++;
//printk("rawe_ident=%x\n",rawe_ident);
last_sent = rawe_ident;
U8out[4]=rawe_ident<<8;
U8out[5]=rawe_ident;
/* dont fragment */
U8out[6]=0xC0;
U8out[7]=0;
U8out[8]=63;
U8out[9]=97;
U8out[10]=0;
U8out[11]=0;
U8out[12]=(local_ip>>24); U8out[13]=(local_ip>>16);
U8out[14]=(local_ip>>8); U8out[15]=local_ip;
U8out[16]=(remote_ip>>24); U8out[17]=(remote_ip>>16);
U8out[18]=(remote_ip>>8); U8out[19]=remote_ip;
SET_V16_checksum(U8out,0);
SET_V16_checksum(U8out,Checksum_of(U8out,GET_V16_length(U8out),0));
/* Both headers are ready here */
//Msg_printhex_length(&U8out[0],20);
size = 2*ETH_ALEN + 2 + length;
if((skb3 = dev_alloc_skb(size)) == NULL){
//printk("RAWE: dev_alloc_skb failed\n");
rawe_exit();
goto done;
}
memcpy(skb_put(skb3,size),&router_header[0],14);
skb3->mac.raw=skb3->data;
memcpy(&(skb3->mac.raw[14]),&U8out[0],length);
//Msg_printhex_length(skb3->mac.raw,14+length);
skb3->dev=router_dev;
skb3->pkt_type=PACKET_HOST;
dev_queue_xmit(skb3);
mixer2:
//printk("mixer2\n");
u = &U8out[20];
//Msg_dump(u);
global = GET_V16_global(u);
src_addr=Saddr_get(u);
dst_addr=Daddr_get(u);
printk("Saddr_get addr=%016.llX\n",src_addr);
printk("Daddr_get addr=%016.llX\n",dst_addr);
if((((src_addr>>52)&0x0FFF)==LAN_PORT)&&(((dst_addr>>52)&0xFFF)==LAN_PORT)){
src_addr >>= 4;
dst_addr >>= 4;
}
else{
return 0;
}
length = GET_V16_length(u);
//printk("length=%d\n",length);
/* size is what will be sent on wire */
size = (2*6)+2+length-1-2+8;
//printk("size=%d\n",size);
if(local && router_src){
//printk("RAWE: ALERT Should not happen\n");
goto done;
}
if(local && (router_src == 0)){
//printk("Local packet with no tunnel up\n");
goto route_local;
}
if((local == 0) && (router_src == 0)){
//printk("Remote packet and No Tunnel ???? HOW ???\n");
}
if((local == 0) && (state0 == LOCK_STATE)){
//printk("mac0 is free for remote mac\n");
mac0 = src_addr;
state0 = REMOTE_STATE;
dev0 = NULL;
}
if((local == 0) && (state1 == LOCK_STATE)){
//printk("mac1 is free for remote mac\n");
mac1 = src_addr;
state1 = REMOTE_STATE;
dev1 = NULL;
}
/*
* Route to any local directly connected devices
*/
route_local:
//printk("route local\n");
//printk("src_addr=%016.llX\n",src_addr);
//printk("dst_addr=%016.llX\n",dst_addr);
//printk("mac0=%016.llX\n",mac0);
//printk("mac1=%016.llX\n",mac1);
if((skb2 = dev_alloc_skb(size)) == NULL){
//printk("RAWE: dev_alloc_skb failed\n");
rawe_exit();
goto done;
}
// skb2->dev = dev;
skb2->protocol = __constant_htons(ETH_P_IP);
skb2->mac.raw = skb_put(skb2,size);
skb2->mac.raw[0]=dst_addr>>40;
skb2->mac.raw[1]=dst_addr>>32;
skb2->mac.raw[2]=dst_addr>>24;
skb2->mac.raw[3]=dst_addr>>16;
skb2->mac.raw[4]=dst_addr>>8;
skb2->mac.raw[5]=dst_addr;
skb2->mac.raw[6]=src_addr>>40;
skb2->mac.raw[7]=src_addr>>32;
skb2->mac.raw[8]=src_addr>>24;
skb2->mac.raw[9]=src_addr>>16;
skb2->mac.raw[10]=src_addr>>8;
skb2->mac.raw[11]=src_addr;
skb2->mac.raw[12]=8;
skb2->mac.raw[13]=0;
skb2->nh.raw = &(skb2->mac.raw[14]);
/* length now becomes the legacy length */
length = length-1-2+8;
/* v4 and header length fixed to 5 */
skb2->nh.raw[0]=0x45;
/* tos - sent as first data byte */
skb2->nh.raw[1]=U8out[40];
/* legacy length - will only use 10 bits */
skb2->nh.raw[2]=((length>>8)&0x03);
skb2->nh.raw[3]=length;
/* ident sent as two data bytes */
skb2->nh.raw[4]=U8out[41];
skb2->nh.raw[5]=U8out[42];
/* useless frag bytes */
skb2->nh.raw[6]=0;
skb2->nh.raw[7]=0;
/* ttl set to 1 because we are directly connected */
skb2->nh.raw[8]=1;
/* UDP */
skb2->nh.raw[9]=0x11;
/* checksum set to zero here and computed below */
skb2->nh.raw[10]=0;
skb2->nh.raw[11]=0;
/* useless 0.0.0.1 IP addresses */
skb2->nh.raw[12]=0; skb2->nh.raw[13]=0; skb2->nh.raw[14]=0;
skb2->nh.raw[15]=1;
if(global){
skb2->nh.raw[16]=0xFF; skb2->nh.raw[17]=0xFF; skb2->nh.raw[18]=0xFF;
skb2->nh.raw[19]=0xFF;
}
else{
skb2->nh.raw[16]=0; skb2->nh.raw[17]=0; skb2->nh.raw[18]=0;
skb2->nh.raw[19]=1;
}
checksum = Checksum_of(skb2->nh.raw,20,0);
skb2->nh.raw[10]=checksum;
skb2->nh.raw[11]=(checksum>>8);
/* fix up a UDP header */
skb2->nh.raw[20]=(unsigned char)(LAN_PORT>>8);
skb2->nh.raw[21]=(unsigned char)LAN_PORT;
skb2->nh.raw[22]=(unsigned char)(LAN_PORT>>8);
skb2->nh.raw[23]=(unsigned char)LAN_PORT;
/* length does not include the tos or 2-byte ident removed above */
udp_len=length-20;
// printk("udp_len=%d\n",udp_len);
skb2->nh.raw[24]=(udp_len>>8);
skb2->nh.raw[25]=udp_len;
/* skip over tos and ident stealth bytes */
p = &U8out[43];
for(i=0; i<(udp_len-8); i++){
byte_counts[*p]++;
skb2->nh.raw[28+i]=*p++;
}
/* UDP checksum with pseudo header */
skb2->nh.raw[26]=0;
skb2->nh.raw[27]=0;
/* this could be faster with a sum pre-computed */
if(global){
ph=pseudo_hdrB;
//printk("broadcast\n");
}
else{
ph=pseudo_hdrA;
//printk("non-broadcast\n");
}
ph[10]=udp_len>>8;
ph[11]=udp_len;
checksum = Checksum_of(&(skb2->nh.raw[20]),udp_len,ph);
skb2->nh.raw[26]=checksum;
skb2->nh.raw[27]=(checksum>>8);
//printk("Deliver to local console\n");
//printk("src_addr=%016.llX\n",src_addr);
//printk("dst_addr=%016.llX\n",dst_addr);
if((src_addr==mac0) && (dst_addr==mac1) && (state1 >= LOCAL_STATE)){
//printk("Bridge mac0 to mac1\n");
skb2->dev = dev1;
dev_queue_xmit(skb2);
goto done;
}
else if((src_addr==mac1) && (dst_addr==mac0) && (state0 >= LOCAL_STATE)){
//printk("Bridge mac1 to mac0\n");
skb2->dev = dev0;
dev_queue_xmit(skb2);
goto done;
}
//printk("global=%d\n",global);
if((src_addr==mac0)&&(global)){
if(state1 >= LOCAL_STATE){
skb2->dev = dev1;
dev_queue_xmit(skb2);
//printk("queued on dev1\n");
goto done;
}
}
if((src_addr==mac1)&&(global)){
if(state0 >= LOCAL_STATE){
skb2->dev = dev0;
dev_queue_xmit(skb2);
//printk("queued on dev0\n");
goto done;
}
}
/* toss the Uni.X packet */
kfree_skb(skb2);
//printk("RAWE: ALERT why are we here...restart?\n");
return 0;
done:
//printk("done\n");
return 0;
skip:
kfree_skb(skb);
return 0;
}
_______________________________________________
governance mailing list
governance at lists.cpsr.org
https://ssl.cpsr.org/mailman/listinfo/governance
More information about the Governance
mailing list