[BACK]Return to mld6.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netinet6/mld6.c between version 1.35 and 1.37.2.4

version 1.35, 2006/11/20 04:26:22 version 1.37.2.4, 2007/10/23 20:17:22
Line 163  static struct mld_hdr * mld_allocbuf(str
Line 163  static struct mld_hdr * mld_allocbuf(str
 static void mld_sendpkt(struct in6_multi *, int, const struct in6_addr *);  static void mld_sendpkt(struct in6_multi *, int, const struct in6_addr *);
 static void mld_starttimer(struct in6_multi *);  static void mld_starttimer(struct in6_multi *);
 static void mld_stoptimer(struct in6_multi *);  static void mld_stoptimer(struct in6_multi *);
 static void mld_timeo(struct in6_multi *);  
 static u_long mld_timerresid(struct in6_multi *);  static u_long mld_timerresid(struct in6_multi *);
   
 void  void
Line 181  mld_init()
Line 180  mld_init()
         hbh_buf[3] = 0;          hbh_buf[3] = 0;
         hbh_buf[4] = IP6OPT_RTALERT;          hbh_buf[4] = IP6OPT_RTALERT;
         hbh_buf[5] = IP6OPT_RTALERT_LEN - 2;          hbh_buf[5] = IP6OPT_RTALERT_LEN - 2;
         bcopy((caddr_t)&rtalert_code, &hbh_buf[6], sizeof(u_int16_t));          bcopy((void *)&rtalert_code, &hbh_buf[6], sizeof(u_int16_t));
   
         ip6_opts.ip6po_hbh = hbh;          ip6_opts.ip6po_hbh = hbh;
         /* We will specify the hoplimit by a multicast option. */          /* We will specify the hoplimit by a multicast option. */
Line 189  mld_init()
Line 188  mld_init()
 }  }
   
 static void  static void
 mld_starttimer(in6m)  mld_starttimer(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         struct timeval now;          struct timeval now;
   
Line 204  mld_starttimer(in6m)
Line 202  mld_starttimer(in6m)
         }          }
   
         /* start or restart the timer */          /* start or restart the timer */
         callout_reset(in6m->in6m_timer_ch, in6m->in6m_timer,          callout_schedule(&in6m->in6m_timer_ch, in6m->in6m_timer);
             (void (*) __P((void *)))mld_timeo, in6m);  
 }  }
   
 static void  static void
 mld_stoptimer(in6m)  mld_stoptimer(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         if (in6m->in6m_timer == IN6M_TIMER_UNDEF)          if (in6m->in6m_timer == IN6M_TIMER_UNDEF)
                 return;                  return;
   
         callout_stop(in6m->in6m_timer_ch);          callout_stop(&in6m->in6m_timer_ch);
   
         in6m->in6m_timer = IN6M_TIMER_UNDEF;          in6m->in6m_timer = IN6M_TIMER_UNDEF;
 }  }
   
 static void  static void
 mld_timeo(in6m)  mld_timeo(void *arg)
         struct in6_multi *in6m;  
 {  {
           struct in6_multi *in6m = arg;
         int s = splsoftnet();          int s = splsoftnet();
   
         in6m->in6m_timer = IN6M_TIMER_UNDEF;          in6m->in6m_timer = IN6M_TIMER_UNDEF;
   
         callout_stop(in6m->in6m_timer_ch);  
   
         switch (in6m->in6m_state) {          switch (in6m->in6m_state) {
         case MLD_REPORTPENDING:          case MLD_REPORTPENDING:
                 mld_start_listening(in6m);                  mld_start_listening(in6m);
Line 243  mld_timeo(in6m)
Line 237  mld_timeo(in6m)
 }  }
   
 static u_long  static u_long
 mld_timerresid(in6m)  mld_timerresid(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         struct timeval now, diff;          struct timeval now, diff;
   
Line 268  mld_timerresid(in6m)
Line 261  mld_timerresid(in6m)
 }  }
   
 static void  static void
 mld_start_listening(in6m)  mld_start_listening(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         struct in6_addr all_in6;          struct in6_addr all_in6;
   
Line 301  mld_start_listening(in6m)
Line 293  mld_start_listening(in6m)
 }  }
   
 static void  static void
 mld_stop_listening(in6m)  mld_stop_listening(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         struct in6_addr allnode, allrouter;          struct in6_addr allnode, allrouter;
   
Line 326  mld_stop_listening(in6m)
Line 317  mld_stop_listening(in6m)
 }  }
   
 void  void
 mld_input(m, off)  mld_input(struct mbuf *m, int off)
         struct mbuf *m;  
         int off;  
 {  {
         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);          struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
         struct mld_hdr *mldh;          struct mld_hdr *mldh;
Line 497  mld_input(m, off)
Line 486  mld_input(m, off)
 }  }
   
 static void  static void
 mld_sendpkt(in6m, type, dst)  mld_sendpkt(struct in6_multi *in6m, int type,
         struct in6_multi *in6m;          const struct in6_addr *dst)
         int type;  
         const struct in6_addr *dst;  
 {  {
         struct mbuf *mh;          struct mbuf *mh;
         struct mld_hdr *mldh;          struct mld_hdr *mldh;
Line 620  mld_allocbuf(struct mbuf **mh, int len, 
Line 607  mld_allocbuf(struct mbuf **mh, int len, 
  * Add an address to the list of IP6 multicast addresses for a given interface.   * Add an address to the list of IP6 multicast addresses for a given interface.
  */   */
 struct  in6_multi *  struct  in6_multi *
 in6_addmulti(maddr6, ifp, errorp, timer)  in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
         struct in6_addr *maddr6;          int *errorp, int timer)
         struct ifnet *ifp;  
         int *errorp, timer;  
 {  {
         struct  in6_ifaddr *ia;          struct  in6_ifaddr *ia;
         struct  in6_ifreq ifr;          struct  in6_ifreq ifr;
Line 659  in6_addmulti(maddr6, ifp, errorp, timer)
Line 644  in6_addmulti(maddr6, ifp, errorp, timer)
                 in6m->in6m_ifp = ifp;                  in6m->in6m_ifp = ifp;
                 in6m->in6m_refcount = 1;                  in6m->in6m_refcount = 1;
                 in6m->in6m_timer = IN6M_TIMER_UNDEF;                  in6m->in6m_timer = IN6M_TIMER_UNDEF;
                 in6m->in6m_timer_ch =  
                     malloc(sizeof(*in6m->in6m_timer_ch), M_IPMADDR, M_NOWAIT);  
                 if (in6m->in6m_timer_ch == NULL) {  
                         free(in6m, M_IPMADDR);  
                         splx(s);  
                         return (NULL);  
                 }  
                 IFP_TO_IA6(ifp, ia);                  IFP_TO_IA6(ifp, ia);
                 if (ia == NULL) {                  if (ia == NULL) {
                         free(in6m, M_IPMADDR);                          free(in6m, M_IPMADDR);
Line 681  in6_addmulti(maddr6, ifp, errorp, timer)
Line 659  in6_addmulti(maddr6, ifp, errorp, timer)
                  * Ask the network driver to update its multicast reception                   * Ask the network driver to update its multicast reception
                  * filter appropriately for the new address.                   * filter appropriately for the new address.
                  */                   */
                 memset(&ifr.ifr_addr, 0, sizeof(struct sockaddr_in6));                  sockaddr_in6_init(&ifr.ifr_addr, maddr6, 0, 0, 0);
                 ifr.ifr_addr.sin6_family = AF_INET6;  
                 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);  
                 ifr.ifr_addr.sin6_addr = *maddr6;  
                 if (ifp->if_ioctl == NULL)                  if (ifp->if_ioctl == NULL)
                         *errorp = ENXIO; /* XXX: appropriate? */                          *errorp = ENXIO; /* XXX: appropriate? */
                 else                  else
                         *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,                          *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,
                             (caddr_t)&ifr);                              (void *)&ifr);
                 if (*errorp) {                  if (*errorp) {
                         LIST_REMOVE(in6m, in6m_entry);                          LIST_REMOVE(in6m, in6m_entry);
                         free(in6m, M_IPMADDR);                          free(in6m, M_IPMADDR);
Line 698  in6_addmulti(maddr6, ifp, errorp, timer)
Line 673  in6_addmulti(maddr6, ifp, errorp, timer)
                         return (NULL);                          return (NULL);
                 }                  }
   
                 callout_init(in6m->in6m_timer_ch);                  callout_init(&in6m->in6m_timer_ch, 0);
                   callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m);
                 in6m->in6m_timer = timer;                  in6m->in6m_timer = timer;
                 if (in6m->in6m_timer > 0) {                  if (in6m->in6m_timer > 0) {
                         in6m->in6m_state = MLD_REPORTPENDING;                          in6m->in6m_state = MLD_REPORTPENDING;
Line 722  in6_addmulti(maddr6, ifp, errorp, timer)
Line 698  in6_addmulti(maddr6, ifp, errorp, timer)
  * Delete a multicast address record.   * Delete a multicast address record.
  */   */
 void  void
 in6_delmulti(in6m)  in6_delmulti(struct in6_multi *in6m)
         struct in6_multi *in6m;  
 {  {
         struct  in6_ifreq ifr;          struct  in6_ifreq ifr;
         struct  in6_ifaddr *ia;          struct  in6_ifaddr *ia;
Line 763  in6_delmulti(in6m)
Line 738  in6_delmulti(in6m)
                  * Notify the network driver to update its multicast                   * Notify the network driver to update its multicast
                  * reception filter.                   * reception filter.
                  */                   */
                 memset(&ifr.ifr_addr, 0, sizeof(struct sockaddr_in6));                  sockaddr_in6_init(&ifr.ifr_addr, &in6m->in6m_addr, 0, 0, 0);
                 ifr.ifr_addr.sin6_family = AF_INET6;  
                 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);  
                 ifr.ifr_addr.sin6_addr = in6m->in6m_addr;  
                 (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,                  (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,
                     SIOCDELMULTI, (caddr_t)&ifr);                      SIOCDELMULTI, (void *)&ifr);
                 free(in6m->in6m_timer_ch, M_IPMADDR);                  callout_destroy(&in6m->in6m_timer_ch);
                 free(in6m, M_IPMADDR);                  free(in6m, M_IPMADDR);
         }          }
         splx(s);          splx(s);
Line 777  in6_delmulti(in6m)
Line 749  in6_delmulti(in6m)
   
   
 struct in6_multi_mship *  struct in6_multi_mship *
 in6_joingroup(ifp, addr, errorp, timer)  in6_joingroup(struct ifnet *ifp, struct in6_addr *addr,
         struct ifnet *ifp;          int *errorp, int timer)
         struct in6_addr *addr;  
         int *errorp, timer;  
 {  {
         struct in6_multi_mship *imm;          struct in6_multi_mship *imm;
   
Line 793  in6_joingroup(ifp, addr, errorp, timer)
Line 763  in6_joingroup(ifp, addr, errorp, timer)
         memset(imm, 0, sizeof(*imm));          memset(imm, 0, sizeof(*imm));
         imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp, timer);          imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp, timer);
         if (!imm->i6mm_maddr) {          if (!imm->i6mm_maddr) {
                 /* *errorp is alrady set */                  /* *errorp is already set */
                 free(imm, M_IPMADDR);                  free(imm, M_IPMADDR);
                 return NULL;                  return NULL;
         }          }
Line 801  in6_joingroup(ifp, addr, errorp, timer)
Line 771  in6_joingroup(ifp, addr, errorp, timer)
 }  }
   
 int  int
 in6_leavegroup(imm)  in6_leavegroup(struct in6_multi_mship *imm)
         struct in6_multi_mship *imm;  
 {  {
   
         if (imm->i6mm_maddr) {          if (imm->i6mm_maddr) {
Line 820  in6_leavegroup(imm)
Line 789  in6_leavegroup(imm)
  * such time as this interface is reconfigured for IPv6.   * such time as this interface is reconfigured for IPv6.
  */   */
 void  void
 in6_savemkludge(oia)  in6_savemkludge(struct in6_ifaddr *oia)
         struct in6_ifaddr *oia;  
 {  {
         struct in6_ifaddr *ia;          struct in6_ifaddr *ia;
         struct in6_multi *in6m, *next;          struct in6_multi *in6m;
   
         IFP_TO_IA6(oia->ia_ifp, ia);          IFP_TO_IA6(oia->ia_ifp, ia);
         if (ia) {       /* there is another address */          if (ia) {       /* there is another address */
                 for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);                  KASSERT(ia != oia);
                      in6m != NULL;                  while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) {
                      in6m = next) {                          LIST_REMOVE(in6m, in6m_entry);
                         next = LIST_NEXT(in6m, in6m_entry);  
                         IFAFREE(&in6m->in6m_ia->ia_ifa);  
                         IFAREF(&ia->ia_ifa);                          IFAREF(&ia->ia_ifa);
                           IFAFREE(&in6m->in6m_ia->ia_ifa);
                         in6m->in6m_ia = ia;                          in6m->in6m_ia = ia;
                         LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);                          LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
                 }                  }
Line 847  in6_savemkludge(oia)
Line 814  in6_savemkludge(oia)
                 if (mk == NULL) /* this should not happen! */                  if (mk == NULL) /* this should not happen! */
                         panic("in6_savemkludge: no kludge space");                          panic("in6_savemkludge: no kludge space");
   
                 for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);                  while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) {
                      in6m != NULL;                          LIST_REMOVE(in6m, in6m_entry);
                      in6m = next) {  
                         next = LIST_NEXT(in6m, in6m_entry);  
                         IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */                          IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
                         in6m->in6m_ia = NULL;                          in6m->in6m_ia = NULL;
                         LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);                          LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
Line 864  in6_savemkludge(oia)
Line 829  in6_savemkludge(oia)
  * then we re-attach it to the first address configured on the i/f.   * then we re-attach it to the first address configured on the i/f.
  */   */
 void  void
 in6_restoremkludge(ia, ifp)  in6_restoremkludge(struct in6_ifaddr *ia, struct ifnet *ifp)
         struct in6_ifaddr *ia;  
         struct ifnet *ifp;  
 {  {
         struct multi6_kludge *mk;          struct multi6_kludge *mk;
         struct in6_multi *in6m, *next;          struct in6_multi *in6m;
   
         LIST_FOREACH(mk, &in6_mk, mk_entry) {          LIST_FOREACH(mk, &in6_mk, mk_entry) {
                 if (mk->mk_ifp == ifp)                  if (mk->mk_ifp == ifp)
Line 877  in6_restoremkludge(ia, ifp)
Line 840  in6_restoremkludge(ia, ifp)
         }          }
         if (mk == NULL)          if (mk == NULL)
                 return;                  return;
         for (in6m = LIST_FIRST(&mk->mk_head); in6m != NULL; in6m = next) {          while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) {
                 next = LIST_NEXT(in6m, in6m_entry);                  LIST_REMOVE(in6m, in6m_entry);
                 in6m->in6m_ia = ia;                  in6m->in6m_ia = ia;
                 IFAREF(&ia->ia_ifa);                  IFAREF(&ia->ia_ifa);
                 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);                  LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
         }          }
         LIST_INIT(&mk->mk_head);  
 }  }
   
 /*  /*
Line 898  in6_restoremkludge(ia, ifp)
Line 860  in6_restoremkludge(ia, ifp)
  * it is a global function.   * it is a global function.
  */   */
 void  void
 in6_createmkludge(ifp)  in6_createmkludge(struct ifnet *ifp)
         struct ifnet *ifp;  
 {  {
         struct multi6_kludge *mk;          struct multi6_kludge *mk;
   
Line 918  in6_createmkludge(ifp)
Line 879  in6_createmkludge(ifp)
 }  }
   
 void  void
 in6_purgemkludge(ifp)  in6_purgemkludge(struct ifnet *ifp)
         struct ifnet *ifp;  
 {  {
         struct multi6_kludge *mk;          struct multi6_kludge *mk;
         struct in6_multi *in6m;          struct in6_multi *in6m, *next;
   
         LIST_FOREACH(mk, &in6_mk, mk_entry) {          LIST_FOREACH(mk, &in6_mk, mk_entry) {
                 if (mk->mk_ifp == ifp)                  if (mk->mk_ifp == ifp)
Line 932  in6_purgemkludge(ifp)
Line 892  in6_purgemkludge(ifp)
                 return;                  return;
   
         /* leave from all multicast groups joined */          /* leave from all multicast groups joined */
         while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) {          for (in6m = LIST_FIRST(&mk->mk_head); in6m != NULL; in6m = next) {
                   next = LIST_NEXT(in6m, in6m_entry);
                 in6_delmulti(in6m);                  in6_delmulti(in6m);
         }          }
         LIST_REMOVE(mk, mk_entry);          LIST_REMOVE(mk, mk_entry);

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.37.2.4

CVSweb <webmaster@jp.NetBSD.org>