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

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