diff options
author | ume <ume@FreeBSD.org> | 2000-11-01 16:57:01 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2000-11-01 16:57:01 +0000 |
commit | 46dec50392f1ffdfdd71d2b80a188aea6a2790d4 (patch) | |
tree | 285bdbef0874c8c755f16482b1d067a5f54fdce7 /sys/net | |
parent | 549eb5cb6bb89790b0587cd0e692e7f610a33e25 (diff) | |
download | FreeBSD-src-46dec50392f1ffdfdd71d2b80a188aea6a2790d4.zip FreeBSD-src-46dec50392f1ffdfdd71d2b80a188aea6a2790d4.tar.gz |
IPv6 was not work on FDDI.
Reported by: Akihiro IIJIMA <aki@noc.titech.ac.jp>
Submitted by: JINMEI Tatuya <jinmei@isl.rdc.toshiba.co.jp>
Reviewed by: Akihiro IIJIMA <aki@noc.titech.ac.jp>
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_fddisubr.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index b3a8ead..b0e74ab 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -93,6 +93,9 @@ extern u_char at_org_code[ 3 ]; extern u_char aarp_org_code[ 3 ]; #endif /* NETATALK */ +static int fddi_resolvemulti __P((struct ifnet *, struct sockaddr **, + struct sockaddr *)); + #define senderr(e) { error = (e); goto bad;} /* @@ -542,6 +545,7 @@ fddi_ifattach(ifp) ifp->if_addrlen = 6; ifp->if_hdrlen = 21; ifp->if_mtu = FDDIMTU; + ifp->if_resolvemulti = fddi_resolvemulti; ifp->if_baudrate = 100000000; #ifdef IFF_NOTRAILERS ifp->if_flags |= IFF_NOTRAILERS; @@ -569,3 +573,86 @@ fddi_ifattach(ifp) } #endif } + +static int +fddi_resolvemulti(ifp, llsa, sa) + struct ifnet *ifp; + struct sockaddr **llsa; + struct sockaddr *sa; +{ + struct sockaddr_dl *sdl; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif + u_char *e_addr; + + switch(sa->sa_family) { + case AF_LINK: + /* + * No mapping needed. Just check that it's a valid MC address. + */ + sdl = (struct sockaddr_dl *)sa; + e_addr = LLADDR(sdl); + if ((e_addr[0] & 1) != 1) + return EADDRNOTAVAIL; + *llsa = 0; + return 0; + +#ifdef INET + case AF_INET: + sin = (struct sockaddr_in *)sa; + if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) + return EADDRNOTAVAIL; + MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, + M_WAITOK); + sdl->sdl_len = sizeof *sdl; + sdl->sdl_family = AF_LINK; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = IFT_FDDI; + sdl->sdl_nlen = 0; + sdl->sdl_alen = ETHER_ADDR_LEN; /* XXX */ + sdl->sdl_slen = 0; + e_addr = LLADDR(sdl); + ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); + *llsa = (struct sockaddr *)sdl; + return 0; +#endif +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * An IP6 address of 0 means listen to all + * of the Ethernet multicast address used for IP6. + * (This is used for multicast routers.) + */ + ifp->if_flags |= IFF_ALLMULTI; + *llsa = 0; + return 0; + } + if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + return EADDRNOTAVAIL; + MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, + M_WAITOK); + sdl->sdl_len = sizeof *sdl; + sdl->sdl_family = AF_LINK; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = IFT_FDDI; + sdl->sdl_nlen = 0; + sdl->sdl_alen = ETHER_ADDR_LEN; /* XXX */ + sdl->sdl_slen = 0; + e_addr = LLADDR(sdl); + ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); + *llsa = (struct sockaddr *)sdl; + return 0; +#endif + + default: + /* + * Well, the text isn't quite right, but it's the name + * that counts... + */ + return EAFNOSUPPORT; + } +} |