private DatagramChannel connectClient() throws IOException { final DatagramChannel client = address.isMulticastAddress() ? DatagramChannel.open(address.getAddress().length == 4 ? INET : INET6) : DatagramChannel.open(); final InetSocketAddress hostAddress = new InetSocketAddress(port); client.configureBlocking(false); if (address.isMulticastAddress()) { client.setOption(SO_REUSEADDR, true); client.bind(hostAddress); if (networkInterface != null) { // This is probably not needed, because client socket doesn't send datagrams, // but since EVERYBODY on the internet configures this for any channels, and // I don't see any harm this config could make, I leave it here client.setOption(IP_MULTICAST_IF, networkInterface); client.join(address, networkInterface); } else { client.join(address, NetworkInterface.getByInetAddress(hostAddress.getAddress())); } if (LOG.isDebugEnabled()) LOG.debug("Connecting via multicast, group=" + address); } else { client.bind(hostAddress); } if (LOG.isDebugEnabled()) LOG.debug("Listening on port " + port); closeables.add(client); return client; }
/** Block datagrams from given source if a memory to receive all datagrams. */ void block(MembershipKeyImpl key, InetAddress source) throws IOException { assert key.channel() == this; assert key.sourceAddress() == null; synchronized (stateLock) { if (!key.isValid()) throw new IllegalStateException("key is no longer valid"); if (source.isAnyLocalAddress()) throw new IllegalArgumentException("Source address is a wildcard address"); if (source.isMulticastAddress()) throw new IllegalArgumentException("Source address is multicast address"); if (source.getClass() != key.group().getClass()) throw new IllegalArgumentException("Source address is different type to group"); int n; if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) key; n = Net.block6(fd, key6.groupAddress(), key6.index(), Net.inet6AsByteArray(source)); } else { MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) key; n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), Net.inet4AsInt(source)); } if (n == IOStatus.UNAVAILABLE) { // ancient kernel throw new UnsupportedOperationException(); } } }
/** Publish a request message to the specified multicast group. */ protected void publishRequest(String message) throws IOException, SocketException { groupAddr = InetAddress.getByName(request_group); interfaceAddr = InetAddress.getByName(request_interface_address); /* is it a multicast address? */ if (groupAddr.isMulticastAddress()) { /* open the socket and join the multicast group */ udpSocket = new MulticastSocket(); udpSocket.setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddr)); udpSocket.setInterface(interfaceAddr); udpSocket.joinGroup(groupAddr); /* Send request packet */ DatagramPacket p = new DatagramPacket(message.getBytes(), message.getBytes().length, groupAddr, 7777); System.out.println("Sending request: " + new String(p.getData(), 0, p.getLength())); udpSocket.send(p); } else { System.err.println("Invalid multicast address: " + groupAddr.toString()); } }
public static String[] getNetworkParams(NetworkInterface nic) { List<InterfaceAddress> addrs = nic.getInterfaceAddresses(); if (addrs == null || addrs.size() == 0) { return null; } InterfaceAddress addr = null; for (InterfaceAddress iaddr : addrs) { InetAddress inet = iaddr.getAddress(); if (!inet.isLinkLocalAddress() && !inet.isLoopbackAddress() && !inet.isMulticastAddress() && inet.getAddress().length == 4) { addr = iaddr; break; } } if (addr == null) { return null; } String[] result = new String[3]; result[0] = addr.getAddress().getHostAddress(); try { byte[] mac = nic.getHardwareAddress(); result[1] = byte2Mac(mac); } catch (Exception e) { } result[2] = prefix2Netmask(addr.getNetworkPrefixLength()); return result; }
/** * Joins a multicast group. Its behavior may be affected by {@code setInterface} or {@code * setNetworkInterface}. * * <p>If there is a security manager, this method first calls its {@code checkMulticast} method * with the {@code mcastaddr} argument as its argument. * * @param mcastaddr is the multicast address to join * @exception IOException if there is an error joining or when the address is not a multicast * address. * @exception SecurityException if a security manager exists and its {@code checkMulticast} method * doesn't allow the join. * @see SecurityManager#checkMulticast(InetAddress) */ public void joinGroup(InetAddress mcastaddr) throws IOException { if (isClosed()) { throw new SocketException("Socket is closed"); } checkAddress(mcastaddr, "joinGroup"); SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkMulticast(mcastaddr); } if (!mcastaddr.isMulticastAddress()) { throw new SocketException("Not a multicast address"); } /** * required for some platforms where it's not possible to join a group without setting the * interface first. */ NetworkInterface defaultInterface = NetworkInterface.getDefault(); if (!interfaceSet && defaultInterface != null) { setNetworkInterface(defaultInterface); } getImpl().join(mcastaddr); }
// TODO: needs to be InetAddress[] public InetAddress resolvePublishHostAddresses(String publishHosts[]) throws IOException { if (publishHosts == null) { if (GLOBAL_NETWORK_PUBLISHHOST_SETTING.exists(settings) || GLOBAL_NETWORK_HOST_SETTING.exists(settings)) { // if we have settings use them (we have a fallback to GLOBAL_NETWORK_HOST_SETTING inline publishHosts = GLOBAL_NETWORK_PUBLISHHOST_SETTING.get(settings).toArray(Strings.EMPTY_ARRAY); } else { // next check any registered custom resolvers for (CustomNameResolver customNameResolver : customNameResolvers) { InetAddress addresses[] = customNameResolver.resolveDefault(); if (addresses != null) { return addresses[0]; } } // we know it's not here. get the defaults publishHosts = GLOBAL_NETWORK_PUBLISHHOST_SETTING.get(settings).toArray(Strings.EMPTY_ARRAY); } } InetAddress addresses[] = resolveInetAddresses(publishHosts); // TODO: allow publishing multiple addresses // for now... the hack begins // 1. single wildcard address, probably set by network.host: expand to all interface addresses. if (addresses.length == 1 && addresses[0].isAnyLocalAddress()) { HashSet<InetAddress> all = new HashSet<>(Arrays.asList(NetworkUtils.getAllAddresses())); addresses = all.toArray(new InetAddress[all.size()]); } // 2. try to deal with some (mis)configuration for (InetAddress address : addresses) { // check if its multicast: flat out mistake if (address.isMulticastAddress()) { throw new IllegalArgumentException( "publish address: {" + NetworkAddress.format(address) + "} is invalid: multicast address"); } // check if its a wildcard address: this is only ok if its the only address! // (if it was a single wildcard address, it was replaced by step 1 above) if (address.isAnyLocalAddress()) { throw new IllegalArgumentException( "publish address: {" + NetworkAddress.format(address) + "} is wildcard, but multiple addresses specified: this makes no sense"); } } // 3. if we end out with multiple publish addresses, select by preference. // don't warn the user, or they will get confused by bind_host vs publish_host etc. if (addresses.length > 1) { List<InetAddress> sorted = new ArrayList<>(Arrays.asList(addresses)); NetworkUtils.sortAddresses(sorted); addresses = new InetAddress[] {sorted.get(0)}; } return addresses[0]; }
public int send(ByteBuffer src, SocketAddress target) throws IOException { if (src == null) throw new NullPointerException(); synchronized (writeLock) { ensureOpen(); InetSocketAddress isa = Net.checkAddress(target); InetAddress ia = isa.getAddress(); if (ia == null) throw new IOException("Target address not resolved"); synchronized (stateLock) { if (!isConnected()) { if (target == null) throw new NullPointerException(); SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ia.isMulticastAddress()) { sm.checkMulticast(ia); } else { sm.checkConnect(ia.getHostAddress(), isa.getPort()); } } } else { // Connected case; Check address then write if (!target.equals(remoteAddress)) { throw new IllegalArgumentException("Connected address not equal to target address"); } return write(src); } } int n = 0; try { begin(); if (!isOpen()) return 0; writerThread = NativeThread.current(); do { n = send(fd, src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); synchronized (stateLock) { if (isOpen() && (localAddress == null)) { localAddress = Net.localAddress(fd); } } return IOStatus.normalize(n); } finally { writerThread = 0; end((n > 0) || (n == IOStatus.UNAVAILABLE)); assert IOStatus.check(n); } } }
private synchronized void addLocalAddress(InetAddress addr) { int addrtype; if (addr.isLoopbackAddress()) { addrtype = HOSTMAP_LOOPBACK; } else if (addr.isLinkLocalAddress()) { addrtype = HOSTMAP_LINKLOCAL; } else if (addr.isSiteLocalAddress()) { addrtype = HOSTMAP_SITELOCAL; } else if (addr.isMulticastAddress()) { addrtype = HOSTMAP_MULTICAST; } else { addrtype = HOSTMAP_GLOBAL; } if (addr.getAddress().length == 4) { addrtype |= HOSTMAP_IPV4; } else { addrtype |= HOSTMAP_IPV6; } String addrAsString = addr.getHostAddress(); fLocalHostAddresses.put(addrAsString, Integer.valueOf(addrtype | HOSTMAP_ADDR)); if (0 == (addrtype & (HOSTMAP_LINKLOCAL | HOSTMAP_SITELOCAL | HOSTMAP_MULTICAST))) { // Don't do DNS Reverse Loopkup's for non-routable addresses. // They won't be known to the Name Server anyway, and they // make startup _much_ slower. String addrAsNameCan = addr.getCanonicalHostName().toLowerCase(); // query the name after the canonical name, it will re-use // cached canonical name (if the name was not explicitly set) String addrAsName = addr.getHostName().toLowerCase(); if (!addrAsNameCan.equals(addrAsString)) { // We must check if we really got a name, since InetAddress.getHostName() // returns the original address in case it thinks the name is spoofed! if (0 == (addrtype & HOSTMAP_LOOPBACK)) { // Not loopback --> found a Canonical Name. fLocalHostAddresses.put( addrAsNameCan, Integer.valueOf(addrtype | HOSTMAP_NAME | HOSTMAP_CANONICALNAME)); // override the address as canonical-address fLocalHostAddresses.put( addrAsString, Integer.valueOf(addrtype | HOSTMAP_ADDR | HOSTMAP_CANONICALADDR)); } else { // Loopback --> add the found name as non-canonical. fLocalHostAddresses.put(addrAsNameCan, Integer.valueOf(addrtype | HOSTMAP_NAME)); } } if (!addrAsName.equals(addrAsString) && !addrAsName.equals(addrAsNameCan)) { // don't override the canonical name by the name. fLocalHostAddresses.put(addrAsName, Integer.valueOf(addrtype | HOSTMAP_NAME)); } } }
/** * Leave a multicast group. Its behavior may be affected by <code>setInterface</code> or <code> * setNetworkInterface</code>. * * <p>If there is a security manager, this method first calls its <code>checkMulticast</code> * method with the <code>mcastaddr</code> argument as its argument. * * @param mcastaddr is the multicast address to leave * @exception IOException if there is an error leaving or when the address is not a multicast * address. * @exception SecurityException if a security manager exists and its <code>checkMulticast</code> * method doesn't allow the operation. * @see SecurityManager#checkMulticast(InetAddress) */ public void leaveGroup(InetAddress mcastaddr) throws IOException { if (isClosed()) { throw new SocketException("Socket is closed"); } SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkMulticast(mcastaddr); } if (!mcastaddr.isMulticastAddress()) { throw new SocketException("Not a multicast address"); } getImpl().leave(mcastaddr); }
/** * Initialise the listener, including opening a multicast socket and joining the specified * group. * * @throws IOException if the socket cannot be opened. * @throws SocketException if there is a problem setting the interface or joining the multicast * group. */ public void init() throws IOException, SocketException { String request_interface_address = InetAddress.getLocalHost().getHostAddress(); groupListenRequestAddr = InetAddress.getByName(request_group); interfaceListenRequestAddr = InetAddress.getByName(request_interface_address); /* is it a multicast address? */ if (groupListenRequestAddr.isMulticastAddress()) { udpListenRequestSocket = new MulticastSocket(request_port); udpListenRequestSocket.setInterface(interfaceListenRequestAddr); udpListenRequestSocket.joinGroup(groupListenRequestAddr); } else { System.err.println("Not a valid multicast address!"); } }
public static void main(String[] args) { if (args.length == 0 || args == null) { System.out.println("Didn't enter argument!, Please enter like this."); System.out.println("ex. java IPCharateristics args[0] args[1] ..."); return; } try { InetAddress address = InetAddress.getByName(args[0]); if (address.isAnyLocalAddress()) { System.out.println(address + " is a wildcard address."); } if (address.isLoopbackAddress()) { System.out.println(address + " is a loopback address."); } if (address.isLinkLocalAddress()) { System.out.println(address + " is a link-local address."); } if (address.isSiteLocalAddress()) { System.out.println(address + " is a site-local address"); } else { System.out.println(address + " is a global address"); } if (address.isMulticastAddress()) { if (address.isMCGlobal()) { System.out.println(address + " is a global multicast address."); } else if (address.isMCOrgLocal()) { System.out.println(address + " is an organization wide multicast address."); } else if (address.isMCSiteLocal()) { System.out.println(address + " is a site wide multicast address."); } else if (address.isMCLinkLocal()) { System.out.println(address + " is a subnet wide multicast address."); } else if (address.isMCNodeLocal()) { System.out.println(address + " is an interface-local multicast address."); } else { System.out.println(address + " is an unknown multicast address type."); } } else { System.out.println(address + " is a unicast address."); } } catch (UnknownHostException ex) { System.out.println("Could not resolve " + args[0]); } }
private Pair<String, Integer> validateUrl(String url) throws IllegalArgumentException { try { URI uri = new URI(url); if (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https")) { throw new IllegalArgumentException("Unsupported scheme for url"); } int port = uri.getPort(); if (!(port == 80 || port == 443 || port == -1)) { throw new IllegalArgumentException("Only ports 80 and 443 are allowed"); } if (port == -1 && uri.getScheme().equalsIgnoreCase("https")) { port = 443; } else if (port == -1 && uri.getScheme().equalsIgnoreCase("http")) { port = 80; } String host = uri.getHost(); try { InetAddress hostAddr = InetAddress.getByName(host); if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { throw new IllegalArgumentException("Illegal host specified in url"); } if (hostAddr instanceof Inet6Address) { throw new IllegalArgumentException( "IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); } return new Pair<String, Integer>(host, port); } catch (UnknownHostException uhe) { throw new IllegalArgumentException("Unable to resolve " + host); } } catch (IllegalArgumentException iae) { s_logger.warn("Failed uri validation check: " + iae.getMessage()); throw iae; } catch (URISyntaxException use) { s_logger.warn("Failed uri syntax check: " + use.getMessage()); throw new IllegalArgumentException(use.getMessage()); } }
/** * {@collect.stats} {@description.open} Connects this socket to a remote socket address (IP * address + port number). Binds socket if not already bound. * * <p>{@description.close} * * @param addr The remote address. * @param port The remote port * @throws SocketException if binding the socket fails. */ private synchronized void connectInternal(InetAddress address, int port) throws SocketException { if (port < 0 || port > 0xFFFF) { throw new IllegalArgumentException("connect: " + port); } if (address == null) { throw new IllegalArgumentException("connect: null address"); } checkAddress(address, "connect"); if (isClosed()) return; SecurityManager security = System.getSecurityManager(); if (security != null) { if (address.isMulticastAddress()) { security.checkMulticast(address); } else { security.checkConnect(address.getHostAddress(), port); security.checkAccept(address.getHostAddress(), port); } } if (!isBound()) bind(new InetSocketAddress(0)); // old impls do not support connect/disconnect if (oldImpl) { connectState = ST_CONNECTED_NO_IMPL; } else { try { getImpl().connect(address, port); // socket is now connected by the impl connectState = ST_CONNECTED; } catch (SocketException se) { // connection will be emulated by DatagramSocket connectState = ST_CONNECTED_NO_IMPL; } } connectedAddress = address; connectedPort = port; }
/** * Resolves {@code bindHosts} to a list of internet addresses. The list will not contain duplicate * addresses. * * @param bindHosts list of hosts to bind to. this may contain special pseudo-hostnames such as * _local_ (see the documentation). if it is null, it will be populated based on global * default settings. * @return unique set of internet addresses */ public InetAddress[] resolveBindHostAddresses(String bindHosts[]) throws IOException { // first check settings if (bindHosts == null) { if (GLOBAL_NETWORK_BINDHOST_SETTING.exists(settings) || GLOBAL_NETWORK_HOST_SETTING.exists(settings)) { // if we have settings use them (we have a fallback to GLOBAL_NETWORK_HOST_SETTING inline bindHosts = GLOBAL_NETWORK_BINDHOST_SETTING.get(settings).toArray(Strings.EMPTY_ARRAY); } else { // next check any registered custom resolvers for (CustomNameResolver customNameResolver : customNameResolvers) { InetAddress addresses[] = customNameResolver.resolveDefault(); if (addresses != null) { return addresses; } } // we know it's not here. get the defaults bindHosts = GLOBAL_NETWORK_BINDHOST_SETTING.get(settings).toArray(Strings.EMPTY_ARRAY); } } InetAddress addresses[] = resolveInetAddresses(bindHosts); // try to deal with some (mis)configuration for (InetAddress address : addresses) { // check if its multicast: flat out mistake if (address.isMulticastAddress()) { throw new IllegalArgumentException( "bind address: {" + NetworkAddress.format(address) + "} is invalid: multicast address"); } // check if its a wildcard address: this is only ok if its the only address! if (address.isAnyLocalAddress() && addresses.length > 1) { throw new IllegalArgumentException( "bind address: {" + NetworkAddress.format(address) + "} is wildcard, but multiple addresses specified: this makes no sense"); } } return addresses; }
private static boolean shouldInclude( InetAddress ia, boolean includeSiteLocal, boolean includeLoopbackAndWildcard, boolean includeIPv6) { return (!ia.isLinkLocalAddress()) && // 169.254.x.x (!ia.isMulticastAddress()) && (includeLoopbackAndWildcard || ((!ia.isAnyLocalAddress()) && (!ia.isLoopbackAddress()))) && (includeSiteLocal || ((!ia.isSiteLocalAddress()) && // disallow fc00::/8 and fd00::/8 (Unique local addresses RFC 4193) // not recognized as local by InetAddress (ia.getAddress().length != 16 || (ia.getAddress()[0] & 0xfe) != 0xfc))) && // Hamachi 5/8 allocated to RIPE (30 November 2010) // Removed from TransportImpl.isPubliclyRoutable() // Check moved to here, for now, but will eventually need to // remove it from here also. // (includeLocal || // (!ia.getHostAddress().startsWith("5."))) && (includeIPv6 || (ia instanceof Inet4Address)); }
private String validateUrl(String url) { try { URI uri = new URI(url); if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) { throw new IllegalArgumentException("Unsupported scheme for url: " + url); } int port = uri.getPort(); if (!(port == 80 || port == 443 || port == -1)) { throw new IllegalArgumentException("Only ports 80 and 443 are allowed"); } String host = uri.getHost(); try { InetAddress hostAddr = InetAddress.getByName(host); if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) { throw new IllegalArgumentException("Illegal host specified in url"); } if (hostAddr instanceof Inet6Address) { throw new IllegalArgumentException( "IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); } } catch (UnknownHostException uhe) { throw new IllegalArgumentException("Unable to resolve " + host); } return uri.toString(); } catch (URISyntaxException e) { throw new IllegalArgumentException("Invalid URL " + url); } }
private static boolean isGoodV6Address(InetAddress address) { return address instanceof Inet6Address && !address.isAnyLocalAddress() && !address.isLoopbackAddress() && !address.isMulticastAddress(); }
public static boolean isValidIp(long addr) { InetAddress ip = getAddressFromLong(addr); return !ip.isLoopbackAddress() && !ip.isMulticastAddress(); }
/** (thread entry-point) */ private void multicastReceiverThreadMain() { while (_enabled) { MulticastSocket socket = null; try { synchronized (_lock) { // clear flag regardless _recycleReceiver = false; } socket = createMulticastSocket(s_receiveSocketlabel, s_interface, MDNS_PORT); synchronized (_lock) { // make sure not flagged since reset if (_recycleReceiver) { Stream.safeClose(socket); continue; } _receiveSocket = socket; } while (_enabled) { DatagramPacket dp = UDPPacketRecycleQueue.instance().getReadyToUsePacket(); // ('returnPacket' will be called in 'catch' or later after use in thread-pool) try { socket.receive(dp); } catch (Exception exc) { UDPPacketRecycleQueue.instance().returnPacket(dp); throw exc; } InetAddress recvAddr = dp.getAddress(); if (recvAddr.isMulticastAddress()) { s_multicastInData.addAndGet(dp.getLength()); s_multicastInOps.incrementAndGet(); } else { s_unicastInData.addAndGet(dp.getLength()); s_unicastInOps.incrementAndGet(); } // check whether it's external i.e. completely different IP address // (local multicasting would almost always be reliable) MulticastSocket otherLocal = _sendSocket; boolean isLocal = (otherLocal != null && recvAddr.equals(otherLocal.getLocalAddress())); // update counter which is used to detect silence if (!isLocal) _lastExternalMulticastPacket = System.nanoTime(); enqueueForProcessing(dp, s_receiveSocketlabel); } // (inner while) } catch (Exception exc) { // (timeouts and general IO problems) // clean up regardless Stream.safeClose(socket); synchronized (_lock) { if (!_enabled) break; if (_recycleReceiver) _logger.info(s_receiveSocketlabel + " was gracefully closed. Will reinitialise..."); else _logger.warn( s_receiveSocketlabel + " receive failed; this may be a transitional condition. Will reinitialise... message was '" + exc.toString() + "'"); // set flag _recycleSender = true; // "signal" other thread Stream.safeClose(_sendSocket); // stagger retry Threads.waitOnSync(_lock, 333); } } } // (outer while) _logger.info("This thread has run to completion."); } // (method)
/** Joins channel's socket to the given group/interface and optional source address. */ private MembershipKey innerJoin(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException { if (!group.isMulticastAddress()) throw new IllegalArgumentException("Group not a multicast address"); // check multicast address is compatible with this socket if (group instanceof Inet4Address) { if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); } else if (group instanceof Inet6Address) { if (family != StandardProtocolFamily.INET6) throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); } else { throw new IllegalArgumentException("Address type not supported"); } // check source address if (source != null) { if (source.isAnyLocalAddress()) throw new IllegalArgumentException("Source address is a wildcard address"); if (source.isMulticastAddress()) throw new IllegalArgumentException("Source address is multicast address"); if (source.getClass() != group.getClass()) throw new IllegalArgumentException("Source address is different type to group"); } SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkMulticast(group); synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); // check the registry to see if we are already a member of the group if (registry == null) { registry = new MembershipRegistry(); } else { // return existing membership key MembershipKey key = registry.checkMembership(group, interf, source); if (key != null) return key; } MembershipKeyImpl key; if ((family == StandardProtocolFamily.INET6) && ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) { int index = interf.getIndex(); if (index == -1) throw new IOException("Network interface cannot be identified"); // need multicast and source address as byte arrays byte[] groupAddress = Net.inet6AsByteArray(group); byte[] sourceAddress = (source == null) ? null : Net.inet6AsByteArray(source); // join the group int n = Net.join6(fd, groupAddress, index, sourceAddress); if (n == IOStatus.UNAVAILABLE) throw new UnsupportedOperationException(); key = new MembershipKeyImpl.Type6( this, group, interf, source, groupAddress, index, sourceAddress); } else { // need IPv4 address to identify interface Inet4Address target = Net.anyInet4Address(interf); if (target == null) throw new IOException("Network interface not configured for IPv4"); int groupAddress = Net.inet4AsInt(group); int targetAddress = Net.inet4AsInt(target); int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); // join the group int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); if (n == IOStatus.UNAVAILABLE) throw new UnsupportedOperationException(); key = new MembershipKeyImpl.Type4( this, group, interf, source, groupAddress, targetAddress, sourceAddress); } registry.add(key); return key; } }