1975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/*
2975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Copyright 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 Chesnutt#include "AsynchronousSocketCloseMonitor.h"
18975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "JNIHelp.h"
19975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "JniException.h"
20975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "JniConstants.h"
21975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "NetFd.h"
22975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "NetworkUtilities.h"
23975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "ScopedUtfChars.h"
24975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "ScopedPrimitiveArray.h"
25975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
26975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include "jni.h"
27975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
28975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <sys/types.h>
29975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <sys/socket.h>
30975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <linux/rtnetlink.h>
31975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <net/if.h>
32975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <linux/if_ether.h>
33975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <linux/if_packet.h>
34975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <arpa/inet.h>
35975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <errno.h>
36975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <fcntl.h>
37975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <poll.h>
38975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <netinet/ip.h>
39975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt#include <linux/udp.h>
40975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
41da2fb9754a9ccfa954c1b554982f06e7cf7d680aElliott Hughesunion sockunion {
422f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes    sockaddr sa;
432f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes    sockaddr_ll sll;
44da2fb9754a9ccfa954c1b554982f06e7cf7d680aElliott Hughes};
452f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes
46975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/*
47975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Creates a socket suitable for raw socket operations.  The socket is
48975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * bound to the interface specified by the supplied name.  The socket
49975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * value is placed into the supplied FileDescriptor instance.
50975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt *
51975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * TODO(chesnutt): consider breaking this into pieces: create a
52975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * variety of constructors for different socket types, then a generic
53975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * setBlocking() method followed by polymorphic bind().
54975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */
55975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttstatic void RawSocket_create(JNIEnv* env, jclass, jobject fileDescriptor,
565f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    jshort protocolType, jstring interfaceName)
575f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff{
58975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
59975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  ScopedUtfChars ifname(env, interfaceName);
60975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (ifname.c_str() == NULL) {
61975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return;
62975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
63975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
64da2fb9754a9ccfa954c1b554982f06e7cf7d680aElliott Hughes  sockunion su;
65975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  memset(&su, 0, sizeof(su));
66975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_family = PF_PACKET;
675f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff  su.sll.sll_protocol = htons(protocolType);
68975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_ifindex = if_nametoindex(ifname.c_str());
695f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff  int sock = socket(PF_PACKET, SOCK_DGRAM, htons(protocolType));
70975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
71975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (sock == -1) {
72679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block    ALOGE("Can't create socket %s", strerror(errno));
73975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    jniThrowSocketException(env, errno);
74975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return;
75975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
76975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
77975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
78975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (!setBlocking(sock, false)) {
79679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block    ALOGE("Can't set non-blocking mode on socket %s", strerror(errno));
80975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    jniThrowSocketException(env, errno);
81975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return;
82975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
83975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
84975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  int err = bind(sock, &su.sa, sizeof(su));
85975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (err != 0) {
86679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block    ALOGE("Socket bind error %s", strerror(errno));
87975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    jniThrowSocketException(env, errno);
88975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return;
89975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
90975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt}
91975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
92975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/*
93975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Writes the L3 (IP) packet to the raw socket supplied in the
94975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * FileDescriptor instance.
95975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt *
96975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Assumes that the caller has validated the offset & byteCount values.
97975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */
98975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttstatic int RawSocket_sendPacket(JNIEnv* env, jclass, jobject fileDescriptor,
995f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    jstring interfaceName, jshort protocolType, jbyteArray destMac,
1005f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    jbyteArray packet, jint offset, jint byteCount)
101975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt{
102975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  NetFd fd(env, fileDescriptor);
103975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
104975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (fd.isClosed()) {
105975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
106975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
107975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
108975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  ScopedUtfChars ifname(env, interfaceName);
109975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (ifname.c_str() == NULL) {
110975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
111975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
112975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
113975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  ScopedByteArrayRO byteArray(env, packet);
114975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (byteArray.get() == NULL) {
115975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
116975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
117975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
118975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  ScopedByteArrayRO mac(env, destMac);
119975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (mac.get() == NULL) {
120975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
121975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
122975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
123da2fb9754a9ccfa954c1b554982f06e7cf7d680aElliott Hughes  sockunion su;
124975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  memset(&su, 0, sizeof(su));
125975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_hatype = htons(1); // ARPHRD_ETHER
126975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_halen = mac.size();
127975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  memcpy(&su.sll.sll_addr, mac.get(), mac.size());
128975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_family = AF_PACKET;
1295f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff  su.sll.sll_protocol = htons(protocolType);
130975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  su.sll.sll_ifindex = if_nametoindex(ifname.c_str());
131975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
132975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  int err;
133975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  {
134975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    int intFd = fd.get();
135975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    AsynchronousSocketCloseMonitor monitor(intFd);
136975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    err = NET_FAILURE_RETRY(fd, sendto(intFd, byteArray.get() + offset,
137975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt        byteCount, 0, &su.sa, sizeof(su)));
138975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
139975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
140975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  return err;
141975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt}
142975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
143975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt/*
144975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Reads a network packet into the user-supplied buffer.  Return the
145975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * length of the packet, or a 0 if there was a timeout or an
146975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * unacceptable packet was acquired.
147975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt *
148975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt * Assumes that the caller has validated the offset & byteCount values.
149975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt */
150975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttstatic jint RawSocket_recvPacket(JNIEnv* env, jclass, jobject fileDescriptor,
151975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    jbyteArray packet, jint offset, jint byteCount, jint port,
152975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    jint timeout_millis)
153975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt{
154975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  NetFd fd(env, fileDescriptor);
155975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (fd.isClosed()) {
156975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
157975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
158975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
159975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  ScopedByteArrayRW body(env, packet);
160975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  jbyte* packetData = body.get();
161975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (packetData == NULL) {
162975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
163975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
164975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
165975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  packetData += offset;
166975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
1672f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes  pollfd fds[1];
168975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  fds[0].fd = fd.get();
169975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  fds[0].events = POLLIN;
170975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  int retval = poll(fds, 1, timeout_millis);
171975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (retval <= 0) {
172975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
173975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
174975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
1752f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes  unsigned int size = 0;
176975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  {
1772f03ccad590827233fcba84a8b6eafcd414e5fe7Elliott Hughes    int packetSize = byteCount;
178975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    int intFd = fd.get();
179975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    AsynchronousSocketCloseMonitor monitor(intFd);
180975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    size = NET_FAILURE_RETRY(fd, read(intFd, packetData, packetSize));
181975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
182975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
183975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  if (env->ExceptionOccurred()) {
184975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt    return 0;
185975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
186975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
1875f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff  if (port != -1) {
1885f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    // quick check for UDP type & UDP port
1895f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    // the packet is an IP header, UDP header, and UDP payload
1905f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    if ((size < (sizeof(struct iphdr) + sizeof(struct udphdr)))) {
1915f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff      return 0;  // runt packet
1925f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    }
193975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
1945f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    u_int8_t ip_proto = ((iphdr *) packetData)->protocol;
1955f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    if (ip_proto != IPPROTO_UDP) {
1965f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff      return 0;  // something other than UDP
1975f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    }
198975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
1995f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    __be16 destPort = htons((reinterpret_cast<udphdr*>(packetData + sizeof(iphdr)))->dest);
2005f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    if (destPort != port) {
2015f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff      return 0; // something other than requested port
2025f0ed6ed5798a3e6ad642bcd5382b864796cdcb8Irfan Sheriff    }
203975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  }
204975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
205975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt  return size;
206975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt}
207975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
208975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnuttstatic JNINativeMethod gRawMethods[] = {
2097cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes  NATIVE_METHOD(RawSocket, create, "(Ljava/io/FileDescriptor;SLjava/lang/String;)V"),
2107cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes  NATIVE_METHOD(RawSocket, sendPacket, "(Ljava/io/FileDescriptor;Ljava/lang/String;S[B[BII)I"),
2117cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes  NATIVE_METHOD(RawSocket, recvPacket, "(Ljava/io/FileDescriptor;[BIIII)I"),
212975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt};
213975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt
2147cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_libcore_net_RawSocket(JNIEnv* env) {
2157cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes  jniRegisterNativeMethods(env, "libcore/net/RawSocket", gRawMethods, NELEM(gRawMethods));
216975dc421bdf9f207ed88b3fbedbba558f0f62c3cStan Chesnutt}
217