mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2024-11-16 14:35:34 +08:00
206 lines
4.3 KiB
C
206 lines
4.3 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;
|
|
|
|
fgets(buf, sizeof(buf), fp);
|
|
|
|
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;
|
|
|
|
fgets(buf, sizeof(buf), fp);
|
|
|
|
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%s", 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);
|
|
}
|