Exemplo n.º 1
0
/*
 * returns: -1 - address not found, 0 - addr is ok, 1 - addr is tentative
 */
int is_addr_tentative(char * ifacename, int iface, char * addr)
{
    char buf[256];
    char packed1[16];
    char packed2[16];
    struct rtattr * rta_tb[IFA_MAX+1];
    struct nlmsg_list *ainfo = NULL;
    struct nlmsg_list *head = NULL;
    struct rtnl_handle rth;

    int tentative = LOWLEVEL_TENTATIVE_DONT_KNOW;

    inet_pton6(addr,packed1);

    rtnl_open(&rth, 0);

    /* 2nd attribute: AF_UNSPEC, AF_INET, AF_INET6 */
    /* rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK); */
    rtnl_wilddump_request(&rth, AF_INET6, RTM_GETADDR);
    rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL);

    head = ainfo;
    while (ainfo) {
	struct nlmsghdr *n = &ainfo->h;
	struct ifaddrmsg *ifa = NLMSG_DATA(n);
	
	memset(rta_tb, 0, sizeof(*rta_tb));
	
	if (ifa->ifa_index == iface && ifa->ifa_family==AF_INET6) {
	    parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
	    if (!rta_tb[IFA_LOCAL])   rta_tb[IFA_LOCAL]   = rta_tb[IFA_ADDRESS];
	    if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
	    
	    inet_ntop6(RTA_DATA(rta_tb[IFA_LOCAL]), buf /*, sizeof(buf)*/);
	    memcpy(packed2,RTA_DATA(rta_tb[IFA_LOCAL]),16);

	    /* print_packed(packed1); printf(" "); print_packed(packed2); printf("\n"); */

	    /* is this addr which are we looking for? */
	    if (!memcmp(packed1,packed2,16) ) {
		if (ifa->ifa_flags & IFA_F_TENTATIVE)
		    tentative = LOWLEVEL_TENTATIVE_YES;
		else
		    tentative = LOWLEVEL_TENTATIVE_NO;
	    }
	}
	ainfo = ainfo->next;
    }

    /* now delete list */
    while (head) {
	ainfo = head;
	head = head->next;
	free(ainfo);
    }
    
    rtnl_close(&rth);

    return tentative;
}
Exemplo n.º 2
0
static void load_info(void)
{
	struct ifstat_ent *db, *n;
	struct rtnl_handle rth;

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

	if (rtnl_dump_filter(&rth, get_netstat_nlmsg, NULL, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	rtnl_close(&rth);

	db = kern_db;
	kern_db = NULL;

	while (db) {
		n = db;
		db = db->next;
		n->next = kern_db;
		kern_db = n;
	}
}
Exemplo n.º 3
0
static int iprule_flush(int argc, char **argv)
{
	int af = preferred_family;

#ifdef HTC_IPRULE_DEBUG
	ALOGD("[IPROUTE2]iprule_flush +");
#endif

	if (af == AF_UNSPEC)
		af = AF_INET;

	if (argc > 0) {
		fprintf(stderr, "\"ip rule flush\" does not allow arguments\n");
		return -1;
	}

	if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
		perror("Cannot send dump request");
		return 1;
	}

	if (rtnl_dump_filter(&rth, flush_rule, NULL) < 0) {
		fprintf(stderr, "Flush terminated\n");
		return 1;
	}

#ifdef HTC_IPRULE_DEBUG
	ALOGD("[IPROUTE2]iprule_flush -");
#endif

	return 0;
}
Exemplo n.º 4
0
struct rt_entry * rt_fetch(struct rt_entry *r)
{
	struct rtnl_handle rth;

	// open netlink socket of NETLINK_ROUTE
	if (rtnl_open(&rth, 0) < 0) {
		printf("Can not initialize netlink interface...\n");
		return NULL;
	}

	ll_init_map(&rth);

	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETROUTE) < 0) {
		printf("Cannot send dump request\n");
		close(rth.fd);
		return NULL;
	}

	if (rtnl_dump_filter(&rth, rt_filter, r, NULL, NULL) < 0) {
		printf("Dump terminated.\n");
		close(rth.fd);
		return NULL;
	}

	close(rth.fd);
	return r;
}
Exemplo n.º 5
0
/****************************************************************
 NAME	: ipaddr_list				00/06/02 20:02:23
 AIM	: 
 REMARK	:
****************************************************************/
int ipaddr_list( int ifindex, uint32_t *array, int max_elem )
{
	struct rtnl_handle	rth;
	iplist_ctx	ctx;
	/* init the struct */
	ctx.ifindex	= ifindex;
	ctx.addr	= array;
	ctx.max_elem	= max_elem;
	ctx.nb_elem	= 0;
	/* open the rtnetlink socket */
	if( rtnl_open( &rth, 0) )
		return -1;
	/* send the request */
	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETADDR) < 0) {
		perror("Cannot send dump request");
		return -1;
	}
	/* parse the answer */
	if (rtnl_dump_filter(&rth, get_addrinfo, &ctx, NULL, NULL) < 0) {
		fprintf(stderr, "Flush terminated\n");
		exit(1);
	}
	
	/* to close the clocket */
 	rtnl_close( &rth );
	
	return ctx.nb_elem;
}
Exemplo n.º 6
0
/*
 * rule_flush_table_range: deletes all the rules which lookup the table X.
 * The table X is any table in the range of `a' <= X <= `b'.
 */
int
rule_flush_table_range(int family, int a, int b)
{
	struct rtnl_handle rth;
	int arg[2];

	if (rtnl_open(&rth, 0) < 0)
		return 1;

	if (rtnl_wilddump_request(&rth, family, RTM_GETRULE) < 0) {
		error("Cannot dump the routing rule table");
		return -1;
	}

	arg[0] = a;
	arg[1] = b;
	if (rtnl_dump_filter
		(&rth, rule_flush_table_range_filter, arg, NULL, NULL) < 0) {
		error("Flush terminated");
		return -1;
	}

	rtnl_close(&rth);

	return 0;
}
Exemplo n.º 7
0
static int do_show(int argc, char **argv)
{
	struct {
		struct nlmsghdr		n;
		struct netconfmsg	ncm;
		char			buf[1024];
	} req;

	ipnetconf_reset_filter(0);
	filter.family = preferred_family;
	if (filter.family == AF_UNSPEC)
		filter.family = AF_INET;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			filter.ifindex = ll_name_to_index(*argv);
			if (filter.ifindex <= 0) {
				fprintf(stderr, "Device \"%s\" does not exist.\n",
					*argv);
				return -1;
			}
		}
		argv++; argc--;
	}

	ll_init_map(&rth);
	if (filter.ifindex) {
		memset(&req, 0, sizeof(req));
		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg));
		req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
		req.n.nlmsg_type = RTM_GETNETCONF;
		req.ncm.ncm_family = filter.family;
		if (filter.ifindex)
			addattr_l(&req.n, sizeof(req), NETCONFA_IFINDEX,
				  &filter.ifindex, sizeof(filter.ifindex));

		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
			perror("Can not send request");
			exit(1);
		}
		rtnl_listen(&rth, print_netconf, stdout);
	} else {
dump:
		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNETCONF) < 0) {
			perror("Cannot send dump request");
			exit(1);
		}
		if (rtnl_dump_filter(&rth, print_netconf2, stdout) < 0) {
			fprintf(stderr, "Dump terminated\n");
			exit(1);
		}
		if (preferred_family == AF_UNSPEC) {
			preferred_family = AF_INET6;
			filter.family = AF_INET6;
			goto dump;
		}
	}
	return 0;
}
Exemplo n.º 8
0
static int iprule_list_or_save(int argc, char **argv, int save)
{
	rtnl_filter_t filter = print_rule;
	int af = preferred_family;

	if (af == AF_UNSPEC)
		af = AF_INET;

	if (argc > 0) {
		fprintf(stderr, "\"ip rule %s\" does not take any arguments.\n",
				save ? "save" : "show");
		return -1;
	}

	if (save) {
		if (save_rule_prep())
			return -1;
		filter = save_rule;
	}

	if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
		perror("Cannot send dump request");
		return 1;
	}

	if (rtnl_dump_filter(&rth, filter, stdout) < 0) {
		fprintf(stderr, "Dump terminated\n");
		return 1;
	}

	return 0;
}
Exemplo n.º 9
0
Arquivo: fdb.c Projeto: SamB/iproute2
static int fdb_show(int argc, char **argv)
{
	char *filter_dev = NULL;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if (filter_dev)
				duparg("dev", *argv);
			filter_dev = *argv;
		}
		argc--; argv++;
	}

	if (filter_dev) {
		filter_index = if_nametoindex(filter_dev);
		if (filter_index == 0) {
			fprintf(stderr, "Cannot find device \"%s\"\n",
				filter_dev);
			return -1;
		}
	}

	if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETNEIGH) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

	if (rtnl_dump_filter(&rth, print_fdb, stdout) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	return 0;
}
Exemplo n.º 10
0
void neigh_flush_table(char *iface)
{
	struct rtnl_handle rth;
	char flushb[4096-512];

   DEBUG_MSG("neigh_flush_table %s", iface);
   
	memset(&filter, 0, sizeof(filter));

   filter.state = ~0;
   filter.family = AF_INET;

   /* flush all but permanent and noarp */
    
	filter.state = ~(NUD_PERMANENT|NUD_NOARP);

   /* open the netlink socket */
   
	if (rtnl_open(&rth, 0) < 0)
		ERROR_MSG("rtnl_open()");

	ll_init_map(&rth);

   /* fill the device data */
   
   if ((filter.index = ll_name_to_index(iface)) == 0)
      ERROR_MSG("ll_name_to_index(%s)", iface);


	filter.flushb = flushb;
	filter.flushp = 0;
	filter.flushe = sizeof(flushb);
	filter.rth = &rth;
	filter.state &= ~NUD_FAILED;

	for (;;) {
		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNEIGH) < 0) 
         ERROR_MSG("rtnl_wilddump_request()");
      
		filter.flushed = 0;
		
      /* 
       * count how many neigh are to be flushed 
       * and prepare the data
       */
      
      if (rtnl_dump_filter(&rth, count_neigh, stdout, NULL, NULL) < 0) 
         ERROR_MSG("rtnl_dump_filter()");
      
		if (filter.flushed == 0)
         return;
		
		if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0)
			ERROR_MSG("rtnl_send()");
      
      filter.flushp = 0;
 
      DEBUG_MSG("*** deleting %d entries ***", filter.flushed);
	}
}
int iprule_list(int argc, char **argv)
{
	struct rtnl_handle rth;
	int af = preferred_family;

	if (af == AF_UNSPEC)
		af = AF_INET;

	if (argc > 0) {
		fprintf(stderr, "\"ip rule show\" does not take any arguments.\n");
		return -1;
	}

	if (rtnl_open(&rth, 0) < 0)
		return 1;

	if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
		perror("Cannot send dump request");
		return 1;
	}

	if (rtnl_dump_filter(&rth, print_rule, stdout, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		return 1;
	}

	return 0;
}
Exemplo n.º 12
0
static void load_initial_table(void)
{
	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH) < 0) {
		perror("dump request failed");
		exit(1);
	}
		
}
Exemplo n.º 13
0
void TunManager::probe() {
  std::lock_guard<std::mutex> lock(mutex_);
  stop();                       // stop all interfaces
  intfs_.clear();               // clear all interface info
  auto ret = rtnl_wilddump_request(&rth_, AF_UNSPEC, RTM_GETLINK);
  sysCheckError(ret, "Cannot send RTM_GETLINK request");
  ret = rtnl_dump_filter(&rth_, getLinkRespParser, this);
  sysCheckError(ret, "Cannot process RTM_GETLINK response");
  ret = rtnl_wilddump_request(&rth_, AF_UNSPEC, RTM_GETADDR);
  sysCheckError(ret, "Cannot send RTM_GETADDR request");
  ret = rtnl_dump_filter(&rth_, getAddrRespParser, this);
  sysCheckError(ret, "Cannot process RTM_GETADDR response");
  // Bring up all interfaces. Interfaces could be already up.
  for (const auto& intf : intfs_) {
    bringupIntf(intf.second->getName(), intf.second->getIfIndex());
  }
  start();
}
Exemplo n.º 14
0
int ll_init_map(struct rtnl_handle *rth)
{
	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
		bb_perror_msg_and_die("cannot send dump request");
	}

	if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
		bb_error_msg_and_die("dump terminated");
	}
	return 0;
}
Exemplo n.º 15
0
int ll_init_map(struct rtnl_handle *rth)
{
	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
//		perror("Cannot send dump request");
		exit(1);
	}

	if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
//		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}
	return 0;
}
Exemplo n.º 16
0
/* Based on iproute2/ip/iproute.c:iproute_list_flush_or_save. */
static int dump(int tbl_id)
{
	reset_filter();
	filter.tb = tbl_id;

	if (rtnl_wilddump_request(&rth, AF_XIA, RTM_GETROUTE) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}
	if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}
	return 0;
}
Exemplo n.º 17
0
/* XXX This should become a function in a library, there're very
 * little variance of this repeated code instances
 */
static int showneighs(void)
{
	reset_filter();

	if (rtnl_wilddump_request(&rth, AF_XIA, RTM_GETROUTE) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}
	if (rtnl_dump_filter(&rth, print_neigh, stdout, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	return 0;
}
Exemplo n.º 18
0
static PyObject* pyrtnl_wilddump_request(PyObject* obj, PyObject* args)
{
  PyRtnlObject* self = (PyRtnlObject*)obj;
  int family, type;

  if (!PyArg_ParseTuple(args, "ii", &family, &type))
    return NULL;

  if (rtnl_wilddump_request(&self->rth, family, type) < 0) {
    PyErr_SetString(PyExc_IOError, "could not send dump request");
    return NULL;
  }

  Py_INCREF(Py_None);
  return Py_None;
}
Exemplo n.º 19
0
void list(void) {
	struct rtnl_handle rth;

	if (rtnl_open(&rth,0)) {
		perror("Cannot open rtnetlink");
		return;
	}
	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		return;
	}

	if (rtnl_dump_filter(&rth, print_link, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		return;
	}
	rtnl_close(&rth);
}
Exemplo n.º 20
0
int init_bridge_ops(void)
{
    if(rtnl_open(&rth, RTMGRP_LINK) < 0)
    {
        fprintf(stderr, "Couldn't open rtnl socket for monitoring\n");
        return -1;
    }

    if(rtnl_open(&rth_state, 0) < 0)
    {
        fprintf(stderr, "Couldn't open rtnl socket for setting state\n");
        return -1;
    }

    if(rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0)
    {
        //fprintf(stderr, "Cannot send dump request: %m\n");
        fprintf(stderr, "Cannot send dump request: %s\n", strerror(errno));
        return -1;
    }
    if(rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0)
    {
        fprintf(stderr, "Dump terminated\n");
        return -1;
    }
    if(fcntl(rth.fd, F_SETFL, O_NONBLOCK) < 0)
    {
        //fprintf(stderr, "Error setting O_NONBLOCK: %m\n");
        fprintf(stderr, "Error setting O_NONBLOCK: %s\n", strerror(errno));
        return -1;
    }

    br_handler.fd = rth.fd;
    br_handler.arg = NULL;
    br_handler.handler = br_ev_handler;

    if(add_epoll(&br_handler) < 0){
        return -1;
	}

    return 0;
}
Exemplo n.º 21
0
int do_show_ip_route(struct params* params)
{
	struct rtnl_handle rth;
	if (rtnl_open(&rth,0) < 0) {
		printf("Could not open netlink socket\n");
		return -1;
	}

	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) {
		printf("Cannot send dump request");
		return -1;
	}

	/*if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
		printf("Dump terminated\n");
		return -1;
	}*/
	
	return 0;
}
int rtnl_iterate(int proto, int type, rtnl_filter_t func, void *extarg)
{
	struct rtnl_handle rth;

	if (rtnl_open_byproto(&rth, 0, proto) < 0)
		return -1;

	if (rtnl_wilddump_request(&rth, AF_INET6, type) < 0) {
		rtnl_close(&rth);
		return -1;
	}

	if (rtnl_dump_filter(&rth, func, extarg, NULL, NULL) < 0) {
		rtnl_close(&rth);
		return -1;
	}

	rtnl_close(&rth);

	return 0;
}
Exemplo n.º 23
0
int ll_init_map(struct rtnl_handle *rth)
{
	static int initialized;

	if (initialized)
		return 0;

	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

	if (rtnl_dump_filter(rth, ll_remember_index, NULL, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	initialized = 1;

	return 0;
}
Exemplo n.º 24
0
int main(int argc, char *argv[])
{
    int i;
    int preferred_family = AF_PACKET;

    if (rtnl_open(&my_rth, 0) < 0) {
        fprintf(stderr, "Cannot open rtnetlink\n");
        return -1;
    }

    if (rtnl_wilddump_request(&my_rth, preferred_family, RTM_GETLINK) < 0) {
        perror("Cannot send dump request");
        exit(1);
    }

    if (rtnl_dump_filter(&my_rth, my_print_linkinfo, stdout, NULL, NULL) < 0) {
        fprintf(stderr, "Dump terminated\n");
        exit(1);
    }

    exit(0);
}
Exemplo n.º 25
0
/*
 * route_get_exact_prefix: it dumps the routing table and search for a route
 * which has the prefix equal to `prefix', if it is found its destination
 * address is stored in `dst' and its interface name in `dev_name' (which must
 * be IFNAMSIZ big).
 */
int
route_get_exact_prefix_dst(inet_prefix prefix, inet_prefix * dst,
						   char *dev_name)
{
	int do_ipv6 = AF_UNSPEC;
	struct rtnl_handle rth;
	char dst_data[sizeof(inet_prefix) + IFNAMSIZ];

	route_reset_filter();
	filter.tb = RT_TABLE_MAIN;

	filter.mdst = prefix;
	filter.rdst = filter.mdst;

	if (do_ipv6 == AF_UNSPEC && filter.tb)
		do_ipv6 = AF_INET;

	if (rtnl_open(&rth, 0) < 0)
		return -1;

	ll_init_map(&rth);

	if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
		error(ERROR_MSG "Cannot send dump request" ERROR_POS);
		return -1;
	}

	setzero(dst_data, sizeof(dst_data));
	if (rtnl_dump_filter(&rth, route_get_gw, dst_data, NULL, NULL) < 0) {
		debug(DBG_NORMAL, ERROR_MSG "Dump terminated" ERROR_POS);
		return -1;
	}
	inet_copy(dst, (inet_prefix *) dst_data);
	memcpy(dev_name, dst_data + sizeof(inet_prefix), IFNAMSIZ);

	rtnl_close(&rth);

	return 0;
}
Exemplo n.º 26
0
int Label_show(int argc, char **argv) {
    int af = preferred_family;

    if (af == AF_UNSPEC)
        af = AF_INET6;

    if (argc > 0) {
        fprintf(stderr, "\"label show\" does not take any arguments.\n");
        return -1;
    }

    if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
        perror("Can not send dump request");
        return 1;
    }

    if (rtnl_dump_filter(&rth, print_addrlabel, stdout, NULL, NULL) < 0) {
        fprintf(stderr, "Dump terminated\n");
        return 1;
    }

    return 0;
}
Exemplo n.º 27
0
static int ipntable_show(int argc, char **argv)
{
	ipntable_reset_filter();

	filter.family = preferred_family;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();

			if (strcmp("none", *argv) == 0)
				filter.index = NONE_DEV;
			else if ((filter.index = ll_name_to_index(*argv)) == 0)
				invarg("\"DEV\" is invalid", *argv);
		} else if (strcmp(*argv, "name") == 0) {
			NEXT_ARG();

			strncpy(filter.name, *argv, sizeof(filter.name));
		} else
			invarg("unknown", *argv);

		argc--; argv++;
	}

	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETNEIGHTBL) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

	if (rtnl_dump_filter(&rth, print_ntable, stdout, NULL, NULL) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	return 0;
}
static int ipaddrlabel_flush(int argc, char **argv)
{
	int af = preferred_family;

	if (af == AF_UNSPEC)
		af = AF_INET6;

	if (argc > 0) {
		fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n");
		return -1;
	}

	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
		perror("Cannot send dump request");
		return 1;
	}

	if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) {
		fprintf(stderr, "Flush terminated\n");
		return 1;
	}

	return 0;
}
Exemplo n.º 29
0
static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall)
{
	char *selp = NULL;
	struct rtnl_handle rth;

	if (argc > 0)
		filter.use = 1;
	filter.xpinfo.sel.family = preferred_family;

	while (argc > 0) {
		if (strcmp(*argv, "dir") == 0) {
			NEXT_ARG();
			xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv);

			filter.dir_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&filter.xpinfo.index, *argv, 0))
				invarg("\"INDEX\" is invalid", *argv);

			filter.index_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "ptype") == 0) {
			NEXT_ARG();
			xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv);

			filter.ptype_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "action") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "allow") == 0)
				filter.xpinfo.action = XFRM_POLICY_ALLOW;
			else if (strcmp(*argv, "block") == 0)
				filter.xpinfo.action = XFRM_POLICY_BLOCK;
			else
				invarg("\"ACTION\" is invalid\n", *argv);

			filter.action_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "priority") == 0) {
			NEXT_ARG();
			if (get_u32(&filter.xpinfo.priority, *argv, 0))
				invarg("\"PRIORITY\" is invalid", *argv);

			filter.priority_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "flag") == 0) {
			NEXT_ARG();
			xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc,
					       &argv);

			filter.policy_flags_mask = XFRM_FILTER_MASK_FULL;

		} else {
			if (selp)
				invarg("unknown", *argv);
			selp = *argv;

			xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv);
			if (preferred_family == AF_UNSPEC)
				preferred_family = filter.xpinfo.sel.family;

		}

		argc--; argv++;
	}

	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
		exit(1);

	if (deleteall) {
		struct xfrm_buffer xb;
		char buf[NLMSG_DELETEALL_BUF_SIZE];
		int i;

		xb.buf = buf;
		xb.size = sizeof(buf);
		xb.rth = &rth;

		for (i = 0; ; i++) {
			xb.offset = 0;
			xb.nlmsg_count = 0;

			if (show_stats > 1)
				fprintf(stderr, "Delete-all round = %d\n", i);

			if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
				perror("Cannot send dump request");
				exit(1);
			}

			if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) {
				fprintf(stderr, "Delete-all terminated\n");
				exit(1);
			}
			if (xb.nlmsg_count == 0) {
				if (show_stats > 1)
					fprintf(stderr, "Delete-all completed\n");
				break;
			}

			if (rtnl_send(&rth, xb.buf, xb.offset) < 0) {
				perror("Failed to send delete-all request\n");
				exit(1);
			}
			if (show_stats > 1)
				fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);

			xb.offset = 0;
			xb.nlmsg_count = 0;
		}
	} else {
		if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
			perror("Cannot send dump request");
			exit(1);
		}

		if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) {
			fprintf(stderr, "Dump terminated\n");
			exit(1);
		}
	}

	rtnl_close(&rth);

	exit(0);
}
extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
{
	const char *option[] = { "to", "scope", "up", "label", "dev", 0 };
	struct nlmsg_list *linfo = NULL;
	struct nlmsg_list *ainfo = NULL;
	struct nlmsg_list *l;
	struct rtnl_handle rth;
	char *filter_dev = NULL;
	int no_link = 0;

	ipaddr_reset_filter(oneline);
	filter.showqueue = 1;

	if (filter.family == AF_UNSPEC)
		filter.family = preferred_family;

	if (flush) {
		if (argc <= 0) {
			fprintf(stderr, "Flush requires arguments.\n");
			return -1;
		}
		if (filter.family == AF_PACKET) {
			fprintf(stderr, "Cannot flush link addresses.\n");
			return -1;
		}
	}

	while (argc > 0) {
		const unsigned short option_num = compare_string_array(option, *argv);
		switch (option_num) {
			case 0: /* to */
				NEXT_ARG();
				get_prefix(&filter.pfx, *argv, filter.family);
				if (filter.family == AF_UNSPEC) {
					filter.family = filter.pfx.family;
				}
				break;
			case 1: /* scope */
			{
				int scope = 0;
				NEXT_ARG();
				filter.scopemask = -1;
				if (rtnl_rtscope_a2n(&scope, *argv)) {
					if (strcmp(*argv, "all") != 0) {
						invarg("invalid \"scope\"\n", *argv);
					}
					scope = RT_SCOPE_NOWHERE;
					filter.scopemask = 0;
				}
				filter.scope = scope;
				break;
			}
			case 2: /* up */
				filter.up = 1;
				break;
			case 3: /* label */
				NEXT_ARG();
				filter.label = *argv;
				break;
			case 4: /* dev */
				NEXT_ARG();
			default:
				if (filter_dev) {
					duparg2("dev", *argv);
				}
				filter_dev = *argv;
		}
		argv++;
		argc--;
	}

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
		bb_perror_msg_and_die("Cannot send dump request");
	}

	if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
		bb_error_msg_and_die("Dump terminated");
	}

	if (filter_dev) {
		filter.ifindex = ll_name_to_index(filter_dev);
		if (filter.ifindex <= 0) {
			bb_error_msg("Device \"%s\" does not exist.", filter_dev);
			return -1;
		}
	}

	if (flush) {
		int round = 0;
		char flushb[4096-512];

		filter.flushb = flushb;
		filter.flushp = 0;
		filter.flushe = sizeof(flushb);
		filter.rth = &rth;

		for (;;) {
			if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
				perror("Cannot send dump request");
				exit(1);
			}
			filter.flushed = 0;
			if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
				fprintf(stderr, "Flush terminated\n");
				exit(1);
			}
			if (filter.flushed == 0) {
#if 0
				if (round == 0)
					fprintf(stderr, "Nothing to flush.\n");
#endif
				fflush(stdout);
				return 0;
			}
			round++;
			if (flush_update() < 0)
				exit(1);
		}
	}

	if (filter.family != AF_PACKET) {
		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
			bb_perror_msg_and_die("Cannot send dump request");
		}

		if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
			bb_error_msg_and_die("Dump terminated");
		}
	}


	if (filter.family && filter.family != AF_PACKET) {
		struct nlmsg_list **lp;
		lp=&linfo;

		if (filter.oneline)
			no_link = 1;

		while ((l=*lp)!=NULL) {
			int ok = 0;
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			struct nlmsg_list *a;

			for (a=ainfo; a; a=a->next) {
				struct nlmsghdr *n = &a->h;
				struct ifaddrmsg *ifa = NLMSG_DATA(n);

				if (ifa->ifa_index != ifi->ifi_index ||
				    (filter.family && filter.family != ifa->ifa_family))
					continue;
				if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
					continue;
				if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
					continue;
				if (filter.pfx.family || filter.label) {
					struct rtattr *tb[IFA_MAX+1];
					memset(tb, 0, sizeof(tb));
					parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
					if (!tb[IFA_LOCAL])
						tb[IFA_LOCAL] = tb[IFA_ADDRESS];

					if (filter.pfx.family && tb[IFA_LOCAL]) {
						inet_prefix dst;
						memset(&dst, 0, sizeof(dst));
						dst.family = ifa->ifa_family;
						memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
						if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
							continue;
					}
					if (filter.label) {
						SPRINT_BUF(b1);
						const char *label;
						if (tb[IFA_LABEL])
							label = RTA_DATA(tb[IFA_LABEL]);
						else
							label = ll_idx_n2a(ifa->ifa_index, b1);
						if (fnmatch(filter.label, label, 0) != 0)
							continue;
					}
				}

				ok = 1;
				break;
			}
			if (!ok)
				*lp = l->next;
			else
				lp = &l->next;
		}
	}

	for (l=linfo; l; l = l->next) {
		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			if (filter.family != AF_PACKET)
				print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
		}
		fflush(stdout);
	}

	exit(0);
}