1975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/* 2975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Copyright (C) 2010 The Android Open Source Project 3975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * 4975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Licensed under the Apache License, Version 2.0 (the "License"); 5975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * you may not use this file except in compliance with the License. 6975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * You may obtain a copy of the License at 7975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * 8975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * http://www.apache.org/licenses/LICENSE-2.0 9975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * 10975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Unless required by applicable law or agreed to in writing, software 11975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * distributed under the License is distributed on an "AS IS" BASIS, 12975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * See the License for the specific language governing permissions and 14975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * limitations under the License. 15975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 16975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 17975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttpackage libcore.net; 18975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 19975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport dalvik.system.CloseGuard; 20975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport java.io.Closeable; 21975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport java.io.FileDescriptor; 22975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport java.io.IOException; 23975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport java.net.SocketException; 24975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttimport java.util.Arrays; 250b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 26975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 27975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/** 28975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * This class allows raw L2 packets to be sent and received via the 29975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * specified network interface. The receive-side implementation is 30975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * restricted to UDP packets for efficiency. 31975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * 32975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * @hide 33975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 34975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttpublic class RawSocket implements Closeable { 355f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff /** 365f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * Ethernet IP protocol type, part of the L2 header of IP packets. 375f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff */ 385f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff public static final short ETH_P_IP = (short) 0x0800; 395f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff 405f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff /** 415f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * Ethernet ARP protocol type, part of the L2 header of ARP packets. 425f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff */ 435f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff public static final short ETH_P_ARP = (short) 0x0806; 445f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff 455f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff private static native void create(FileDescriptor fd, short 465f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff protocolType, String interfaceName) 47975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throws SocketException; 48975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt private static native int sendPacket(FileDescriptor fd, 495f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff String interfaceName, short protocolType, byte[] destMac, byte[] packet, 505f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff int offset, int byteCount); 51975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt private static native int recvPacket(FileDescriptor fd, byte[] packet, 52975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt int offset, int byteCount, int destPort, int timeoutMillis); 53975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 54975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt private final FileDescriptor fd; 55975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt private final String mInterfaceName; 565f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff private final short mProtocolType; 57975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt private final CloseGuard guard = CloseGuard.get(); 58975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 59975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt /** 60975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Creates a socket on the specified interface. 61975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 625f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff public RawSocket(String interfaceName, short protocolType) 635f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff throws SocketException { 64975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt mInterfaceName = interfaceName; 655f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff mProtocolType = protocolType; 66975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt fd = new FileDescriptor(); 675f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff create(fd, mProtocolType, mInterfaceName); 68975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt guard.open("close"); 69975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 70975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 71975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt /** 72975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Reads a raw packet into the specified buffer, with the 735f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * specified timeout. If the destPort is -1, then the IP 745f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * destination port is not verified, otherwise only packets 755f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * destined for the specified UDP port are returned. Returns the 765f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * length actually read. No indication of overflow is signaled. 775f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * The packet data will start at the IP header (EthernetII 785f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * dest/source/type headers are removed). 79975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 80975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt public int read(byte[] packet, int offset, int byteCount, int destPort, 81975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt int timeoutMillis) { 82975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt if (packet == null) { 83975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throw new NullPointerException("packet == null"); 84975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 85975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 86975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt Arrays.checkOffsetAndCount(packet.length, offset, byteCount); 87975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 885f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff if (destPort > 65535) { 89975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throw new IllegalArgumentException("Port out of range: " 90975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt + destPort); 91975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 92975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 93975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt return recvPacket(fd, packet, offset, byteCount, destPort, 94975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt timeoutMillis); 95975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 96975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 97975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt /** 98975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Writes a raw packet to the desired interface. A L2 header will 99975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * be added which includes the specified destination address, our 1005f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * source MAC, and the specified protocol type. The caller is responsible 1015f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff * for computing correct IP-header and payload checksums. 102975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 103975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt public int write(byte[] destMac, byte[] packet, int offset, int byteCount) { 104975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt if (destMac == null) { 105975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throw new NullPointerException("destMac == null"); 106975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 107975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 108975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt if (packet == null) { 109975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throw new NullPointerException("packet == null"); 110975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 111975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 112975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt Arrays.checkOffsetAndCount(packet.length, offset, byteCount); 113975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 114975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt if (destMac.length != 6) { 115975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt throw new IllegalArgumentException("MAC length must be 6: " 116975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt + destMac.length); 117975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 118975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 1195f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff return sendPacket(fd, mInterfaceName, mProtocolType, destMac, packet, 1205f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff offset, byteCount); 121975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 122975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 123975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt /** 124975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Closes the socket. After this method is invoked, subsequent 125975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * read/write operations will fail. 126975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */ 127975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt public void close() throws IOException { 128975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt guard.close(); 1290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoBridge.closeSocket(fd); 130975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 131975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt 132975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt @Override protected void finalize() throws Throwable { 133975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt try { 134975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt if (guard != null) { 135975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt guard.warnIfOpen(); 136975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 137975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt close(); 138975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } finally { 139975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt super.finalize(); 140975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 141975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt } 142975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt} 143