root/net/ipv4/ipmr.c

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

DEFINITIONS

This source file includes following definitions.
  1. vif_delete
  2. ipmr_vifi_find
  3. ipmr_cache_delete
  4. ipmr_cache_timer
  5. ipmr_cache_insert
  6. ipmr_cache_find
  7. ipmr_cache_alloc
  8. ipmr_cache_resolve
  9. ipmr_cache_report
  10. ipmr_cache_unresolved
  11. ipmr_mfc_modify
  12. ip_mroute_setsockopt
  13. ip_mroute_getsockopt
  14. ipmr_ioctl
  15. mroute_close
  16. ipmr_device_event
  17. ipmr_queue_xmit
  18. ipmr_forward
  19. ipmr_vif_info
  20. ipmr_mfc_info
  21. ip_mr_init

   1 /*
   2  *      IP multicast routing support for mrouted 3.6
   3  *
   4  *              (c) 1995 Alan Cox, <alan@cymru.net>
   5  *        Linux Consultancy and Custom Driver Development
   6  *
   7  *      This program is free software; you can redistribute it and/or
   8  *      modify it under the terms of the GNU General Public License
   9  *      as published by the Free Software Foundation; either version
  10  *      2 of the License, or (at your option) any later version.
  11  *
  12  *
  13  *      Fixes:
  14  *      Michael Chastain        :       Incorrect size of copying.
  15  *      Alan Cox                :       Added the cache manager code
  16  *
  17  *      Status:
  18  *              Cache manager under test. Forwarding in vague test mode
  19  *      Todo:
  20  *              Flow control
  21  *              Finish Tunnels
  22  *              Debug cache ttl handling properly
  23  *              Resolve IFF_ALLMULTI for rest of cards
  24  */
  25 
  26 #include <asm/system.h>
  27 #include <asm/segment.h>
  28 #include <linux/types.h>
  29 #include <linux/sched.h>
  30 #include <linux/errno.h>
  31 #include <linux/timer.h>
  32 #include <linux/mm.h>
  33 #include <linux/kernel.h>
  34 #include <linux/fcntl.h>
  35 #include <linux/stat.h>
  36 #include <linux/socket.h>
  37 #include <linux/in.h>
  38 #include <linux/inet.h>
  39 #include <linux/netdevice.h>
  40 #include <linux/proc_fs.h>
  41 #include <linux/mroute.h>
  42 #include <net/ip.h>
  43 #include <net/protocol.h>
  44 #include <linux/skbuff.h>
  45 #include <net/sock.h>
  46 #include <net/icmp.h>
  47 #include <net/udp.h>
  48 #include <linux/notifier.h>
  49 #include <net/checksum.h>
  50 
  51 /*
  52  *      Multicast router conrol variables
  53  */
  54 
  55 static struct vif_device vif_table[MAXVIFS];            /* Devices              */
  56 static unsigned long vifc_map;                          /* Active device map    */
  57 int mroute_do_pim = 0;                                  /* Set in PIM assert    */
  58 static struct mfc_cache *mfc_cache_array[MFC_LINES];    /* Forwarding cache     */
  59 static struct mfc_cache *cache_resolve_queue;           /* Unresolved cache     */
  60 int cache_resolve_queue_len = 0;                        /* Size of unresolved   */
  61 
  62 /*
  63  *      Delete a VIF entry
  64  */
  65  
  66 static void vif_delete(struct vif_device *v)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68         if(!(v->flags&VIFF_TUNNEL))
  69         {
  70                 v->dev->flags&=~IFF_ALLMULTI;
  71                 dev_mc_upload(v->dev);
  72         }
  73         v->dev=NULL;
  74 }
  75 
  76 /*
  77  *      Find a vif
  78  */
  79  
  80 static int ipmr_vifi_find(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         struct vif_device *v=&vif_table[0];
  83         int ct;
  84         for(ct=0;ct<MAXVIFS;ct++,v++)
  85         {
  86                 if(v->dev==dev)
  87                         return ct;
  88         }
  89         return -1;
  90 }
  91 
  92 /*
  93  *      Delete a multicast route cache entry
  94  */
  95  
  96 static void ipmr_cache_delete(struct mfc_cache *cache)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         struct sk_buff *skb;
  99         int line;
 100         struct mfc_cache **cp;
 101         
 102         /*
 103          *      Find the right cache line
 104          */
 105 
 106         if(cache->mfc_flags&MFC_QUEUED)
 107         {       
 108                 cp=&cache_resolve_queue;
 109                 del_timer(&cache->mfc_timer);
 110         }       
 111         else
 112         {
 113                 line=MFC_HASH(cache->mfc_mcastgrp,cache->mfc_origin);
 114                 cp=&(mfc_cache_array[line]);
 115         }
 116         
 117         /*
 118          *      Unlink the buffer
 119          */
 120         
 121         while(*cp!=NULL)
 122         {
 123                 if(*cp==cache)
 124                 {
 125                         *cp=cache->next;
 126                         break;
 127                 }
 128                 cp=&((*cp)->next);
 129         }
 130         
 131         /*
 132          *      Free the buffer. If it is a pending resolution
 133          *      clean up the other resources.
 134          */
 135 
 136         if(cache->mfc_flags&MFC_QUEUED)
 137         {
 138                 cache_resolve_queue_len--;
 139                 while((skb=skb_dequeue(&cache->mfc_unresolved)))
 140                         kfree_skb(skb, FREE_WRITE);
 141         }
 142         kfree_s(cache,sizeof(cache));
 143 }
 144 
 145 /*
 146  *      Cache expiry timer
 147  */     
 148  
 149 static void ipmr_cache_timer(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         struct mfc_cache *cache=(struct mfc_cache *)data;
 152         ipmr_cache_delete(cache);
 153 }
 154 
 155 /*
 156  *      Insert a multicast cache entry
 157  */
 158 
 159 static void ipmr_cache_insert(struct mfc_cache *c)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int line=MFC_HASH(c->mfc_mcastgrp,c->mfc_origin);
 162         c->next=mfc_cache_array[line];
 163         mfc_cache_array[line]=c;
 164 }
 165  
 166 /*
 167  *      Find a multicast cache entry
 168  */
 169  
 170 struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int line=MFC_HASH(mcastgrp,origin);
 173         struct mfc_cache *cache;
 174         cache=mfc_cache_array[line];
 175         while(cache!=NULL)
 176         {
 177                 if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
 178                         return cache;
 179                 cache=cache->next;
 180         }
 181         cache=cache_resolve_queue;
 182         while(cache!=NULL)
 183         {
 184                 if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
 185                         return cache;
 186                 cache=cache->next;
 187         }
 188         return NULL;
 189 }
 190 
 191 /*
 192  *      Allocate a multicast cache entry
 193  */
 194  
 195 static struct mfc_cache *ipmr_cache_alloc(int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         struct mfc_cache *c=(struct mfc_cache *)kmalloc(sizeof(struct mfc_cache), priority);
 198         if(c==NULL)
 199                 return NULL;
 200         c->mfc_queuelen=0;
 201         skb_queue_head_init(&c->mfc_unresolved);
 202         init_timer(&c->mfc_timer);
 203         c->mfc_timer.data=(long)c;
 204         c->mfc_timer.function=ipmr_cache_timer;
 205         return c;
 206 }
 207  
 208 /*
 209  *      A cache entry has gone into a resolved state from queued
 210  */
 211  
 212 static void ipmr_cache_resolve(struct mfc_cache *cache)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         struct mfc_cache **p;
 215         struct sk_buff *skb;
 216         /*
 217          *      Kill the queue entry timer.
 218          */
 219         del_timer(&cache->mfc_timer);
 220         cache->mfc_flags&=~MFC_QUEUED;
 221         /*
 222          *      Remove from the resolve queue
 223          */
 224         p=&cache_resolve_queue;
 225         while((*p)!=NULL)
 226         {
 227                 if((*p)==cache)
 228                 {
 229                         *p=cache->next;
 230                         break;
 231                 }
 232                 p=&((*p)->next);
 233         }
 234         cache_resolve_queue_len--;
 235         sti();
 236         /*
 237          *      Insert into the main cache
 238          */
 239         ipmr_cache_insert(cache);
 240         /*
 241          *      Play the pending entries through our router
 242          */
 243         while((skb=skb_dequeue(&cache->mfc_unresolved)))
 244                 ipmr_forward(skb, skb->protocol);
 245 }
 246 
 247 /*
 248  *      Bounce a cache query up to mrouted. We could use netlink for this but mrouted
 249  *      expects the following bizarre scheme..
 250  */
 251  
 252 static void ipmr_cache_report(struct sk_buff *pkt)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254         struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
 255         int ihl=pkt->ip_hdr->ihl<<2;
 256         struct igmphdr *igmp;
 257         if(!skb)
 258                 return;
 259                 
 260         skb->free=1;
 261         
 262         /*
 263          *      Copy the IP header
 264          */
 265 
 266         skb->ip_hdr=(struct iphdr *)skb_put(skb,ihl);
 267         skb->h.iph=skb->ip_hdr;
 268         memcpy(skb->data,pkt->data,ihl);
 269         skb->ip_hdr->protocol = 0;                      /* Flag to the kernel this is a route add */
 270         
 271         /*
 272          *      Add our header
 273          */
 274         
 275         igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
 276         igmp->type      =       IGMPMSG_NOCACHE;                /* non IGMP dummy message */
 277         igmp->code      =       0;
 278         skb->ip_hdr->tot_len=htons(skb->len);                   /* Fix the length */
 279         
 280         /*
 281          *      Deliver to mrouted
 282          */
 283         if(sock_queue_rcv_skb(mroute_socket,skb)<0)
 284         {
 285                 skb->sk=NULL;
 286                 kfree_skb(skb, FREE_READ);
 287         }
 288 }
 289                 
 290  
 291 /*
 292  *      Queue a packet for resolution
 293  */
 294  
 295 static void ipmr_cache_unresolved(struct mfc_cache *cache, vifi_t vifi, struct sk_buff *skb, int is_frag)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         if(cache==NULL)
 298         {       
 299                 /*
 300                  *      Create a new entry if allowable
 301                  */
 302                 if(cache_resolve_queue_len>=10 || (cache=ipmr_cache_alloc(GFP_ATOMIC))==NULL)
 303                 {
 304                         kfree_skb(skb, FREE_WRITE);
 305                         return;
 306                 }
 307                 /*
 308                  *      Fill in the new cache entry
 309                  */
 310                 cache->mfc_parent=vifi;
 311                 cache->mfc_origin=skb->ip_hdr->saddr;
 312                 cache->mfc_mcastgrp=skb->ip_hdr->daddr;
 313                 cache->mfc_flags=MFC_QUEUED;
 314                 /*
 315                  *      Link to the unresolved list
 316                  */
 317                 cache->next=cache_resolve_queue;
 318                 cache_resolve_queue=cache;
 319                 cache_resolve_queue_len++;
 320                 /*
 321                  *      Fire off the expiry timer
 322                  */
 323                 cache->mfc_timer.expires=jiffies+10*HZ;
 324                 add_timer(&cache->mfc_timer);
 325                 /*
 326                  *      Reflect first query at mrouted.
 327                  */
 328                 if(mroute_socket)
 329                         ipmr_cache_report(skb);
 330         }
 331         /*
 332          *      See if we can append the packet
 333          */
 334         if(cache->mfc_queuelen>3)
 335         {
 336                 kfree_skb(skb, FREE_WRITE);
 337                 return;
 338         }
 339         /*
 340          *      Add to our 'pending' list. Cache the is_frag data
 341          *      in skb->protocol now it is spare.
 342          */
 343         cache->mfc_queuelen++;
 344         skb->protocol=is_frag;
 345         skb_queue_tail(&cache->mfc_unresolved,skb);
 346 }
 347 
 348 /*
 349  *      MFC cache manipulation by user space mroute daemon
 350  */
 351  
 352 int ipmr_mfc_modify(int action, struct mfcctl *mfc)
     /* [previous][next][first][last][top][bottom][index][help] */
 353 {
 354         struct mfc_cache *cache;
 355         if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr))
 356                 return -EINVAL;
 357         /*
 358          *      Find the cache line
 359          */
 360         
 361         cli();
 362 
 363         cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
 364         
 365         /*
 366          *      Delete an entry
 367          */
 368         if(action==MRT_DEL_MFC)
 369         {
 370                 if(cache)
 371                 {
 372                         ipmr_cache_delete(cache);
 373                         sti();
 374                         return 0;
 375                 }
 376                 sti();
 377                 return -ENOENT;
 378         }
 379         if(cache)
 380         {
 381                 /*
 382                  *      Update the cache, see if it frees a pending queue
 383                  */
 384 
 385                 cache->mfc_flags|=MFC_RESOLVED;
 386                 memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
 387                  
 388                 /*
 389                  *      Check to see if we resolved a queued list. If so we
 390                  *      need to send on the frames and tidy up.
 391                  */
 392                  
 393                 if(cache->mfc_flags&MFC_QUEUED)
 394                         ipmr_cache_resolve(cache);      /* Unhook & send the frames */
 395                 sti();
 396                 return 0;
 397         }
 398         /*
 399          *      Unsolicited update - thats ok add anyway.
 400          */
 401          
 402         
 403         cache=ipmr_cache_alloc(GFP_ATOMIC);
 404         if(cache==NULL)
 405         {
 406                 sti();
 407                 return -ENOMEM;
 408         }
 409         cache->mfc_flags=MFC_RESOLVED;
 410         cache->mfc_origin=mfc->mfcc_origin.s_addr;
 411         cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
 412         cache->mfc_parent=mfc->mfcc_parent;
 413         memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
 414         ipmr_cache_insert(cache);
 415         sti();
 416         return 0;
 417 }
 418  
 419 /*
 420  *      Socket options and virtual interface manipulation. The whole
 421  *      virtual interface system is a complete heap, but unfortunately
 422  *      thats how BSD mrouted happens to think. Maybe one day with a proper
 423  *      MOSPF/PIM router set up we can clean this up.
 424  */
 425  
 426 int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 427 {
 428         int err;
 429         struct vifctl vif;
 430         struct mfcctl mfc;
 431         
 432         if(optname!=MRT_INIT)
 433         {
 434                 if(sk!=mroute_socket)
 435                         return -EACCES;
 436         }
 437         
 438         switch(optname)
 439         {
 440                 case MRT_INIT:
 441                         if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
 442                                 return -EOPNOTSUPP;
 443                         if(optlen!=sizeof(int))
 444                                 return -ENOPROTOOPT;
 445                         if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
 446                                 return err;
 447                         if(get_user((int *)optval)!=1)
 448                                 return -ENOPROTOOPT;
 449                         if(mroute_socket)
 450                                 return -EADDRINUSE;
 451                         mroute_socket=sk;
 452                         /* Initialise state */
 453                         return 0;
 454                 case MRT_DONE:
 455                         mroute_close(sk);
 456                         mroute_socket=NULL;
 457                         return 0;
 458                 case MRT_ADD_VIF:
 459                 case MRT_DEL_VIF:
 460                         if(optlen!=sizeof(vif))
 461                                 return -EINVAL;
 462                         if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
 463                                 return err;
 464                         memcpy_fromfs(&vif,optval,sizeof(vif));
 465                         if(vif.vifc_vifi > MAXVIFS)
 466                                 return -ENFILE;
 467                         if(optname==MRT_ADD_VIF)
 468                         {
 469                                 struct vif_device *v=&vif_table[vif.vifc_vifi];
 470                                 struct device *dev;
 471                                 /* Empty vif ? */
 472                                 if(vifc_map&(1<<vif.vifc_vifi))
 473                                         return -EADDRINUSE;
 474                                 /* Find the interface */
 475                                 dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
 476                                 if(!dev)
 477                                         return -EADDRNOTAVAIL;
 478                                 /* Must be tunnelled or multicastable */
 479                                 if(vif.vifc_flags&VIFF_TUNNEL)
 480                                 {
 481                                         if(vif.vifc_flags&VIFF_SRCRT)
 482                                                 return -EOPNOTSUPP;
 483                                         /* IPIP will do all the work */
 484                                 }
 485                                 else
 486                                 {
 487                                         if(dev->flags&IFF_MULTICAST)
 488                                         {
 489                                                 /* Most ethernet cards dont know
 490                                                    how to do this yet.. */
 491                                                 dev->flags|=IFF_ALLMULTI;
 492                                                 dev_mc_upload(dev);
 493                                         }
 494                                         else
 495                                         {
 496                                                 /* We are stuck.. */
 497                                                 return -EOPNOTSUPP;
 498                                         }
 499                                 }
 500                                 /*
 501                                  *      Fill in the VIF structures
 502                                  */
 503                                 cli();
 504                                 v->rate_limit=vif.vifc_rate_limit;
 505                                 v->local=vif.vifc_lcl_addr.s_addr;
 506                                 v->remote=vif.vifc_rmt_addr.s_addr;
 507                                 v->flags=vif.vifc_flags;
 508                                 v->threshold=vif.vifc_threshold;
 509                                 v->dev=dev;
 510                                 v->bytes_in = 0;
 511                                 v->bytes_out = 0;
 512                                 v->pkt_in = 0;
 513                                 v->pkt_out = 0;
 514                                 vifc_map|=(1<<vif.vifc_vifi);
 515                                 sti();
 516                                 return 0;
 517                         }
 518                         else
 519                         /*
 520                          *      VIF deletion
 521                          */
 522                         {
 523                                 struct vif_device *v=&vif_table[vif.vifc_vifi];
 524                                 if(vifc_map&(1<<vif.vifc_vifi))
 525                                 {
 526                                         vif_delete(v);
 527                                         vifc_map&=~(1<<vif.vifc_vifi);
 528                                         return 0;                                       
 529                                 }
 530                                 else
 531                                         return -EADDRNOTAVAIL;
 532                         }
 533                 /*
 534                  *      Manipulate the forwarding caches. These live
 535                  *      in a sort of kernel/user symbiosis.
 536                  */
 537                 case MRT_ADD_MFC:
 538                 case MRT_DEL_MFC:
 539                         err=verify_area(VERIFY_READ, optval, sizeof(mfc));
 540                         if(err)
 541                                 return err;
 542                         memcpy_fromfs(&mfc,optval, sizeof(mfc));
 543                         return ipmr_mfc_modify(optname, &mfc);
 544                 /*
 545                  *      Control PIM assert.
 546                  */
 547                 case MRT_ASSERT:
 548                         if(optlen!=sizeof(int))
 549                                 return -EINVAL;
 550                         if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
 551                                 return err;
 552                         mroute_do_pim= (optval)?1:0;
 553                         return 0;
 554                 /*
 555                  *      Spurious command, or MRT_VERSION which you cannot
 556                  *      set.
 557                  */
 558                 default:
 559                         return -EOPNOTSUPP;
 560         }
 561 }
 562 
 563 /*
 564  *      Getsock opt support for the multicast routing system.
 565  */
 566  
 567 int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 568 {
 569         int olr;
 570         int err;
 571 
 572         if(sk!=mroute_socket)
 573                 return -EACCES;
 574         if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
 575                 return -EOPNOTSUPP;
 576         
 577         olr=get_user(optlen);
 578         if(olr!=sizeof(int))
 579                 return -EINVAL;
 580         err=verify_area(VERIFY_WRITE, optval,sizeof(int));
 581         if(err)
 582                 return err;
 583         put_user(sizeof(int),optlen);
 584         if(optname==MRT_VERSION)
 585                 put_user(0x0305,(int *)optval);
 586         else
 587                 put_user(mroute_do_pim,(int *)optval);
 588         return 0;
 589 }
 590 
 591 /*
 592  *      The IP multicast ioctl support routines.
 593  */
 594  
 595 int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 596 {
 597         int err;
 598         struct sioc_sg_req sr;
 599         struct sioc_vif_req vr;
 600         struct vif_device *vif;
 601         
 602         switch(cmd)
 603         {
 604                 case SIOCGETVIFCNT:
 605                         err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
 606                         if(err)
 607                                 return err;
 608                         memcpy_fromfs(&vr,(void *)arg,sizeof(vr));
 609                         if(vr.vifi>=MAXVIFS)
 610                                 return -EINVAL;
 611                         vif=&vif_table[vr.vifi];
 612                         if(vifc_map&(1<<vr.vifi))
 613                         {
 614                                 vr.icount=vif->pkt_in;
 615                                 vr.ocount=vif->pkt_out;
 616                                 vr.ibytes=vif->bytes_in;
 617                                 vr.obytes=vif->bytes_out;
 618                                 memcpy_tofs((void *)arg,&vr,sizeof(vr));
 619                                 return 0;
 620                         }
 621                         return -EADDRNOTAVAIL;
 622                 case SIOCGETSGCNT:
 623                         err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
 624                         if(err)
 625                                 return err;
 626                         memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
 627                         memcpy_tofs((void *)arg,&sr,sizeof(sr));
 628                         return 0;
 629                 default:
 630                         return -EINVAL;
 631         }
 632 }
 633 
 634 /*
 635  *      Close the multicast socket, and clear the vif tables etc
 636  */
 637  
 638 void mroute_close(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 639 {
 640         int i;
 641         struct vif_device *v=&vif_table[0];
 642                 
 643         /*
 644          *      Shut down all active vif entries
 645          */
 646          
 647         for(i=0;i<MAXVIFS;i++)
 648         {
 649                 if(vifc_map&(1<<i))
 650                 {
 651                         if(!(v->flags&VIFF_TUNNEL))
 652                         {
 653                                 v->dev->flags&=~IFF_ALLMULTI;
 654                                 dev_mc_upload(v->dev);
 655                         }
 656                 }
 657                 v++;
 658         }               
 659         vifc_map=0;     
 660         /*
 661          *      Wipe the cache
 662          */
 663         for(i=0;i<MFC_LINES;i++)
 664         {
 665                 while(mfc_cache_array[i]!=NULL)
 666                         ipmr_cache_delete(mfc_cache_array[i]);
 667         }       
 668         /* The timer will clear any 'pending' stuff */
 669 }
 670 
 671 static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673         struct vif_device *v;
 674         int ct;
 675         if(event!=NETDEV_DOWN)
 676                 return NOTIFY_DONE;
 677         v=&vif_table[0];
 678         for(ct=0;ct<MAXVIFS;ct++)
 679         {
 680                 if((vifc_map&(1<<ct)) && v->dev==ptr)
 681                 {
 682                         vif_delete(v);
 683                         vifc_map&=~(1<<ct);
 684                 }
 685                 v++;
 686         }
 687         return NOTIFY_DONE;
 688 }
 689 
 690 
 691 static struct notifier_block ip_mr_notifier={
 692         ipmr_device_event,
 693         NULL,
 694         0
 695 };
 696 
 697 /*
 698  *      Processing handlers for ipmr_forward
 699  */
 700 
 701 static void ipmr_queue_xmit(struct sk_buff *skb, struct vif_device *vif, struct device *in_dev, int frag)
     /* [previous][next][first][last][top][bottom][index][help] */
 702 {
 703         int tunnel=0;
 704         __u32 raddr=skb->raddr;
 705         if(vif->flags&VIFF_TUNNEL)
 706         {
 707                 tunnel=16;
 708                 raddr=vif->remote;
 709         }
 710         vif->pkt_out++;
 711         vif->bytes_out+=skb->len;
 712         skb->dev=vif->dev;
 713         skb->raddr=skb->h.iph->daddr;
 714         if(ip_forward(skb, in_dev, frag|8|tunnel, raddr)==-1)
 715                 kfree_skb(skb, FREE_WRITE);
 716 }
 717 
 718 /*
 719  *      Multicast packets for forwarding arrive here
 720  */
 721 
 722 void ipmr_forward(struct sk_buff *skb, int is_frag)
     /* [previous][next][first][last][top][bottom][index][help] */
 723 {
 724         struct mfc_cache *cache;
 725         struct sk_buff *skb2;
 726         int psend = -1;
 727         int vif=ipmr_vifi_find(skb->dev);
 728         if(vif==-1)
 729         {
 730                 kfree_skb(skb, FREE_WRITE);
 731                 return;
 732         }
 733         
 734         vif_table[vif].pkt_in++;
 735         vif_table[vif].bytes_in+=skb->len;
 736         
 737         cache=ipmr_cache_find(skb->ip_hdr->saddr,skb->ip_hdr->daddr);
 738         
 739         /*
 740          *      No usable cache entry
 741          */
 742          
 743         if(cache==NULL || (cache->mfc_flags&MFC_QUEUED))
 744                 ipmr_cache_unresolved(cache,vif,skb, is_frag);
 745         else
 746         {
 747                 /*
 748                  *      Forward the frame
 749                  */
 750                  int ct=0;
 751                  while(ct<MAXVIFS)
 752                  {
 753                         /*
 754                          *      0 means don't do it. Silly idea, 255 as don't do it would be cleaner!
 755                          */
 756                         if(skb->ip_hdr->ttl > cache->mfc_ttls[ct] && cache->mfc_ttls[ct]>0)
 757                         {
 758                                 if(psend!=-1)
 759                                 {
 760                                         skb2=skb_clone(skb, GFP_ATOMIC);
 761                                         if(skb2)
 762                                         {
 763                                                 skb2->free=1;
 764                                                 ipmr_queue_xmit(skb2, &vif_table[psend], skb->dev, is_frag);
 765                                         }
 766                                 }
 767                                 psend=ct;
 768                         }
 769                         ct++;
 770                 }
 771                 if(psend==-1)
 772                         kfree_skb(skb, FREE_WRITE);
 773                 else
 774                 {
 775                         ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
 776                 }
 777                 /*
 778                  *      Adjust the stats
 779                  */
 780         }
 781 }
 782 
 783 /*
 784  *      The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
 785  */
 786  
 787 int ipmr_vif_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789         struct vif_device *vif;
 790         int len=0;
 791         off_t pos=0;
 792         off_t begin=0;
 793         int size;
 794         int ct;
 795 
 796         len += sprintf(buffer,
 797                  "Interface  Bytes In  Pkts In  Bytes Out  Pkts Out  Flags Local    Remote\n");
 798         pos=len;
 799   
 800         for (ct=0;ct<MAXVIFS;ct++) 
 801         {
 802                 vif=&vif_table[ct];
 803                 if(!(vifc_map&(1<<ct)))
 804                         continue;
 805                 if(vif->dev==NULL)
 806                         continue;
 807                 size = sprintf(buffer+len, "%-10s %8ld  %7ld  %8ld   %7ld   %05X %08lX %08lX\n",
 808                         vif->dev->name,vif->bytes_in, vif->pkt_in, vif->bytes_out,vif->pkt_out,
 809                         vif->flags, vif->local, vif->remote);
 810                 len+=size;
 811                 pos+=size;
 812                 if(pos<offset)
 813                 {
 814                         len=0;
 815                         begin=pos;
 816                 }
 817                 if(pos>offset+length)
 818                         break;
 819         }
 820         
 821         *start=buffer+(offset-begin);
 822         len-=(offset-begin);
 823         if(len>length)
 824                 len=length;
 825         return len;
 826 }
 827 
 828 int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 829 {
 830         struct mfc_cache *mfc;
 831         int len=0;
 832         off_t pos=0;
 833         off_t begin=0;
 834         int size;
 835         int ct;
 836 
 837         len += sprintf(buffer,
 838                  "Group    Origin   SrcIface \n");
 839         pos=len;
 840   
 841         for (ct=0;ct<MFC_LINES;ct++) 
 842         {
 843                 cli();
 844                 mfc=mfc_cache_array[ct];
 845                 while(mfc!=NULL)
 846                 {
 847                         char *name="none";
 848                         char vifmap[MAXVIFS+1];
 849                         int n;
 850                         /*
 851                          *      Device name
 852                          */
 853                         if(vifc_map&(1<<mfc->mfc_parent))
 854                                 name=vif_table[mfc->mfc_parent].dev->name;
 855                         /*
 856                          *      Interface forwarding map
 857                          */
 858                         for(n=0;n<MAXVIFS;n++)
 859                                 if(vifc_map&(1<<n) && mfc->mfc_ttls[ct])
 860                                         vifmap[n]='X';
 861                                 else
 862                                         vifmap[n]='-';
 863                         vifmap[n]=0;
 864                         /*
 865                          *      Now print it out
 866                          */
 867                         size = sprintf(buffer+len, "%08lX %08lX %-8s %s\n",
 868                                 (unsigned long)mfc->mfc_mcastgrp,
 869                                 (unsigned long)mfc->mfc_origin,
 870                                 name,
 871                                 vifmap);
 872                         len+=size;
 873                         pos+=size;
 874                         if(pos<offset)
 875                         {
 876                                 len=0;
 877                                 begin=pos;
 878                         }
 879                         if(pos>offset+length)
 880                         {
 881                                 sti();
 882                                 goto done;
 883                         }
 884                         mfc=mfc->next;
 885                 }
 886                 sti();
 887         }
 888 done:
 889         *start=buffer+(offset-begin);
 890         len-=(offset-begin);
 891         if(len>length)
 892                 len=length;
 893         return len;
 894 }
 895 
 896 /*
 897  *      Setup for IP multicast routing
 898  */
 899  
 900 void ip_mr_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 901 {
 902         printk("Linux IP multicast router 0.04-might-work 8)\n");
 903         register_netdevice_notifier(&ip_mr_notifier);
 904         proc_net_register(&(struct proc_dir_entry) {
 905                 PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
 906                 S_IFREG | S_IRUGO, 1, 0, 0,
 907                 0, &proc_net_inode_operations,
 908                 ipmr_vif_info
 909         });
 910         proc_net_register(&(struct proc_dir_entry) {
 911                 PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
 912                 S_IFREG | S_IRUGO, 1, 0, 0,
 913                 0, &proc_net_inode_operations,
 914                 ipmr_mfc_info
 915         });
 916 }

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