Ejemplo n.º 1
0
static int ipnetns_have_nsid(void)
{
	struct {
		struct nlmsghdr n;
		struct rtgenmsg g;
		char            buf[1024];
	} req;
	int fd;

	if (have_rtnl_getnsid < 0) {
		memset(&req, 0, sizeof(req));
		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETNSID;
		req.g.rtgen_family = AF_UNSPEC;

		fd = open("/proc/self/ns/net", O_RDONLY);
		if (fd < 0) {
			perror("open(\"/proc/self/ns/net\")");
			exit(1);
		}

		addattr32(&req.n, 1024, NETNSA_FD, fd);

		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
			perror("request send failed");
			exit(1);
		}
		rtnl_listen(&rth, ipnetns_accept_msg, NULL);
		close(fd);
	}

	return have_rtnl_getnsid;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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);
	}
}
Ejemplo n.º 4
0
static int
iplink_have_newlink(void)                                                        
{
    struct iplink_req req;
    struct softgred_config *cfg = softgred_config_ref();

    if (have_rtnl_newlink < 0)
    {
        memset(&req, 0, sizeof(req));

        req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
        req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
        req.n.nlmsg_type = RTM_NEWLINK;
        req.i.ifi_family = AF_UNSPEC;

        if (rtnl_send(&cfg->rth, &req.n, req.n.nlmsg_len) < 0)
        {
            perror("request send failed");
            exit(1);
        }

        rtnl_listen(&cfg->rth, accept_msg, NULL);
    }
    return have_rtnl_newlink;
}
Ejemplo n.º 5
0
/*
 * All the code below this point is ripped from iproute2/iproute.c
 * written by Alexey Kuznetsov, <*****@*****.**>.
 *
 * Modified lightly
 */
static int flush_update(void)
{                       
        if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
                error("Failed to send flush request: %s", strerror(errno));
                return -1;
        }               
        filter.flushp = 0;
        return 0;
}
static int flush_update(void)
{
	if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
		perror("Failed to send flush request\n");
		return -1;
	}
	filter.flushp = 0;
	return 0;
}
Ejemplo n.º 7
0
static int flush_update(void)
{
	if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
		bb_perror_msg("failed to send flush request");
		return -1;
	}
	filter.flushp = 0;
	return 0;
}
Ejemplo n.º 8
0
static int flush_update(void)
{
	if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
		bb_perror_msg("can't send flush request");
		return -1;
	}
	G_filter.flushp = 0;
	return 0;
}
Ejemplo n.º 9
0
int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
{
	struct {
		struct nlmsghdr nlh;
		struct rtgenmsg g;
	} req;

	req.nlh.nlmsg_len = sizeof(req);
	req.nlh.nlmsg_type = type;
	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
	req.nlh.nlmsg_pid = 0;
	req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
	req.g.rtgen_family = family;

	return rtnl_send(rth, (void*)&req, sizeof(req));
}
Ejemplo n.º 10
0
static int iplink_have_newlink(void)
{
	struct {
		struct nlmsghdr		n;
		struct ifinfomsg	i;
		char			buf[1024];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
		.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		.n.nlmsg_type = RTM_NEWLINK,
		.i.ifi_family = AF_UNSPEC,
	};

	if (have_rtnl_newlink < 0) {
		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
			perror("request send failed");
			exit(1);
		}
		rtnl_listen(&rth, accept_msg, NULL);
	}
	return have_rtnl_newlink;
}
#else /* IPLINK_IOCTL_COMPAT */
static int iplink_have_newlink(void)
{
	return 1;
}
#endif /* ! IPLINK_IOCTL_COMPAT */

static int nl_get_ll_addr_len(unsigned int dev_index)
{
	int len;
	struct iplink_req req = {
		.n = {
			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
			.nlmsg_type = RTM_GETLINK,
			.nlmsg_flags = NLM_F_REQUEST
		},
		.i = {
			.ifi_family = preferred_family,
			.ifi_index = dev_index,
		}
	};
Ejemplo n.º 11
0
static int iplink_have_newlink(void)
{
	struct {
		struct nlmsghdr		n;
		struct ifinfomsg	i;
		char			buf[1024];
	} req;

	if (have_rtnl_newlink < 0) {
		memset(&req, 0, sizeof(req));

		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
		req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
		req.n.nlmsg_type = RTM_NEWLINK;
		req.i.ifi_family = AF_UNSPEC;

		rtnl_send(&rth, &req.n, req.n.nlmsg_len);
		rtnl_listen(&rth, accept_msg, NULL);
	}
	return have_rtnl_newlink;
}
Ejemplo n.º 12
0
static int get_tunnel(struct l2tp_data *p)
{
	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
		     L2TP_CMD_TUNNEL_GET,
		     NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);

	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;

	if (p->config.tunnel_id)
		addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);

	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
		return -2;

	if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}

	return 0;
}
Ejemplo n.º 13
0
int mpls_list(int cmd,int argc, char **argv)
{
	struct genlmsghdr *ghdr;
	struct rtnl_handle rth;

	struct {
		struct nlmsghdr		n;
		char			buf[4096];
	} req;

	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
		fprintf (stderr, "Error opening nl socket\n");
		//exit(-1);
		return -1;
	}
	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
	req.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
	req.n.nlmsg_type = PF_MPLS;
	req.n.nlmsg_seq = rth.dump = ++rth.seq;

	ghdr = NLMSG_DATA(&req.n);
	ghdr->cmd = cmd;
	
	if (rtnl_send(&rth, (const char *)&req.n, req.n.nlmsg_len) < 0) {
		perror("Cannot send dump request");
		//exit(1);
		return 1;
	}

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

	return 0;
}
Ejemplo n.º 14
0
static int do_list(int argc, char **argv)
{
	ILA_REQUEST(req, 1024, ILA_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);

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

	if (rtnl_send(&genl_rth, (void *)&req, req.n.nlmsg_len) < 0) {
		perror("Cannot send dump request");
		exit(1);
	}

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

	return 0;
}
Ejemplo n.º 15
0
int count_neigh(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct ndmsg *r = NLMSG_DATA(n);

	if (filter.flushb && n->nlmsg_type != RTM_NEWNEIGH)
		return 0;

	if (filter.family && filter.family != r->ndm_family)
		return 0;
   
	if (filter.index && filter.index != r->ndm_ifindex)
		return 0;
	
   if (!(filter.state & r->ndm_state) &&
	    (r->ndm_state || !(filter.state & 0x100)) &&
             (r->ndm_family != AF_DECnet))
		return 0;
   
	if (filter.flushb) {
		struct nlmsghdr *fn;
		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
		   if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0)
            return -1;
      
         filter.flushp = 0;
		}
		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
		memcpy(fn, n, n->nlmsg_len);
		fn->nlmsg_type = RTM_DELNEIGH;
		fn->nlmsg_flags = NLM_F_REQUEST;
		fn->nlmsg_seq = ++filter.rth->seq;
		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
		filter.flushed++;
		
	}

	return 0;
}
Ejemplo n.º 16
0
int respond_to_kernel(int ifindex, __u32 addr, char *lla, int llalen)
{
	struct {
		struct nlmsghdr 	n;
		struct ndmsg 		ndm;
		char   			buf[256];
	} req;

	memset(&req.n, 0, sizeof(req.n));
	memset(&req.ndm, 0, sizeof(req.ndm));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_NEWNEIGH;
	req.ndm.ndm_family = AF_INET;
	req.ndm.ndm_state = NUD_STALE;
	req.ndm.ndm_ifindex = ifindex;
	req.ndm.ndm_type = RTN_UNICAST;

	addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
	addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
	return rtnl_send(&rth, (char*)&req, req.n.nlmsg_len) <= 0;
}
Ejemplo n.º 17
0
static int do_dump(int ifindex)
{
	MACSEC_GENL_REQ(req, MACSEC_BUFLEN, MACSEC_CMD_GET_TXSC,
			NLM_F_REQUEST | NLM_F_DUMP);

	memset(&filter, 0, sizeof(filter));
	filter.ifindex = ifindex;

	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0) {
		perror("Failed to send dump request");
		exit(1);
	}

	new_json_obj(json);
	if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) {
		delete_json_obj();
		fprintf(stderr, "Dump terminated\n");
		exit(1);
	}
	delete_json_obj();

	return 0;
}
Ejemplo n.º 18
0
static int send_probe(int ifindex, __u32 addr)
{
	struct ifreq ifr = { .ifr_ifindex = ifindex };
	struct sockaddr_in dst = {
		.sin_family = AF_INET,
		.sin_port = htons(1025),
		.sin_addr.s_addr = addr,
	};
	socklen_t len;
	unsigned char buf[256];
	struct arphdr *ah = (struct arphdr *)buf;
	unsigned char *p = (unsigned char *)(ah+1);
	struct sockaddr_ll sll = {
		.sll_family = AF_PACKET,
		.sll_ifindex = ifindex,
		.sll_protocol = htons(ETH_P_ARP),
	};

	if (ioctl(udp_sock, SIOCGIFNAME, &ifr))
		return -1;
	if (ioctl(udp_sock, SIOCGIFHWADDR, &ifr))
		return -1;
	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
		return -1;
	if (setsockopt(udp_sock, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, strlen(ifr.ifr_name)+1) < 0)
		return -1;

	if (connect(udp_sock, (struct sockaddr *)&dst, sizeof(dst)) < 0)
		return -1;
	len = sizeof(dst);
	if (getsockname(udp_sock, (struct sockaddr *)&dst, &len) < 0)
		return -1;

	ah->ar_hrd = htons(ifr.ifr_hwaddr.sa_family);
	ah->ar_pro = htons(ETH_P_IP);
	ah->ar_hln = 6;
	ah->ar_pln = 4;
	ah->ar_op  = htons(ARPOP_REQUEST);

	memcpy(p, ifr.ifr_hwaddr.sa_data, ah->ar_hln);
	p += ah->ar_hln;

	memcpy(p, &dst.sin_addr, 4);
	p += 4;

	memset(sll.sll_addr, 0xFF, sizeof(sll.sll_addr));
	memcpy(p, &sll.sll_addr, ah->ar_hln);
	p += ah->ar_hln;

	memcpy(p, &addr, 4);
	p += 4;

	if (sendto(pset[0].fd, buf, p-buf, 0, (struct sockaddr *)&sll, sizeof(sll)) < 0)
		return -1;
	stats.probes_sent++;
	return 0;
}

/* Be very tough on sending probes: 1 per second with burst of 3. */

static int queue_active_probe(int ifindex, __u32 addr)
{
	static struct timeval prev;
	static int buckets;
	struct timeval now;

	gettimeofday(&now, NULL);
	if (prev.tv_sec) {
		int diff = (now.tv_sec-prev.tv_sec)*1000+(now.tv_usec-prev.tv_usec)/1000;

		buckets += diff;
	} else {
		buckets = broadcast_burst;
	}
	if (buckets > broadcast_burst)
		buckets = broadcast_burst;
	if (buckets >= broadcast_rate && !send_probe(ifindex, addr)) {
		buckets -= broadcast_rate;
		prev = now;
		return 0;
	}
	stats.probes_suppressed++;
	return -1;
}

static int respond_to_kernel(int ifindex, __u32 addr, char *lla, int llalen)
{
	struct {
		struct nlmsghdr	n;
		struct ndmsg		ndm;
		char			buf[256];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
		.n.nlmsg_flags = NLM_F_REQUEST,
		.n.nlmsg_type = RTM_NEWNEIGH,
		.ndm.ndm_family = AF_INET,
		.ndm.ndm_state = NUD_STALE,
		.ndm.ndm_ifindex = ifindex,
		.ndm.ndm_type = RTN_UNICAST,
	};

	addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
	addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
	return rtnl_send(&rth, &req, req.n.nlmsg_len) <= 0;
}

static void prepare_neg_entry(__u8 *ndata, __u32 stamp)
{
	ndata[0] = 0xFF;
	ndata[1] = 0;
	ndata[2] = stamp>>24;
	ndata[3] = stamp>>16;
	ndata[4] = stamp>>8;
	ndata[5] = stamp;
}


static int do_one_request(struct nlmsghdr *n)
{
	struct ndmsg *ndm = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[NDA_MAX+1];
	struct dbkey key;
	DBT dbkey, dbdat;
	int do_acct = 0;

	if (n->nlmsg_type == NLMSG_DONE) {
		dbase->sync(dbase, 0);

		/* Now we have at least mirror of kernel db, so that
		 * may start real resolution.
		 */
		do_sysctl_adjustments();
		return 0;
	}

	if (n->nlmsg_type != RTM_GETNEIGH && n->nlmsg_type != RTM_NEWNEIGH)
		return 0;

	len -= NLMSG_LENGTH(sizeof(*ndm));
	if (len < 0)
		return -1;

	if (ndm->ndm_family != AF_INET ||
	    (ifnum && !handle_if(ndm->ndm_ifindex)) ||
	    ndm->ndm_flags ||
	    ndm->ndm_type != RTN_UNICAST ||
	    !(ndm->ndm_state&~NUD_NOARP))
		return 0;

	parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);

	if (!tb[NDA_DST])
		return 0;

	key.iface = ndm->ndm_ifindex;
	memcpy(&key.addr, RTA_DATA(tb[NDA_DST]), 4);
	dbkey.data = &key;
	dbkey.size = sizeof(key);

	if (dbase->get(dbase, &dbkey, &dbdat, 0) != 0) {
		dbdat.data = 0;
		dbdat.size = 0;
	}

	if (n->nlmsg_type == RTM_GETNEIGH) {
		if (!(n->nlmsg_flags&NLM_F_REQUEST))
			return 0;

		if (!(ndm->ndm_state&(NUD_PROBE|NUD_INCOMPLETE))) {
			stats.app_bad++;
			return 0;
		}

		if (ndm->ndm_state&NUD_PROBE) {
			/* If we get this, kernel still has some valid
			 * address, but unicast probing failed and host
			 * is either dead or changed its mac address.
			 * Kernel is going to initiate broadcast resolution.
			 * OK, we invalidate our information as well.
			 */
			if (dbdat.data && !IS_NEG(dbdat.data))
				stats.app_neg++;

			dbase->del(dbase, &dbkey, 0);
		} else {
			/* If we get this kernel does not have any information.
			 * If we have something tell this to kernel. */
			stats.app_recv++;
			if (dbdat.data && !IS_NEG(dbdat.data)) {
				stats.app_success++;
				respond_to_kernel(key.iface, key.addr, dbdat.data, dbdat.size);
				return 0;
			}

			/* Sheeit! We have nothing to tell. */
			/* If we have recent negative entry, be silent. */
			if (dbdat.data && NEG_VALID(dbdat.data)) {
				if (NEG_CNT(dbdat.data) >= active_probing) {
					stats.app_suppressed++;
					return 0;
				}
				do_acct = 1;
			}
		}

		if (active_probing &&
		    queue_active_probe(ndm->ndm_ifindex, key.addr) == 0 &&
		    do_acct) {
			NEG_CNT(dbdat.data)++;
			dbase->put(dbase, &dbkey, &dbdat, 0);
		}
	} else if (n->nlmsg_type == RTM_NEWNEIGH) {
		if (n->nlmsg_flags&NLM_F_REQUEST)
			return 0;

		if (ndm->ndm_state&NUD_FAILED) {
			/* Kernel was not able to resolve. Host is dead.
			 * Create negative entry if it is not present
			 * or renew it if it is too old. */
			if (!dbdat.data ||
			    !IS_NEG(dbdat.data) ||
			    !NEG_VALID(dbdat.data)) {
				__u8 ndata[6];

				stats.kern_neg++;
				prepare_neg_entry(ndata, time(NULL));
				dbdat.data = ndata;
				dbdat.size = sizeof(ndata);
				dbase->put(dbase, &dbkey, &dbdat, 0);
			}
		} else if (tb[NDA_LLADDR]) {
			if (dbdat.data && !IS_NEG(dbdat.data)) {
				if (memcmp(RTA_DATA(tb[NDA_LLADDR]), dbdat.data, dbdat.size) == 0)
					return 0;
				stats.kern_change++;
			} else {
				stats.kern_new++;
			}
			dbdat.data = RTA_DATA(tb[NDA_LLADDR]);
			dbdat.size = RTA_PAYLOAD(tb[NDA_LLADDR]);
			dbase->put(dbase, &dbkey, &dbdat, 0);
		}
	}
	return 0;
}

static void load_initial_table(void)
{
	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH) < 0) {
		perror("dump request failed");
		exit(1);
	}

}

static void get_kern_msg(void)
{
	int status;
	struct nlmsghdr *h;
	struct sockaddr_nl nladdr = {};
	struct iovec iov;
	char   buf[8192];
	struct msghdr msg = {
		(void *)&nladdr, sizeof(nladdr),
		&iov,	1,
		NULL,	0,
		0
	};

	iov.iov_base = buf;
	iov.iov_len = sizeof(buf);

	status = recvmsg(rth.fd, &msg, MSG_DONTWAIT);

	if (status <= 0)
		return;

	if (msg.msg_namelen != sizeof(nladdr))
		return;

	if (nladdr.nl_pid)
		return;

	for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
		int len = h->nlmsg_len;
		int l = len - sizeof(*h);

		if (l < 0 || len > status)
			return;

		if (do_one_request(h) < 0)
			return;

		status -= NLMSG_ALIGN(len);
		h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
	}
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
static int do_show(int argc, char **argv)
{
	struct {
		struct nlmsghdr		n;
		struct netconfmsg	ncm;
		char			buf[1024];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg)),
		.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		.n.nlmsg_type = RTM_GETNETCONF,
	};

	ipnetconf_reset_filter(0);
	filter.family = preferred_family;

	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 && filter.family != AF_UNSPEC) {
		req.ncm.ncm_family = filter.family;
		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 {
		rth.flags = RTNL_HANDLE_F_SUPPRESS_NLERR;
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) {
			/* kernel does not support netconf dump on AF_UNSPEC;
			 * fall back to requesting by family
			 */
			if (errno == EOPNOTSUPP &&
			    filter.family == AF_UNSPEC) {
				filter.family = AF_INET;
				goto dump;
			}
			perror("RTNETLINK answers");
			fprintf(stderr, "Dump terminated\n");
			exit(1);
		}
		if (preferred_family == AF_UNSPEC && filter.family == AF_INET) {
			preferred_family = AF_INET6;
			filter.family = AF_INET6;
			goto dump;
		}
	}
	return 0;
}

int do_ipnetconf(int argc, char **argv)
{
	if (argc > 0) {
		if (matches(*argv, "show") == 0 ||
		    matches(*argv, "lst") == 0 ||
		    matches(*argv, "list") == 0)
			return do_show(argc-1, argv+1);
		if (matches(*argv, "help") == 0)
			usage();
	} else
		return do_show(0, NULL);

	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netconf help\".\n", *argv);
	exit(-1);
}
Ejemplo n.º 21
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 value 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 value 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 value 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++) {
			struct {
				struct nlmsghdr n;
				char buf[NLMSG_BUF_SIZE];
			} req = {
				.n.nlmsg_len = NLMSG_HDRLEN,
				.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
				.n.nlmsg_type = XFRM_MSG_GETPOLICY,
				.n.nlmsg_seq = rth.dump = ++rth.seq,
			};

			xb.offset = 0;
			xb.nlmsg_count = 0;

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

			if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
				perror("Cannot send dump request");
				exit(1);
			}

			if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb) < 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_check(&rth, xb.buf, xb.offset) < 0) {
				perror("Failed to send delete-all request");
				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 {
		struct {
			struct nlmsghdr n;
			char buf[NLMSG_BUF_SIZE];
		} req = {
			.n.nlmsg_len = NLMSG_HDRLEN,
			.n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
			.n.nlmsg_type = XFRM_MSG_GETPOLICY,
			.n.nlmsg_seq = rth.dump = ++rth.seq,
		};

		if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
			perror("Cannot send dump request");
			exit(1);
		}

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

	rtnl_close(&rth);

	exit(0);
}

static int print_spdinfo( struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	__u32 *f = NLMSG_DATA(n);
	struct rtattr * tb[XFRMA_SPD_MAX+1];
	struct rtattr * rta;

	int len = n->nlmsg_len;

	len -= NLMSG_LENGTH(sizeof(__u32));
	if (len < 0) {
		fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
		return -1;
	}

	rta = XFRMSAPD_RTA(f);
	parse_rtattr(tb, XFRMA_SPD_MAX, rta, len);

	fprintf(fp,"\t SPD");
	if (tb[XFRMA_SPD_INFO]) {
		struct xfrmu_spdinfo *si;

		if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) {
			fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
			return -1;
		}
		si = RTA_DATA(tb[XFRMA_SPD_INFO]);
		fprintf(fp," IN  %d", si->incnt);
		fprintf(fp," OUT %d", si->outcnt);
		fprintf(fp," FWD %d", si->fwdcnt);

		if (show_stats) {
			fprintf(fp," (Sock:");
			fprintf(fp," IN %d", si->inscnt);
			fprintf(fp," OUT %d", si->outscnt);
			fprintf(fp," FWD %d", si->fwdscnt);
			fprintf(fp,")");
		}

		fprintf(fp, "%s", _SL_);
	}
	if (show_stats > 1) {
		struct xfrmu_spdhinfo *sh;

		if (tb[XFRMA_SPD_HINFO]) {
			if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			sh = RTA_DATA(tb[XFRMA_SPD_HINFO]);
			fprintf(fp,"\t SPD buckets:");
			fprintf(fp," count %d", sh->spdhcnt);
			fprintf(fp," Max %d", sh->spdhmcnt);
			fprintf(fp, "%s", _SL_);
		}
		if (tb[XFRMA_SPD_IPV4_HTHRESH]) {
			struct xfrmu_spdhthresh *th;
			if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]);
			fprintf(fp,"\t SPD IPv4 thresholds:");
			fprintf(fp," local %d", th->lbits);
			fprintf(fp," remote %d", th->rbits);
			fprintf(fp, "%s", _SL_);

		}
		if (tb[XFRMA_SPD_IPV6_HTHRESH]) {
			struct xfrmu_spdhthresh *th;
			if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) {
				fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
				return -1;
			}
			th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]);
			fprintf(fp,"\t SPD IPv6 thresholds:");
			fprintf(fp," local %d", th->lbits);
			fprintf(fp," remote %d", th->rbits);
			fprintf(fp, "%s", _SL_);
		}
	}

	if (oneline)
		fprintf(fp, "\n");

        return 0;
}
Ejemplo n.º 22
0
static int tcpm_do_cmd(int cmd, int argc, char **argv)
{
	TCPM_REQUEST(req, 1024, TCP_METRICS_CMD_GET, NLM_F_REQUEST);
	int atype = -1, stype = -1;
	int ack;

	memset(&f, 0, sizeof(f));
	f.daddr.bitlen = -1;
	f.daddr.family = preferred_family;
	f.saddr.bitlen = -1;
	f.saddr.family = preferred_family;

	switch (preferred_family) {
	case AF_UNSPEC:
	case AF_INET:
	case AF_INET6:
		break;
	default:
		fprintf(stderr, "Unsupported protocol family: %d\n", preferred_family);
		return -1;
	}

	for (; argc > 0; argc--, argv++) {
		if (strcmp(*argv, "src") == 0 ||
		    strcmp(*argv, "source") == 0) {
			char *who = *argv;

			NEXT_ARG();
			if (matches(*argv, "help") == 0)
				usage();
			if (f.saddr.bitlen >= 0)
				duparg2(who, *argv);

			get_prefix(&f.saddr, *argv, preferred_family);
			if (f.saddr.bytelen && f.saddr.bytelen * 8 == f.saddr.bitlen) {
				if (f.saddr.family == AF_INET)
					stype = TCP_METRICS_ATTR_SADDR_IPV4;
				else if (f.saddr.family == AF_INET6)
					stype = TCP_METRICS_ATTR_SADDR_IPV6;
			}

			if (stype < 0) {
				fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n",
					*argv);
				return -1;
			}
		} else {
			char *who = "address";

			if (strcmp(*argv, "addr") == 0 ||
			    strcmp(*argv, "address") == 0) {
				who = *argv;
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (f.daddr.bitlen >= 0)
				duparg2(who, *argv);

			get_prefix(&f.daddr, *argv, preferred_family);
			if (f.daddr.bytelen && f.daddr.bytelen * 8 == f.daddr.bitlen) {
				if (f.daddr.family == AF_INET)
					atype = TCP_METRICS_ATTR_ADDR_IPV4;
				else if (f.daddr.family == AF_INET6)
					atype = TCP_METRICS_ATTR_ADDR_IPV6;
			}
			if ((CMD_DEL & cmd) && atype < 0) {
				fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n",
					*argv);
				return -1;
			}
		}
		argc--; argv++;
	}

	if (cmd == CMD_DEL && atype < 0)
		missarg("address");

	/* flush for exact address ? Single del */
	if (cmd == CMD_FLUSH && atype >= 0)
		cmd = CMD_DEL;

	/* flush for all addresses ? Single del without address */
	if (cmd == CMD_FLUSH && f.daddr.bitlen <= 0 &&
	    f.saddr.bitlen <= 0 && preferred_family == AF_UNSPEC) {
		cmd = CMD_DEL;
		req.g.cmd = TCP_METRICS_CMD_DEL;
		ack = 1;
	} else if (cmd == CMD_DEL) {
		req.g.cmd = TCP_METRICS_CMD_DEL;
		ack = 1;
	} else {	/* CMD_FLUSH, CMD_LIST */
		ack = 0;
	}

	if (genl_init_handle(&grth, TCP_METRICS_GENL_NAME, &genl_family))
		exit(1);
	req.n.nlmsg_type = genl_family;

	if (!(cmd & CMD_FLUSH) && (atype >= 0 || (cmd & CMD_DEL))) {
		if (ack)
			req.n.nlmsg_flags |= NLM_F_ACK;
		if (atype >= 0)
			addattr_l(&req.n, sizeof(req), atype, &f.daddr.data,
				  f.daddr.bytelen);
		if (stype >= 0)
			addattr_l(&req.n, sizeof(req), stype, &f.saddr.data,
				  f.saddr.bytelen);
	} else {
		req.n.nlmsg_flags |= NLM_F_DUMP;
	}

	f.cmd = cmd;
	if (cmd & CMD_FLUSH) {
		int round = 0;
		char flushb[4096-512];

		f.flushb = flushb;
		f.flushp = 0;
		f.flushe = sizeof(flushb);

		for (;;) {
			req.n.nlmsg_seq = grth.dump = ++grth.seq;
			if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
				perror("Failed to send flush request");
				exit(1);
			}
			f.flushed = 0;
			if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
				fprintf(stderr, "Flush terminated\n");
				exit(1);
			}
			if (f.flushed == 0) {
				if (round == 0) {
					fprintf(stderr, "Nothing to flush.\n");
				} else if (show_stats)
					printf("*** Flush is complete after %d round%s ***\n",
					       round, round > 1 ? "s" : "");
				fflush(stdout);
				return 0;
			}
			round++;
			if (flush_update() < 0)
				exit(1);
			if (show_stats) {
				printf("\n*** Round %d, deleting %d entries ***\n",
				       round, f.flushed);
				fflush(stdout);
			}
		}
		return 0;
	}

	if (ack) {
		if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
			return -2;
	} else if (atype >= 0) {
		if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
			return -2;
		if (process_msg(NULL, &req.n, stdout) < 0) {
			fprintf(stderr, "Dump terminated\n");
			exit(1);
		}
	} else {
		req.n.nlmsg_seq = grth.dump = ++grth.seq;
		if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
			perror("Failed to send dump request");
			exit(1);
		}

		if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
			fprintf(stderr, "Dump terminated\n");
			exit(1);
		}
	}
	return 0;
}
Ejemplo n.º 23
0
static int ctrl_list(int cmd, int argc, char **argv)
{
	struct rtnl_handle rth;
	struct nlmsghdr *nlh;
	struct genlmsghdr *ghdr;
	int ret = -1;
	char d[GENL_NAMSIZ];
	struct {
		struct nlmsghdr         n;
		char                    buf[4096];
	} req;

	memset(&req, 0, sizeof(req));

	nlh = &req.n;
	nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
	nlh->nlmsg_type = GENL_ID_CTRL;

	ghdr = NLMSG_DATA(&req.n);
	ghdr->cmd = CTRL_CMD_GETFAMILY;

	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
		fprintf(stderr, "Cannot open generic netlink socket\n");
		exit(1);
	}

	if (cmd == CTRL_CMD_GETFAMILY) {
		if (argc != 2) {
			fprintf(stderr, "Wrong number of params\n");
			return -1;
		}

		if (matches(*argv, "name") == 0) {
			NEXT_ARG();
			strncpy(d, *argv, sizeof (d) - 1);
			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME,
				  d, strlen(d) + 1);
		} else if (matches(*argv, "id") == 0) {
			__u16 id;
			NEXT_ARG();
			if (get_u16(&id, *argv, 0)) {
				fprintf(stderr, "Illegal \"id\"\n");
				goto ctrl_done;
			}

			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_ID, &id, 2);

		} else {
			fprintf(stderr, "Wrong params\n");
			goto ctrl_done;
		}

		if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
			fprintf(stderr, "Error talking to the kernel\n");
			goto ctrl_done;
		}

		if (print_ctrl2(NULL, nlh, (void *) stdout) < 0) {
			fprintf(stderr, "Dump terminated\n");
			goto ctrl_done;
		}

	}

	if (cmd == CTRL_CMD_UNSPEC) {
		nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
		nlh->nlmsg_seq = rth.dump = ++rth.seq;

		if (rtnl_send(&rth, nlh, nlh->nlmsg_len) < 0) {
			perror("Failed to send dump request\n");
			goto ctrl_done;
		}

		rtnl_dump_filter(&rth, print_ctrl2, stdout);

        }

	ret = 0;
ctrl_done:
	rtnl_close(&rth);
	return ret;
}
Ejemplo n.º 24
0
static int seg6_do_cmd(void)
{
	SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST);
	int repl = 0, dump = 0;

	if (genl_family < 0) {
		if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) {
			fprintf(stderr, "Cannot open generic netlink socket\n");
			exit(1);
		}
		genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME);
		if (genl_family < 0)
			exit(1);
		req.n.nlmsg_type = genl_family;
	}

	switch (opts.cmd) {
	case SEG6_CMD_SETHMAC:
	{
		addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid);
		addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN,
			 strlen(opts.pass));
		addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id);
		if (strlen(opts.pass))
			addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET,
				  opts.pass, strlen(opts.pass));
		break;
	}
	case SEG6_CMD_SET_TUNSRC:
		addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr,
			  sizeof(struct in6_addr));
		break;
	case SEG6_CMD_DUMPHMAC:
		dump = 1;
		break;
	case SEG6_CMD_GET_TUNSRC:
		repl = 1;
		break;
	}

	if (!repl && !dump) {
		if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
			return -1;
	} else if (repl) {
		if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
			return -2;
		if (process_msg(NULL, &req.n, stdout) < 0) {
			fprintf(stderr, "Error parsing reply\n");
			exit(1);
		}
	} else {
		req.n.nlmsg_flags |= NLM_F_DUMP;
		req.n.nlmsg_seq = grth.dump = ++grth.seq;
		if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
			perror("Failed to send dump request");
			exit(1);
		}

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

	return 0;
}
Ejemplo n.º 25
0
static int ctrl_list(int cmd, int argc, char **argv)
{
	struct rtnl_handle rth;
	int ret = -1;
	char d[GENL_NAMSIZ];
	struct {
		struct nlmsghdr         n;
		struct genlmsghdr	g;
		char                    buf[4096];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN),
		.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		.n.nlmsg_type = GENL_ID_CTRL,
		.g.cmd = CTRL_CMD_GETFAMILY,
	};
	struct nlmsghdr *nlh = &req.n;

	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
		fprintf(stderr, "Cannot open generic netlink socket\n");
		exit(1);
	}

	if (cmd == CTRL_CMD_GETFAMILY) {
		if (argc != 2) {
			fprintf(stderr, "Wrong number of params\n");
			return -1;
		}

		if (matches(*argv, "name") == 0) {
			NEXT_ARG();
			strncpy(d, *argv, sizeof (d) - 1);
			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME,
				  d, strlen(d) + 1);
		} else if (matches(*argv, "id") == 0) {
			__u16 id;
			NEXT_ARG();
			if (get_u16(&id, *argv, 0)) {
				fprintf(stderr, "Illegal \"id\"\n");
				goto ctrl_done;
			}

			addattr_l(nlh, 128, CTRL_ATTR_FAMILY_ID, &id, 2);

		} else {
			fprintf(stderr, "Wrong params\n");
			goto ctrl_done;
		}

		if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
			fprintf(stderr, "Error talking to the kernel\n");
			goto ctrl_done;
		}

		if (print_ctrl2(NULL, nlh, (void *) stdout) < 0) {
			fprintf(stderr, "Dump terminated\n");
			goto ctrl_done;
		}

	}

	if (cmd == CTRL_CMD_UNSPEC) {
		nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
		nlh->nlmsg_seq = rth.dump = ++rth.seq;

		if (rtnl_send(&rth, nlh, nlh->nlmsg_len) < 0) {
			perror("Failed to send dump request\n");
			goto ctrl_done;
		}

		rtnl_dump_filter(&rth, print_ctrl2, stdout);

        }

	ret = 0;
ctrl_done:
	rtnl_close(&rth);
	return ret;
}

static int ctrl_listen(int argc, char **argv)
{
	struct rtnl_handle rth;

	if (rtnl_open_byproto(&rth, nl_mgrp(GENL_ID_CTRL), NETLINK_GENERIC) < 0) {
		fprintf(stderr, "Canot open generic netlink socket\n");
		return -1;
	}

	if (rtnl_listen(&rth, print_ctrl, (void *) stdout) < 0)
		return -1;

	return 0;
}

static int parse_ctrl(struct genl_util *a, int argc, char **argv)
{
	argv++;
	if (--argc <= 0) {
		fprintf(stderr, "wrong controller params\n");
		return -1;
	}

	if (matches(*argv, "monitor") == 0)
		return ctrl_listen(argc-1, argv+1);
	if (matches(*argv, "get") == 0)
		return ctrl_list(CTRL_CMD_GETFAMILY, argc-1, argv+1);
	if (matches(*argv, "list") == 0 ||
	    matches(*argv, "show") == 0 ||
	    matches(*argv, "lst") == 0)
		return ctrl_list(CTRL_CMD_UNSPEC, argc-1, argv+1);
	if (matches(*argv, "help") == 0)
		return usage();

	fprintf(stderr, "ctrl command \"%s\" is unknown, try \"ctrl help\".\n",
		*argv);

	return -1;
}