194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti/*
294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * Copyright (C) 2016 The Android Open Source Project
394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti *
494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * you may not use this file except in compliance with the License.
694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * You may obtain a copy of the License at
794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti *
894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti *
1094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * Unless required by applicable law or agreed to in writing, software
1194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
1294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * See the License for the specific language governing permissions and
1494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti * limitations under the License.
1594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti */
1694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
17fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <unistd.h>
18fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <sys/socket.h>
198464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
208464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/netlink.h>
218464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/sock_diag.h>
228464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/inet_diag.h>
238464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
24fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <functional>
25fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <set>
26fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
27c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti#include "Permission.h"
28fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include "UidRanges.h"
29fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
308464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittistruct inet_diag_msg;
31f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitticlass SockDiagTest;
328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitticlass SockDiag {
348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti  public:
368464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    static const int kBufferSize = 4096;
37fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
38fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    // Callback function that is called once for every socket in the dump. A return value of true
39fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    // means destroy the socket.
40fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    typedef std::function<bool(uint8_t proto, const inet_diag_msg *)> DumpCallback;
418464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
428464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    struct DestroyRequest {
438464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        nlmsghdr nlh;
448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        inet_diag_req_v2 req;
458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } __attribute__((__packed__));
468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
47f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    SockDiag() : mSock(-1), mWriteSock(-1), mSocketsDestroyed(0) {}
488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    bool open();
498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    virtual ~SockDiag() { closeSocks(); }
508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
5194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    int sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states);
528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr);
538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int readDiagMsg(uint8_t proto, DumpCallback callback);
548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int sockDestroy(uint8_t proto, const inet_diag_msg *);
550726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    // Destroys all sockets on the given IPv4 or IPv6 address.
56f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    int destroySockets(const char *addrstr);
570726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    // Destroys all sockets for the given protocol and UID.
580726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    int destroySockets(uint8_t proto, uid_t uid, bool excludeLoopback);
590726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    // Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets for the given UID ranges.
600726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    int destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids,
610726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti                       bool excludeLoopback);
62c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti    // Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets that no longer have
63c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti    // the permissions required by the specified network.
64c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti    int destroySocketsLackingPermission(unsigned netId, Permission permission,
65c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti                                        bool excludeLoopback);
668464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
678464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti  private:
680726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    friend class SockDiagTest;
698464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int mSock;
708464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int mWriteSock;
71f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    int mSocketsDestroyed;
7294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    int sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states, iovec *iov, int iovcnt);
73f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    int destroySockets(uint8_t proto, int family, const char *addrstr);
74c6201c3754710e235f16118761b23760ff4136adLorenzo Colitti    int destroyLiveSockets(DumpCallback destroy, const char *what, iovec *iov, int iovcnt);
758464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    bool hasSocks() { return mSock != -1 && mWriteSock != -1; }
768464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    void closeSocks() { close(mSock); close(mWriteSock); mSock = mWriteSock = -1; }
770726fec82842883a2332318aa675f7f04670db51Lorenzo Colitti    static bool isLoopbackSocket(const inet_diag_msg *msg);
788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti};
79