Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.net;
     18 
     19 import dalvik.system.CloseGuard;
     20 import java.io.Closeable;
     21 import java.io.FileDescriptor;
     22 import java.io.IOException;
     23 import java.net.SocketException;
     24 import java.util.Arrays;
     25 import libcore.io.IoBridge;
     26 
     27 /**
     28  * This class allows raw L2 packets to be sent and received via the
     29  * specified network interface.  The receive-side implementation is
     30  * restricted to UDP packets for efficiency.
     31  *
     32  * @hide
     33  */
     34 public class RawSocket implements Closeable {
     35     /**
     36      * Ethernet IP protocol type, part of the L2 header of IP packets.
     37      */
     38     public static final short ETH_P_IP = (short) 0x0800;
     39 
     40     /**
     41      * Ethernet ARP protocol type, part of the L2 header of ARP packets.
     42      */
     43     public static final short ETH_P_ARP = (short) 0x0806;
     44 
     45     private static native void create(FileDescriptor fd, short
     46             protocolType, String interfaceName)
     47             throws SocketException;
     48     private static native int sendPacket(FileDescriptor fd,
     49         String interfaceName, short protocolType, byte[] destMac, byte[] packet,
     50         int offset, int byteCount);
     51     private static native int recvPacket(FileDescriptor fd, byte[] packet,
     52         int offset, int byteCount, int destPort, int timeoutMillis);
     53 
     54     private final FileDescriptor fd;
     55     private final String mInterfaceName;
     56     private final short mProtocolType;
     57     private final CloseGuard guard = CloseGuard.get();
     58 
     59     /**
     60      * Creates a socket on the specified interface.
     61      */
     62     public RawSocket(String interfaceName, short protocolType)
     63         throws SocketException {
     64         mInterfaceName = interfaceName;
     65         mProtocolType = protocolType;
     66         fd = new FileDescriptor();
     67         create(fd, mProtocolType, mInterfaceName);
     68         guard.open("close");
     69     }
     70 
     71     /**
     72      * Reads a raw packet into the specified buffer, with the
     73      * specified timeout.  If the destPort is -1, then the IP
     74      * destination port is not verified, otherwise only packets
     75      * destined for the specified UDP port are returned.  Returns the
     76      * length actually read.  No indication of overflow is signaled.
     77      * The packet data will start at the IP header (EthernetII
     78      * dest/source/type headers are removed).
     79      */
     80     public int read(byte[] packet, int offset, int byteCount, int destPort,
     81         int timeoutMillis) {
     82         if (packet == null) {
     83             throw new NullPointerException("packet == null");
     84         }
     85 
     86         Arrays.checkOffsetAndCount(packet.length, offset, byteCount);
     87 
     88         if (destPort > 65535) {
     89             throw new IllegalArgumentException("Port out of range: "
     90                 + destPort);
     91         }
     92 
     93         return recvPacket(fd, packet, offset, byteCount, destPort,
     94             timeoutMillis);
     95     }
     96 
     97     /**
     98      * Writes a raw packet to the desired interface.  A L2 header will
     99      * be added which includes the specified destination address, our
    100      * source MAC, and the specified protocol type.  The caller is responsible
    101      * for computing correct IP-header and payload checksums.
    102      */
    103     public int write(byte[] destMac, byte[] packet, int offset, int byteCount) {
    104         if (destMac == null) {
    105             throw new NullPointerException("destMac == null");
    106         }
    107 
    108         if (packet == null) {
    109             throw new NullPointerException("packet == null");
    110         }
    111 
    112         Arrays.checkOffsetAndCount(packet.length, offset, byteCount);
    113 
    114         if (destMac.length != 6) {
    115             throw new IllegalArgumentException("MAC length must be 6: "
    116                 + destMac.length);
    117         }
    118 
    119         return sendPacket(fd, mInterfaceName, mProtocolType, destMac, packet,
    120             offset, byteCount);
    121     }
    122 
    123     /**
    124      * Closes the socket.  After this method is invoked, subsequent
    125      * read/write operations will fail.
    126      */
    127     public void close() throws IOException {
    128         guard.close();
    129         IoBridge.closeSocket(fd);
    130     }
    131 
    132     @Override protected void finalize() throws Throwable {
    133         try {
    134             if (guard != null) {
    135                 guard.warnIfOpen();
    136             }
    137             close();
    138         } finally {
    139             super.finalize();
    140         }
    141     }
    142 }
    143