1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * rtmon.c RTnetlink listener.
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker *
11*de1e4e89SAndroid Build Coastguard Worker */
12*de1e4e89SAndroid Build Coastguard Worker
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/time.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
22*de1e4e89SAndroid Build Coastguard Worker
23*de1e4e89SAndroid Build Coastguard Worker #include "SNAPSHOT.h"
24*de1e4e89SAndroid Build Coastguard Worker
25*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
26*de1e4e89SAndroid Build Coastguard Worker #include "libnetlink.h"
27*de1e4e89SAndroid Build Coastguard Worker
28*de1e4e89SAndroid Build Coastguard Worker static int init_phase = 1;
29*de1e4e89SAndroid Build Coastguard Worker
write_stamp(FILE * fp)30*de1e4e89SAndroid Build Coastguard Worker static void write_stamp(FILE *fp)
31*de1e4e89SAndroid Build Coastguard Worker {
32*de1e4e89SAndroid Build Coastguard Worker char buf[128];
33*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n1 = (void *)buf;
34*de1e4e89SAndroid Build Coastguard Worker struct timeval tv;
35*de1e4e89SAndroid Build Coastguard Worker
36*de1e4e89SAndroid Build Coastguard Worker n1->nlmsg_type = NLMSG_TSTAMP;
37*de1e4e89SAndroid Build Coastguard Worker n1->nlmsg_flags = 0;
38*de1e4e89SAndroid Build Coastguard Worker n1->nlmsg_seq = 0;
39*de1e4e89SAndroid Build Coastguard Worker n1->nlmsg_pid = 0;
40*de1e4e89SAndroid Build Coastguard Worker n1->nlmsg_len = NLMSG_LENGTH(4*2);
41*de1e4e89SAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
42*de1e4e89SAndroid Build Coastguard Worker ((__u32 *)NLMSG_DATA(n1))[0] = tv.tv_sec;
43*de1e4e89SAndroid Build Coastguard Worker ((__u32 *)NLMSG_DATA(n1))[1] = tv.tv_usec;
44*de1e4e89SAndroid Build Coastguard Worker fwrite((void *)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp);
45*de1e4e89SAndroid Build Coastguard Worker }
46*de1e4e89SAndroid Build Coastguard Worker
dump_msg(const struct sockaddr_nl * who,struct rtnl_ctrl_data * ctrl,struct nlmsghdr * n,void * arg)47*de1e4e89SAndroid Build Coastguard Worker static int dump_msg(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
48*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n, void *arg)
49*de1e4e89SAndroid Build Coastguard Worker {
50*de1e4e89SAndroid Build Coastguard Worker FILE *fp = (FILE *)arg;
51*de1e4e89SAndroid Build Coastguard Worker
52*de1e4e89SAndroid Build Coastguard Worker if (!init_phase)
53*de1e4e89SAndroid Build Coastguard Worker write_stamp(fp);
54*de1e4e89SAndroid Build Coastguard Worker fwrite((void *)n, 1, NLMSG_ALIGN(n->nlmsg_len), fp);
55*de1e4e89SAndroid Build Coastguard Worker fflush(fp);
56*de1e4e89SAndroid Build Coastguard Worker return 0;
57*de1e4e89SAndroid Build Coastguard Worker }
58*de1e4e89SAndroid Build Coastguard Worker
dump_msg2(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)59*de1e4e89SAndroid Build Coastguard Worker static int dump_msg2(const struct sockaddr_nl *who,
60*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n, void *arg)
61*de1e4e89SAndroid Build Coastguard Worker {
62*de1e4e89SAndroid Build Coastguard Worker return dump_msg(who, NULL, n, arg);
63*de1e4e89SAndroid Build Coastguard Worker }
64*de1e4e89SAndroid Build Coastguard Worker
usage(void)65*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
66*de1e4e89SAndroid Build Coastguard Worker {
67*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n");
68*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n");
69*de1e4e89SAndroid Build Coastguard Worker exit(-1);
70*de1e4e89SAndroid Build Coastguard Worker }
71*de1e4e89SAndroid Build Coastguard Worker
72*de1e4e89SAndroid Build Coastguard Worker int
main(int argc,char ** argv)73*de1e4e89SAndroid Build Coastguard Worker main(int argc, char **argv)
74*de1e4e89SAndroid Build Coastguard Worker {
75*de1e4e89SAndroid Build Coastguard Worker FILE *fp;
76*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
77*de1e4e89SAndroid Build Coastguard Worker int family = AF_UNSPEC;
78*de1e4e89SAndroid Build Coastguard Worker unsigned int groups = ~0U;
79*de1e4e89SAndroid Build Coastguard Worker int llink = 0;
80*de1e4e89SAndroid Build Coastguard Worker int laddr = 0;
81*de1e4e89SAndroid Build Coastguard Worker int lroute = 0;
82*de1e4e89SAndroid Build Coastguard Worker char *file = NULL;
83*de1e4e89SAndroid Build Coastguard Worker
84*de1e4e89SAndroid Build Coastguard Worker while (argc > 1) {
85*de1e4e89SAndroid Build Coastguard Worker if (matches(argv[1], "-family") == 0) {
86*de1e4e89SAndroid Build Coastguard Worker argc--;
87*de1e4e89SAndroid Build Coastguard Worker argv++;
88*de1e4e89SAndroid Build Coastguard Worker if (argc <= 1)
89*de1e4e89SAndroid Build Coastguard Worker usage();
90*de1e4e89SAndroid Build Coastguard Worker if (strcmp(argv[1], "inet") == 0)
91*de1e4e89SAndroid Build Coastguard Worker family = AF_INET;
92*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(argv[1], "inet6") == 0)
93*de1e4e89SAndroid Build Coastguard Worker family = AF_INET6;
94*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(argv[1], "link") == 0)
95*de1e4e89SAndroid Build Coastguard Worker family = AF_INET6;
96*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(argv[1], "help") == 0)
97*de1e4e89SAndroid Build Coastguard Worker usage();
98*de1e4e89SAndroid Build Coastguard Worker else {
99*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Protocol ID \"%s\" is unknown, try \"rtmon help\".\n", argv[1]);
100*de1e4e89SAndroid Build Coastguard Worker exit(-1);
101*de1e4e89SAndroid Build Coastguard Worker }
102*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(argv[1], "-4") == 0) {
103*de1e4e89SAndroid Build Coastguard Worker family = AF_INET;
104*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(argv[1], "-6") == 0) {
105*de1e4e89SAndroid Build Coastguard Worker family = AF_INET6;
106*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(argv[1], "-0") == 0) {
107*de1e4e89SAndroid Build Coastguard Worker family = AF_PACKET;
108*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "-Version") == 0) {
109*de1e4e89SAndroid Build Coastguard Worker printf("rtmon utility, iproute2-ss%s\n", SNAPSHOT);
110*de1e4e89SAndroid Build Coastguard Worker exit(0);
111*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "file") == 0) {
112*de1e4e89SAndroid Build Coastguard Worker argc--;
113*de1e4e89SAndroid Build Coastguard Worker argv++;
114*de1e4e89SAndroid Build Coastguard Worker if (argc <= 1)
115*de1e4e89SAndroid Build Coastguard Worker usage();
116*de1e4e89SAndroid Build Coastguard Worker file = argv[1];
117*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "link") == 0) {
118*de1e4e89SAndroid Build Coastguard Worker llink = 1;
119*de1e4e89SAndroid Build Coastguard Worker groups = 0;
120*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "address") == 0) {
121*de1e4e89SAndroid Build Coastguard Worker laddr = 1;
122*de1e4e89SAndroid Build Coastguard Worker groups = 0;
123*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "route") == 0) {
124*de1e4e89SAndroid Build Coastguard Worker lroute = 1;
125*de1e4e89SAndroid Build Coastguard Worker groups = 0;
126*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(argv[1], "all") == 0) {
127*de1e4e89SAndroid Build Coastguard Worker groups = ~0U;
128*de1e4e89SAndroid Build Coastguard Worker } else if (matches(argv[1], "help") == 0) {
129*de1e4e89SAndroid Build Coastguard Worker usage();
130*de1e4e89SAndroid Build Coastguard Worker } else {
131*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]);
132*de1e4e89SAndroid Build Coastguard Worker exit(-1);
133*de1e4e89SAndroid Build Coastguard Worker }
134*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
135*de1e4e89SAndroid Build Coastguard Worker }
136*de1e4e89SAndroid Build Coastguard Worker
137*de1e4e89SAndroid Build Coastguard Worker if (file == NULL) {
138*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not enough information: argument \"file\" is required\n");
139*de1e4e89SAndroid Build Coastguard Worker exit(-1);
140*de1e4e89SAndroid Build Coastguard Worker }
141*de1e4e89SAndroid Build Coastguard Worker if (llink)
142*de1e4e89SAndroid Build Coastguard Worker groups |= nl_mgrp(RTNLGRP_LINK);
143*de1e4e89SAndroid Build Coastguard Worker if (laddr) {
144*de1e4e89SAndroid Build Coastguard Worker if (!family || family == AF_INET)
145*de1e4e89SAndroid Build Coastguard Worker groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
146*de1e4e89SAndroid Build Coastguard Worker if (!family || family == AF_INET6)
147*de1e4e89SAndroid Build Coastguard Worker groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
148*de1e4e89SAndroid Build Coastguard Worker }
149*de1e4e89SAndroid Build Coastguard Worker if (lroute) {
150*de1e4e89SAndroid Build Coastguard Worker if (!family || family == AF_INET)
151*de1e4e89SAndroid Build Coastguard Worker groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
152*de1e4e89SAndroid Build Coastguard Worker if (!family || family == AF_INET6)
153*de1e4e89SAndroid Build Coastguard Worker groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
154*de1e4e89SAndroid Build Coastguard Worker }
155*de1e4e89SAndroid Build Coastguard Worker
156*de1e4e89SAndroid Build Coastguard Worker fp = fopen(file, "w");
157*de1e4e89SAndroid Build Coastguard Worker if (fp == NULL) {
158*de1e4e89SAndroid Build Coastguard Worker perror("Cannot fopen");
159*de1e4e89SAndroid Build Coastguard Worker exit(-1);
160*de1e4e89SAndroid Build Coastguard Worker }
161*de1e4e89SAndroid Build Coastguard Worker
162*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open(&rth, groups) < 0)
163*de1e4e89SAndroid Build Coastguard Worker exit(1);
164*de1e4e89SAndroid Build Coastguard Worker
165*de1e4e89SAndroid Build Coastguard Worker if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) {
166*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
167*de1e4e89SAndroid Build Coastguard Worker exit(1);
168*de1e4e89SAndroid Build Coastguard Worker }
169*de1e4e89SAndroid Build Coastguard Worker
170*de1e4e89SAndroid Build Coastguard Worker write_stamp(fp);
171*de1e4e89SAndroid Build Coastguard Worker
172*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, dump_msg2, fp) < 0) {
173*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
174*de1e4e89SAndroid Build Coastguard Worker return 1;
175*de1e4e89SAndroid Build Coastguard Worker }
176*de1e4e89SAndroid Build Coastguard Worker
177*de1e4e89SAndroid Build Coastguard Worker init_phase = 0;
178*de1e4e89SAndroid Build Coastguard Worker
179*de1e4e89SAndroid Build Coastguard Worker if (rtnl_listen(&rth, dump_msg, (void *)fp) < 0)
180*de1e4e89SAndroid Build Coastguard Worker exit(2);
181*de1e4e89SAndroid Build Coastguard Worker
182*de1e4e89SAndroid Build Coastguard Worker exit(0);
183*de1e4e89SAndroid Build Coastguard Worker }
184