1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * ipmroute.c		"ip mroute".
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		This program is free software; you can redistribute it and/or
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		modify it under the terms of the GNU General Public License
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		as published by the Free Software Foundation; either version
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		2 of the License, or (at your option) any later version.
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/ioctl.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h>
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netdevice.h>
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/if.h>
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/if_arp.h>
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/sockios.h>
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar filter_dev[16];
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint  filter_family;
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void) __attribute__((noreturn));
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void)
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Usage: ip mroute show [ PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n");
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#if 0
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Usage: ip mroute [ add | del ] DESTINATION from SOURCE [ iif DEVICE ] [ oif DEVICE ]\n");
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(-1);
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic char *viftable[32];
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct rtfilter
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	inet_prefix mdst;
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	inet_prefix msrc;
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} filter;
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void read_viftable(void)
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[256];
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	FILE *fp = fopen("/proc/net/ip_mr_vif", "r");
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!fp)
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fgets(buf, sizeof(buf), fp);
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (fgets(buf, sizeof(buf), fp)) {
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int vifi;
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char dev[256];
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (sscanf(buf, "%d%s", &vifi, dev) < 2)
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (vifi<0 || vifi>31)
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		viftable[vifi] = strdup(dev);
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fclose(fp);
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void read_mroute_list(FILE *ofp)
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[256];
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	FILE *fp = fopen("/proc/net/ip_mr_cache", "r");
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!fp)
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fgets(buf, sizeof(buf), fp);
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (fgets(buf, sizeof(buf), fp)) {
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		inet_prefix maddr, msrc;
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		unsigned pkts, b, w;
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int vifi;
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char oiflist[256];
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char sbuf[256];
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char mbuf[256];
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char obuf[256];
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		oiflist[0] = 0;
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (sscanf(buf, "%x%x%d%u%u%u %[^\n]",
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			   maddr.data, msrc.data, &vifi,
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			   &pkts, &b, &w, oiflist) < 6)
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (vifi!=-1 && (vifi < 0 || vifi>31))
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (filter_dev[0] && (vifi<0 || strcmp(filter_dev, viftable[vifi])))
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (filter.mdst.family && inet_addr_match(&maddr, &filter.mdst, filter.mdst.bitlen))
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (filter.msrc.family && inet_addr_match(&msrc, &filter.msrc, filter.msrc.bitlen))
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(obuf, sizeof(obuf), "(%s, %s)",
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			 format_host(AF_INET, 4, &msrc.data[0], sbuf, sizeof(sbuf)),
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			 format_host(AF_INET, 4, &maddr.data[0], mbuf, sizeof(mbuf)));
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(ofp, "%-32s Iif: ", obuf);
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (vifi == -1)
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(ofp, "unresolved ");
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(ofp, "%-10s ", viftable[vifi]);
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (oiflist[0]) {
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			char *next = NULL;
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			char *p = oiflist;
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			int ovifi, ottl;
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(ofp, "Oifs: ");
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			while (p) {
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				next = strchr(p, ' ');
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (next) {
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					*next = 0;
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					next++;
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (sscanf(p, "%d:%d", &ovifi, &ottl)<2) {
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					p = next;
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					continue;
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				p = next;
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(ofp, "%s", viftable[ovifi]);
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (ottl>1)
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(ofp, "(ttl %d) ", ovifi);
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				else
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(ofp, " ");
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (show_stats && b) {
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(ofp, "%s  %u packets, %u bytes", _SL_, pkts, b);
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (w)
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(ofp, ", %u arrived on wrong iif.", w);
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(ofp, "\n");
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fclose(fp);
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int mroute_list(int argc, char **argv)
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (argc > 0) {
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcmp(*argv, "iif") == 0) {
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			strncpy(filter_dev, *argv, sizeof(filter_dev)-1);
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else if (matches(*argv, "from") == 0) {
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			get_prefix(&filter.msrc, *argv, AF_INET);
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (strcmp(*argv, "to") == 0) {
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				NEXT_ARG();
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (matches(*argv, "help") == 0)
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				usage();
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			get_prefix(&filter.mdst, *argv, AF_INET);
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argv++; argc--;
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	read_viftable();
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	read_mroute_list(stdout);
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint do_multiroute(int argc, char **argv)
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc < 1)
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return mroute_list(0, NULL);
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#if 0
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "add") == 0)
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return mroute_modify(RTM_NEWADDR, argc-1, argv+1);
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "delete") == 0)
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return mroute_modify(RTM_DELADDR, argc-1, argv+1);
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "get") == 0)
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return mroute_get(argc-1, argv+1);
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    || matches(*argv, "lst") == 0)
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return mroute_list(argc-1, argv+1);
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(*argv, "help") == 0)
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		usage();
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Command \"%s\" is unknown, try \"ip mroute help\".\n", *argv);
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(-1);
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
207