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

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