• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
create(FileDescriptor fd, short protocolType, String interfaceName)45     private static native void create(FileDescriptor fd, short
46             protocolType, String interfaceName)
47             throws SocketException;
sendPacket(FileDescriptor fd, String interfaceName, short protocolType, byte[] destMac, byte[] packet, int offset, int byteCount)48     private static native int sendPacket(FileDescriptor fd,
49         String interfaceName, short protocolType, byte[] destMac, byte[] packet,
50         int offset, int byteCount);
recvPacket(FileDescriptor fd, byte[] packet, int offset, int byteCount, int destPort, int timeoutMillis)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      */
RawSocket(String interfaceName, short protocolType)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      */
read(byte[] packet, int offset, int byteCount, int destPort, int timeoutMillis)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      */
write(byte[] destMac, byte[] packet, int offset, int byteCount)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      */
close()127     public void close() throws IOException {
128         guard.close();
129         IoBridge.closeSocket(fd);
130     }
131 
finalize()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