C++程序  |  138行  |  2.94 KB

/**
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define _GNU_SOURCE
#define ARRAY_SIZE(__a) (sizeof(__a) / sizeof((__a)[0]))
#include <errno.h>
#include <linux/filter.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static struct sock_filter nlattr[] = {
  { 0000, 0, 0, 0x87654321 },
  { 0x01, 0, 0, 0x0000002a },
  { 0x20, 0, 0, 0xfffff00c },
  { 0x16, 0, 0, 0000000000 },
};

static struct sock_fprog bpf_nlattr = {
  .len = ARRAY_SIZE(nlattr),
  .filter = nlattr,
};

static struct sock_filter nlattr_nest[] = {
  { 0000, 0, 0, 0x87654321 },
  { 0x01, 0, 0, 0x0000002a },
  { 0x20, 0, 0, 0xfffff010 },
  { 0x16, 0, 0, 0000000000 },
};

static struct sock_fprog bpf_nlattr_nest = {
  .len = ARRAY_SIZE(nlattr_nest),
  .filter = nlattr_nest,
};

static struct sock_filter nest_rem[] = {
  { 0000, 0, 0, 0000000000 },
  { 0x01, 0, 0, 0x0000002a },
  { 0x20, 0, 0, 0xfffff010 },
  { 0x16, 0, 0, 0000000000 },
};

static struct sock_fprog bpf_nest_rem = {
  .len = ARRAY_SIZE(nest_rem),
  .filter = nest_rem,
};

static int send_receive_packet(int s[2], const void* pkt, int len)
{
  char tmp[1024];
  ssize_t ret;

  ret = send(s[1], pkt, len, 0);
  if (ret != len) {
    return -1;
  }

  ret = recv(s[0], tmp, len, MSG_DONTWAIT);
  if (ret < 0 && errno == EAGAIN)
    return 0;

  return 1;
}

int main()
{
  struct nlattr chkrem[2] = {
    [0] = {
        .nla_len = 0xfff0,
        .nla_type = 0,
    },
    [1] = {
        .nla_len = sizeof(struct nlattr),
        .nla_type = 42,
    },
  };
  __u16 chksz = 0xfefe;
  int s[2], ret;

  ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, s);
  if (ret) {
    return -1;
  }

  ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
      &bpf_nlattr, sizeof(bpf_nlattr));
  if (ret < 0) {
    return -1;
  }

  ret = send_receive_packet(s, &chksz, sizeof(chksz));
  if (ret) {
    ret = 113;
    goto out;
  }

  ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
      &bpf_nlattr_nest, sizeof(bpf_nlattr_nest));
  if (ret < 0) {
    return -1;
  }

  ret = send_receive_packet(s, &chksz, sizeof(chksz));
  if (ret) {
    ret = 113;
    goto out;
  }

  ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
      &bpf_nest_rem, sizeof(bpf_nest_rem));
  if (ret < 0) {
    return -1;
  }

  ret = send_receive_packet(s, chkrem, sizeof(chkrem));
  if(ret){
    ret = 113;
  }

out:
  return ret;
}