root/net/802/tr.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tr_header
  2. tr_rebuild_header
  3. tr_type_trans
  4. tr_source_route
  5. tr_add_rif_info
  6. rif_check_expire
  7. rif_get_info
  8. rif_init

   1 #include <asm/segment.h>
   2 #include <asm/system.h>
   3 #include <linux/types.h>
   4 #include <linux/kernel.h>
   5 #include <linux/sched.h>
   6 #include <linux/string.h>
   7 #include <linux/mm.h>
   8 #include <linux/socket.h>
   9 #include <linux/in.h>
  10 #include <linux/inet.h>
  11 #include <linux/netdevice.h>
  12 #include <linux/trdevice.h>
  13 #include <linux/skbuff.h>
  14 #include <linux/errno.h>
  15 #include <linux/string.h>
  16 #include <linux/timer.h>
  17 #include <linux/net.h>
  18 #include <net/arp.h>
  19 
  20 static void tr_source_route(struct trh_hdr *trh,struct device *dev);
  21 static void tr_add_rif_info(struct trh_hdr *trh);
  22 static void rif_check_expire(unsigned long dummy);
  23 
  24 typedef struct rif_cache_s *rif_cache;
  25 
  26 struct rif_cache_s {    
  27          unsigned char addr[TR_ALEN];
  28          unsigned short rcf;
  29          unsigned short rseg[8];
  30          rif_cache next;
  31          unsigned long last_used;
  32 };
  33 
  34 #define RIF_TABLE_SIZE 16
  35 rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, };
  36 
  37 #define RIF_TIMEOUT 60*10*HZ
  38 #define RIF_CHECK_INTERVAL 60*HZ
  39 static struct timer_list rif_timer={ NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire };
  40 
  41 int tr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
  42               void *daddr, void *saddr, unsigned len) 
  43 {
  44 
  45         struct trh_hdr *trh=(struct trh_hdr *)skb_push(skb,dev->hard_header_len);
  46         struct trllc *trllc=(struct trllc *)(trh+1);
  47 
  48         trh->ac=AC;
  49         trh->fc=LLC_FRAME;
  50 
  51         if(saddr)
  52                 memcpy(trh->saddr,saddr,dev->addr_len);
  53         else
  54                 memset(trh->saddr,0,dev->addr_len); /* Adapter fills in address */
  55 
  56         trllc->dsap=trllc->ssap=EXTENDED_SAP;
  57         trllc->llc=UI_CMD;
  58         
  59         trllc->protid[0]=trllc->protid[1]=trllc->protid[2]=0x00;
  60         trllc->ethertype=htons(type);
  61 
  62         if(daddr) {
  63                 memcpy(trh->daddr,daddr,dev->addr_len);
  64                 tr_source_route(trh,dev);
  65                 return(dev->hard_header_len);
  66         }
  67         return -dev->hard_header_len;
  68 
  69 }
  70         
  71 int tr_rebuild_header(void *buff, struct device *dev, unsigned long dest,
     /* [previous][next][first][last][top][bottom][index][help] */
  72                                                          struct sk_buff *skb) {
  73 
  74         struct trh_hdr *trh=(struct trh_hdr *)buff;
  75         struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr));
  76 
  77         if(trllc->ethertype != htons(ETH_P_IP)) {
  78                 printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(      trllc->ethertype));
  79                 return 0;
  80         }
  81 
  82         if(arp_find(trh->daddr, dest, dev, dev->pa_addr, skb)) {
  83                         return 1;
  84         }
  85         else {  
  86                 tr_source_route(trh,dev); 
  87                 return 0;
  88         }
  89 }
  90         
  91 unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) {
     /* [previous][next][first][last][top][bottom][index][help] */
  92 
  93         struct trh_hdr *trh=(struct trh_hdr *)skb->data;
  94         struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
  95         
  96         skb->mac.raw = skb->data;
  97         
  98         skb_pull(skb,dev->hard_header_len);
  99         
 100         if(trh->saddr[0] & TR_RII)
 101                 tr_add_rif_info(trh);
 102 
 103         if(*trh->daddr & 1) 
 104         {
 105                 if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN))  
 106                         skb->pkt_type=PACKET_BROADCAST;
 107                 else
 108                         skb->pkt_type=PACKET_MULTICAST;
 109         }
 110 
 111         else if(dev->flags & IFF_PROMISC) 
 112         {
 113                 if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN))
 114                         skb->pkt_type=PACKET_OTHERHOST;
 115         }
 116 
 117         return trllc->ethertype;
 118 }
 119 
 120 /* We try to do source routing... */
 121 
 122 static void tr_source_route(struct trh_hdr *trh,struct device *dev) {
     /* [previous][next][first][last][top][bottom][index][help] */
 123 
 124         int i;
 125         unsigned int hash;
 126         rif_cache entry;
 127 
 128         /* Broadcasts are single route as stated in RFC 1042 */
 129         if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) {
 130                 trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
 131                                | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 132                 trh->saddr[0]|=TR_RII;
 133         }
 134         else {
 135                 for(i=0,hash=0;i<TR_ALEN;hash+=trh->daddr[i++]);
 136                 hash&=RIF_TABLE_SIZE-1;
 137                 for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next);
 138 
 139                 if(entry) {
 140 #if 0
 141 printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
 142                   trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
 143 #endif
 144                         if((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) {
 145                                 trh->rcf=entry->rcf;
 146                                 memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
 147                                 trh->rcf^=htons(TR_RCF_DIR_BIT);        
 148                                 trh->rcf&=htons(0x1fff);        /* Issam Chehab <ichehab@madge1.demon.co.uk> */
 149 
 150                                 trh->saddr[0]|=TR_RII;
 151                                 entry->last_used=jiffies;
 152                         }
 153                 }
 154                 else {
 155                         trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
 156                                        | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 157                         trh->saddr[0]|=TR_RII;
 158                 }
 159         }
 160                         
 161 }
 162 
 163 static void tr_add_rif_info(struct trh_hdr *trh) {
     /* [previous][next][first][last][top][bottom][index][help] */
 164 
 165         int i;
 166         unsigned int hash;
 167         rif_cache entry;
 168 
 169 
 170         trh->saddr[0]&=0x7f;
 171         for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
 172         hash&=RIF_TABLE_SIZE-1;
 173 #if 0
 174         printk("hash: %d\n",hash);
 175 #endif
 176         for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
 177 
 178         if(entry==NULL) {
 179 #if 0
 180 printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
 181                 trh->saddr[0],trh->saddr[1],trh->saddr[2],
 182                 trh->saddr[3],trh->saddr[4],trh->saddr[5],
 183                 trh->rcf);
 184 #endif
 185                 entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
 186                 if(!entry) {
 187                         printk("tr.c: Couldn't malloc rif cache entry !\n");
 188                         return;
 189                 }
 190                 entry->rcf=trh->rcf;
 191                 memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
 192                 memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
 193                 entry->next=rif_table[hash];
 194                 entry->last_used=jiffies;
 195                 rif_table[hash]=entry;
 196         }
 197 /* Y. Tahara added */
 198    else {                                       
 199                 if ( entry->rcf != trh->rcf ) {               
 200                                 if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) {
 201 #if 0
 202 printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
 203                 trh->saddr[0],trh->saddr[1],trh->saddr[2],
 204                 trh->saddr[3],trh->saddr[4],trh->saddr[5],
 205                 trh->rcf);
 206 #endif
 207                        entry->rcf = trh->rcf;                  
 208                             memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
 209                          entry->last_used=jiffies;               
 210                                 }                                          
 211                 }                                             
 212         }
 213 
 214 }
 215 
 216 static void rif_check_expire(unsigned long dummy) {
     /* [previous][next][first][last][top][bottom][index][help] */
 217 
 218         int i;
 219         unsigned long now=jiffies,flags;
 220 
 221         save_flags(flags);
 222         cli();
 223 
 224         for(i=0; i < RIF_TABLE_SIZE;i++) {
 225 
 226         rif_cache entry, *pentry=rif_table+i;   
 227 
 228                 while((entry=*pentry)) 
 229                         if((now-entry->last_used) > RIF_TIMEOUT) {
 230                                 *pentry=entry->next;
 231                                 kfree_s(entry,sizeof(struct rif_cache_s));
 232                         }
 233                         else
 234                                 pentry=&entry->next;    
 235         }
 236         restore_flags(flags);
 237 
 238         del_timer(&rif_timer);
 239         rif_timer.expires=jiffies+RIF_CHECK_INTERVAL;
 240         add_timer(&rif_timer);
 241 
 242 }
 243 
 244 int rif_get_info(char *buffer,char **start, off_t offset, int length) {
     /* [previous][next][first][last][top][bottom][index][help] */
 245 
 246    int len=0;
 247    off_t begin=0;
 248    off_t pos=0;
 249    int size,i;
 250 
 251    rif_cache entry;
 252 
 253         size=sprintf(buffer,
 254 "   TR address     rcf             routing segments             TTL\n\n");
 255    pos+=size;
 256    len+=size;
 257 
 258         for(i=0;i < RIF_TABLE_SIZE;i++) {
 259                 for(entry=rif_table[i];entry;entry=entry->next) {
 260                         size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n",
 261                                                                 entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
 262                                                                 entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3],
 263                                                                 entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used); 
 264                         len+=size;
 265                         pos=begin+len;
 266 
 267                         if(pos<offset) {
 268                                 len=0;
 269                                 begin=pos;
 270                         }
 271                         if(pos>offset+length)
 272                                 break;
 273         }
 274                 if(pos>offset+length)
 275                         break;
 276         }
 277 
 278    *start=buffer+(offset-begin); /* Start of wanted data */
 279    len-=(offset-begin);    /* Start slop */
 280    if(len>length)
 281       len=length;    /* Ending slop */
 282    return len;
 283 }
 284 
 285 void rif_init(struct net_proto *unused) {
     /* [previous][next][first][last][top][bottom][index][help] */
 286 
 287         add_timer(&rif_timer);
 288 
 289 }
 290 

/* [previous][next][first][last][top][bottom][index][help] */