/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.net.ipv4; import java.net.BindException; import java.net.SocketException; /** * @author Ewout Prangsma (epr@users.sourceforge.net) */ public class IPv4ControlBlock { /** The list I'm a part of */ private final IPv4ControlBlockList list; /** The local address */ private IPv4Address lAddr; /** The local port */ private int lPort; /** The foreign address */ private IPv4Address fAddr; /** The foreign port */ private int fPort; /** The protocol to use in creating IPv4 headers */ private final int protocol; /** Type of Service to use in creating IPv4 headers */ private final int tos; /** Time to Live to use in creating IPv4 headers */ private final int ttl; /** * Create a new instance * * @param list * @param protocol * @param ttl */ public IPv4ControlBlock(IPv4ControlBlockList list, int protocol, int ttl) { this.list = list; this.protocol = protocol; this.tos = 0; this.ttl = ttl; this.lAddr = IPv4Address.ANY; this.lPort = 0; this.fAddr = IPv4Address.ANY; this.fPort = 0; } /** * @return Returns the foreign address. */ public final IPv4Address getForeignAddress() { return this.fAddr; } /** * @return Returns the foreign port. */ public final int getForeignPort() { return this.fPort; } /** * @return Returns the local address. */ public final IPv4Address getLocalAddress() { return this.lAddr; } /** * @return Returns the local port. */ public final int getLocalPort() { return this.lPort; } /** * Match this control block against the given parameters * * @param fAddr * @param fPort * @param lAddr * @param lPort * @param allowWildcards * @return -1 does not match, >= 0 matches, returns number of wildcards */ final int match(IPv4Address fAddr, int fPort, IPv4Address lAddr, int lPort, boolean allowWildcards) { if (this.lPort != lPort) { // No match return -1; } int wildcard = 0; if (!this.lAddr.isAny()) { if (lAddr.isAny()) { wildcard++; } else if (!this.lAddr.equals(lAddr)) { // No match return -1; } } else { if (!lAddr.isAny()) { wildcard++; } } if (!this.fAddr.isAny()) { if (fAddr.isAny()) { wildcard++; } else if (!this.fAddr.equals(fAddr) || (this.fPort != fPort)) { // No match return -1; } } else { if (!fAddr.isAny()) { wildcard++; } } if (!allowWildcards && (wildcard > 0)) { // No wildcard match allowed return -1; } return wildcard; } /** * Bind to a specific local address. * * @param lAddr * @param lPort */ final void bind(IPv4Address lAddr, int lPort) throws BindException { if ((this.lPort != 0) || !this.lAddr.isAny()) { throw new BindException("ControlBlock already bound"); } this.lAddr = lAddr; this.lPort = lPort; } /** * Connect to a foreign address. * * @param lAddr * @param fAddr * @param fPort */ public synchronized void connect(IPv4Address lAddr, IPv4Address fAddr, int fPort) { if (this.lAddr.isAny()) { if (lAddr.isAny()) { throw new IllegalArgumentException("Specific local address required"); } this.lAddr = lAddr; } else if (!this.lAddr.equals(lAddr)) { throw new IllegalArgumentException("Different lAddr " + lAddr); } this.fAddr = fAddr; this.fPort = fPort; } /** * Create a new control block that has the same local address and port and * is connecto to the given foreign address. * * @param lAddr * @param fAddr * @param fPort */ public IPv4ControlBlock copyAndConnect(IPv4Address lAddr, IPv4Address fAddr, int fPort) throws SocketException { final IPv4ControlBlock copy = list.createControlBlock(this); copy.bind(lAddr, lPort); copy.connect(lAddr, fAddr, fPort); list.add(copy); return copy; } /** * Close any connection and remove from the control block list. */ public synchronized void removeFromList() { this.list.remove(this); } /** * Create an IPv4 header for outgoing packets. * This control block must have been connected before calling this method. * The dataLength of the header is set to 0, this must be * changes before prefixing this header to a SocketBuffer. */ protected IPv4Header createOutgoingIPv4Header() { return new IPv4Header(tos, ttl, protocol, fAddr, 0); } /** * @see java.lang.Object#toString() */ public String toString() { return "local " + lAddr + ':' + lPort + ", foreign " + fAddr + ':' + fPort; } }