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

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