16193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline/*
26193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Copyright (C) 2015 The Android Open Source Project
36193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
46193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Licensed under the Apache License, Version 2.0 (the "License");
56193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * you may not use this file except in compliance with the License.
66193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * You may obtain a copy of the License at
76193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
86193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *      http://www.apache.org/licenses/LICENSE-2.0
96193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
106193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Unless required by applicable law or agreed to in writing, software
116193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * distributed under the License is distributed on an "AS IS" BASIS,
126193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * See the License for the specific language governing permissions and
146193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * limitations under the License.
156193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline */
166193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
176193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klinepackage android.net.netlink;
186193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
1984714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
2084714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport static android.system.OsConstants.NETLINK_ROUTE;
214a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertEquals;
224a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertNotNull;
234a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertTrue;
244a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi
256193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.NetlinkSocket;
266193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.RtNetlinkNeighborMessage;
276193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNdMsg;
286193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNlMsgHdr;
294a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport android.support.test.runner.AndroidJUnit4;
304a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport android.support.test.filters.SmallTest;
316193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.system.ErrnoException;
326193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.system.NetlinkSocketAddress;
3384714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport android.system.Os;
346193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.util.Log;
3584714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport libcore.io.IoUtils;
364a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi
376193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.io.InterruptedIOException;
3884714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport java.io.FileDescriptor;
396193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.nio.ByteBuffer;
406193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.nio.ByteOrder;
414a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi
424a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.runner.RunWith;
434a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.Test;
446193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
456193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
464a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi@RunWith(AndroidJUnit4.class)
474a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi@SmallTest
484a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichipublic class NetlinkSocketTest {
496193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    private final String TAG = "NetlinkSocketTest";
506193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
514a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi    @Test
526193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    public void testBasicWorkingGetNeighborsQuery() throws Exception {
5384714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE);
5484714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        assertNotNull(fd);
556193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
5684714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        NetlinkSocket.connectToKernel(fd);
576193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
5884714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd);
596193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        assertNotNull(localAddr);
606193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        assertEquals(0, localAddr.getGroupsMask());
616193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        assertTrue(0 != localAddr.getPortId());
626193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
636193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        final int TEST_SEQNO = 5;
6484714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO);
6584714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        assertNotNull(req);
666193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
676193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        final long TIMEOUT = 500;
6884714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT));
696193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
706193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        int neighMessageCount = 0;
716193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        int doneMessageCount = 0;
726193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
736193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        while (doneMessageCount == 0) {
7484714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline            ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
756193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            assertNotNull(response);
766193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit());
776193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            assertEquals(0, response.position());
786193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            assertEquals(ByteOrder.nativeOrder(), response.order());
796193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
806193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            // Verify the messages at least appears minimally reasonable.
816193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            while (response.remaining() > 0) {
826193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                final NetlinkMessage msg = NetlinkMessage.parse(response);
836193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertNotNull(msg);
846193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                final StructNlMsgHdr hdr = msg.getHeader();
856193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertNotNull(hdr);
866193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
876193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
886193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    doneMessageCount++;
896193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    continue;
906193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                }
916193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
926193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
936193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertTrue(msg instanceof RtNetlinkNeighborMessage);
946193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0);
956193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertEquals(TEST_SEQNO, hdr.nlmsg_seq);
966193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                assertEquals(localAddr.getPortId(), hdr.nlmsg_pid);
976193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
986193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                neighMessageCount++;
996193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            }
1006193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        }
1016193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
1026193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        assertEquals(1, doneMessageCount);
1036193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        // TODO: make sure this test passes sanely in airplane mode.
1046193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        assertTrue(neighMessageCount > 0);
1056193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
10684714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline        IoUtils.closeQuietly(fd);
107abd3142dcae02026689b939c363329b822b7cc0aErik Kline    }
1086193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline}
109