summaryrefslogtreecommitdiffstats
path: root/sys/net/if_fddisubr.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2000-11-01 16:57:01 +0000
committerume <ume@FreeBSD.org>2000-11-01 16:57:01 +0000
commit46dec50392f1ffdfdd71d2b80a188aea6a2790d4 (patch)
tree285bdbef0874c8c755f16482b1d067a5f54fdce7 /sys/net/if_fddisubr.c
parent549eb5cb6bb89790b0587cd0e692e7f610a33e25 (diff)
downloadFreeBSD-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/if_fddisubr.c')
-rw-r--r--sys/net/if_fddisubr.c87
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;
+ }
+}
OpenPOWER on IntegriCloud