mirror of
				https://git.proxmox.com/git/mirror_iproute2
				synced 2025-11-04 06:22:48 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			212 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * ipmroute.c		"ip mroute".
 | 
						|
 *
 | 
						|
 *		This program is free software; you can redistribute it and/or
 | 
						|
 *		modify it under the terms of the GNU General Public License
 | 
						|
 *		as published by the Free Software Foundation; either version
 | 
						|
 *		2 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <syslog.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <sys/ioctl.h>
 | 
						|
#include <sys/socket.h>
 | 
						|
#include <netinet/in.h>
 | 
						|
#include <arpa/inet.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <linux/netdevice.h>
 | 
						|
#include <linux/if.h>
 | 
						|
#include <linux/if_arp.h>
 | 
						|
#include <linux/sockios.h>
 | 
						|
 | 
						|
#include "utils.h"
 | 
						|
 | 
						|
char filter_dev[16];
 | 
						|
int  filter_family;
 | 
						|
 | 
						|
static void usage(void) __attribute__((noreturn));
 | 
						|
 | 
						|
static void usage(void)
 | 
						|
{
 | 
						|
	fprintf(stderr, "Usage: ip mroute show [ PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n");
 | 
						|
#if 0
 | 
						|
	fprintf(stderr, "Usage: ip mroute [ add | del ] DESTINATION from SOURCE [ iif DEVICE ] [ oif DEVICE ]\n");
 | 
						|
#endif
 | 
						|
	exit(-1);
 | 
						|
}
 | 
						|
 | 
						|
static char *viftable[32];
 | 
						|
 | 
						|
struct rtfilter
 | 
						|
{
 | 
						|
	inet_prefix mdst;
 | 
						|
	inet_prefix msrc;
 | 
						|
} filter;
 | 
						|
 | 
						|
static void read_viftable(void)
 | 
						|
{
 | 
						|
	char buf[256];
 | 
						|
	FILE *fp = fopen("/proc/net/ip_mr_vif", "r");
 | 
						|
 | 
						|
	if (!fp)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (!fgets(buf, sizeof(buf), fp)) {
 | 
						|
		fclose(fp);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	while (fgets(buf, sizeof(buf), fp)) {
 | 
						|
		int vifi;
 | 
						|
		char dev[256];
 | 
						|
 | 
						|
		if (sscanf(buf, "%d%s", &vifi, dev) < 2)
 | 
						|
			continue;
 | 
						|
 | 
						|
		if (vifi<0 || vifi>31)
 | 
						|
			continue;
 | 
						|
 | 
						|
		viftable[vifi] = strdup(dev);
 | 
						|
	}
 | 
						|
	fclose(fp);
 | 
						|
}
 | 
						|
 | 
						|
static void read_mroute_list(FILE *ofp)
 | 
						|
{
 | 
						|
	char buf[256];
 | 
						|
	FILE *fp = fopen("/proc/net/ip_mr_cache", "r");
 | 
						|
 | 
						|
	if (!fp)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (!fgets(buf, sizeof(buf), fp)) {
 | 
						|
		fclose(fp);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	while (fgets(buf, sizeof(buf), fp)) {
 | 
						|
		inet_prefix maddr, msrc;
 | 
						|
		unsigned pkts, b, w;
 | 
						|
		int vifi;
 | 
						|
		char oiflist[256];
 | 
						|
		char sbuf[256];
 | 
						|
		char mbuf[256];
 | 
						|
		char obuf[256];
 | 
						|
 | 
						|
		oiflist[0] = 0;
 | 
						|
		if (sscanf(buf, "%x%x%d%u%u%u %[^\n]",
 | 
						|
			   maddr.data, msrc.data, &vifi,
 | 
						|
			   &pkts, &b, &w, oiflist) < 6)
 | 
						|
			continue;
 | 
						|
 | 
						|
		if (vifi!=-1 && (vifi < 0 || vifi>31))
 | 
						|
			continue;
 | 
						|
 | 
						|
		if (filter_dev[0] && (vifi<0 || strcmp(filter_dev, viftable[vifi])))
 | 
						|
			continue;
 | 
						|
		if (filter.mdst.family && inet_addr_match(&maddr, &filter.mdst, filter.mdst.bitlen))
 | 
						|
			continue;
 | 
						|
		if (filter.msrc.family && inet_addr_match(&msrc, &filter.msrc, filter.msrc.bitlen))
 | 
						|
			continue;
 | 
						|
 | 
						|
		snprintf(obuf, sizeof(obuf), "(%s, %s)",
 | 
						|
			 format_host(AF_INET, 4, &msrc.data[0], sbuf, sizeof(sbuf)),
 | 
						|
			 format_host(AF_INET, 4, &maddr.data[0], mbuf, sizeof(mbuf)));
 | 
						|
 | 
						|
		fprintf(ofp, "%-32s Iif: ", obuf);
 | 
						|
 | 
						|
		if (vifi == -1)
 | 
						|
			fprintf(ofp, "unresolved ");
 | 
						|
		else
 | 
						|
			fprintf(ofp, "%-10s ", viftable[vifi]);
 | 
						|
 | 
						|
		if (oiflist[0]) {
 | 
						|
			char *next = NULL;
 | 
						|
			char *p = oiflist;
 | 
						|
			int ovifi, ottl;
 | 
						|
 | 
						|
			fprintf(ofp, "Oifs: ");
 | 
						|
 | 
						|
			while (p) {
 | 
						|
				next = strchr(p, ' ');
 | 
						|
				if (next) {
 | 
						|
					*next = 0;
 | 
						|
					next++;
 | 
						|
				}
 | 
						|
				if (sscanf(p, "%d:%d", &ovifi, &ottl)<2) {
 | 
						|
					p = next;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				p = next;
 | 
						|
 | 
						|
				fprintf(ofp, "%s", viftable[ovifi]);
 | 
						|
				if (ottl>1)
 | 
						|
					fprintf(ofp, "(ttl %d) ", ovifi);
 | 
						|
				else
 | 
						|
					fprintf(ofp, " ");
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (show_stats && b) {
 | 
						|
			fprintf(ofp, "%s  %u packets, %u bytes", _SL_, pkts, b);
 | 
						|
			if (w)
 | 
						|
				fprintf(ofp, ", %u arrived on wrong iif.", w);
 | 
						|
		}
 | 
						|
		fprintf(ofp, "\n");
 | 
						|
	}
 | 
						|
	fclose(fp);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int mroute_list(int argc, char **argv)
 | 
						|
{
 | 
						|
	while (argc > 0) {
 | 
						|
		if (strcmp(*argv, "iif") == 0) {
 | 
						|
			NEXT_ARG();
 | 
						|
			strncpy(filter_dev, *argv, sizeof(filter_dev)-1);
 | 
						|
		} else if (matches(*argv, "from") == 0) {
 | 
						|
			NEXT_ARG();
 | 
						|
			get_prefix(&filter.msrc, *argv, AF_INET);
 | 
						|
		} else {
 | 
						|
			if (strcmp(*argv, "to") == 0) {
 | 
						|
				NEXT_ARG();
 | 
						|
			}
 | 
						|
			if (matches(*argv, "help") == 0)
 | 
						|
				usage();
 | 
						|
			get_prefix(&filter.mdst, *argv, AF_INET);
 | 
						|
		}
 | 
						|
		argv++; argc--;
 | 
						|
	}
 | 
						|
 | 
						|
	read_viftable();
 | 
						|
	read_mroute_list(stdout);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int do_multiroute(int argc, char **argv)
 | 
						|
{
 | 
						|
	if (argc < 1)
 | 
						|
		return mroute_list(0, NULL);
 | 
						|
#if 0
 | 
						|
	if (matches(*argv, "add") == 0)
 | 
						|
		return mroute_modify(RTM_NEWADDR, argc-1, argv+1);
 | 
						|
	if (matches(*argv, "delete") == 0)
 | 
						|
		return mroute_modify(RTM_DELADDR, argc-1, argv+1);
 | 
						|
	if (matches(*argv, "get") == 0)
 | 
						|
		return mroute_get(argc-1, argv+1);
 | 
						|
#endif
 | 
						|
	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
 | 
						|
	    || matches(*argv, "lst") == 0)
 | 
						|
		return mroute_list(argc-1, argv+1);
 | 
						|
	if (matches(*argv, "help") == 0)
 | 
						|
		usage();
 | 
						|
	fprintf(stderr, "Command \"%s\" is unknown, try \"ip mroute help\".\n", *argv);
 | 
						|
	exit(-1);
 | 
						|
}
 |