aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_iso88025subr.c
diff options
context:
space:
mode:
authorMatthew N. Dodd <mdodd@FreeBSD.org>2003-03-15 16:49:08 +0000
committerMatthew N. Dodd <mdodd@FreeBSD.org>2003-03-15 16:49:08 +0000
commit7c16bd3a8b45e19cb1fa372f0f27806c5bb8b857 (patch)
treec91962b8498192f18b2d13a7828b0995b3cb7f6f /sys/net/if_iso88025subr.c
parentbf54cb290abfcc80884c8acdb539a5d626a625b9 (diff)
downloadsrc-7c16bd3a8b45e19cb1fa372f0f27806c5bb8b857.tar.gz
src-7c16bd3a8b45e19cb1fa372f0f27806c5bb8b857.zip
Add iso88025_resolvemulti().
Cribbed from net/if_fddisubr.c
Notes
Notes: svn path=/head/; revision=112273
Diffstat (limited to 'sys/net/if_iso88025subr.c')
-rw-r--r--sys/net/if_iso88025subr.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 2abd7c8a2175..9b8d540a577d 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -77,6 +77,9 @@
#include <netipx/ipx_if.h>
#endif
+static int iso88025_resolvemulti (struct ifnet *, struct sockaddr **,
+ struct sockaddr *));
+
#define IFP2AC(IFP) ((struct arpcom *)IFP)
void
@@ -532,6 +535,90 @@ iso88025_input(ifp, th, m)
netisr_dispatch(isr, m);
}
+static int
+iso88025_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|M_ZERO);
+ sdl->sdl_len = sizeof *sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = IFT_ISO88025;
+ sdl->sdl_alen = ISO88025_ADDR_LEN;
+ 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|M_ZERO);
+ sdl->sdl_len = sizeof *sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = IFT_ISO88025;
+ sdl->sdl_alen = ISO88025_ADDR_LEN;
+ 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);
+ }
+
+ return (0);
+}
+
static moduledata_t iso88025_mod = {
"iso88025",
NULL,