]>
Commit | Line | Data |
---|---|---|
d04bc300 SH |
1 | |
2 | #include <stdio.h> | |
3 | #include <stdlib.h> | |
4 | #include <unistd.h> | |
5 | #include <time.h> | |
6 | #include <sys/socket.h> | |
7 | #include <sys/time.h> | |
8 | #include <netinet/in.h> | |
9 | #include <linux/if.h> | |
10 | #include <linux/if_bridge.h> | |
11 | #include <string.h> | |
12 | ||
13 | #include "utils.h" | |
14 | #include "br_common.h" | |
15 | ||
16 | static const char *port_states[] = { | |
17 | [BR_STATE_DISABLED] = "disabled", | |
18 | [BR_STATE_LISTENING] = "listening", | |
19 | [BR_STATE_LEARNING] = "learning", | |
20 | [BR_STATE_FORWARDING] = "forwarding", | |
21 | [BR_STATE_BLOCKING] = "blocking", | |
22 | }; | |
23 | ||
24 | extern char *if_indextoname (unsigned int __ifindex, char *__ifname); | |
25 | ||
26 | static void print_link_flags(FILE *fp, unsigned flags) | |
27 | { | |
28 | fprintf(fp, "<"); | |
29 | if (flags & IFF_UP && !(flags & IFF_RUNNING)) | |
30 | fprintf(fp, "NO-CARRIER%s", flags ? "," : ""); | |
31 | flags &= ~IFF_RUNNING; | |
32 | #define _PF(f) if (flags&IFF_##f) { \ | |
33 | flags &= ~IFF_##f ; \ | |
34 | fprintf(fp, #f "%s", flags ? "," : ""); } | |
35 | _PF(LOOPBACK); | |
36 | _PF(BROADCAST); | |
37 | _PF(POINTOPOINT); | |
38 | _PF(MULTICAST); | |
39 | _PF(NOARP); | |
40 | _PF(ALLMULTI); | |
41 | _PF(PROMISC); | |
42 | _PF(MASTER); | |
43 | _PF(SLAVE); | |
44 | _PF(DEBUG); | |
45 | _PF(DYNAMIC); | |
46 | _PF(AUTOMEDIA); | |
47 | _PF(PORTSEL); | |
48 | _PF(NOTRAILERS); | |
49 | _PF(UP); | |
50 | _PF(LOWER_UP); | |
51 | _PF(DORMANT); | |
52 | _PF(ECHO); | |
53 | #undef _PF | |
54 | if (flags) | |
55 | fprintf(fp, "%x", flags); | |
56 | fprintf(fp, "> "); | |
57 | } | |
58 | ||
59 | static const char *oper_states[] = { | |
60 | "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN", | |
61 | "TESTING", "DORMANT", "UP" | |
62 | }; | |
63 | ||
64 | static void print_operstate(FILE *f, __u8 state) | |
65 | { | |
66 | if (state >= sizeof(oper_states)/sizeof(oper_states[0])) | |
67 | fprintf(f, "state %#x ", state); | |
68 | else | |
69 | fprintf(f, "state %s ", oper_states[state]); | |
70 | } | |
71 | ||
72 | int print_linkinfo(const struct sockaddr_nl *who, | |
73 | struct nlmsghdr *n, void *arg) | |
74 | { | |
75 | FILE *fp = arg; | |
76 | int len = n->nlmsg_len; | |
77 | struct ifinfomsg *ifi = NLMSG_DATA(n); | |
78 | struct rtattr * tb[IFLA_MAX+1]; | |
79 | char b1[IFNAMSIZ]; | |
80 | ||
81 | len -= NLMSG_LENGTH(sizeof(*ifi)); | |
82 | if (len < 0) { | |
83 | fprintf(stderr, "Message too short!\n"); | |
84 | return -1; | |
85 | } | |
86 | ||
87 | if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC)) | |
88 | return 0; | |
89 | ||
90 | parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); | |
91 | ||
92 | if (tb[IFLA_IFNAME] == NULL) { | |
93 | fprintf(stderr, "BUG: nil ifname\n"); | |
94 | return -1; | |
95 | } | |
96 | ||
97 | if (n->nlmsg_type == RTM_DELLINK) | |
98 | fprintf(fp, "Deleted "); | |
99 | ||
100 | fprintf(fp, "%d: %s ", ifi->ifi_index, | |
101 | tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>"); | |
102 | ||
103 | if (tb[IFLA_OPERSTATE]) | |
104 | print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE])); | |
105 | ||
106 | if (tb[IFLA_LINK]) { | |
107 | SPRINT_BUF(b1); | |
108 | int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); | |
109 | ||
110 | if (iflink == 0) | |
111 | fprintf(fp, "@NONE: "); | |
112 | else { | |
113 | fprintf(fp, "@%s: ", | |
114 | if_indextoname(iflink, b1)); | |
115 | } | |
116 | } else { | |
117 | fprintf(fp, ": "); | |
118 | } | |
119 | ||
120 | print_link_flags(fp, ifi->ifi_flags); | |
121 | ||
122 | if (tb[IFLA_MTU]) | |
123 | fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); | |
124 | ||
125 | if (tb[IFLA_MASTER]) { | |
126 | fprintf(fp, "master %s ", | |
127 | if_indextoname(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); | |
128 | } | |
129 | ||
130 | if (tb[IFLA_PROTINFO]) { | |
131 | uint8_t state = *(uint8_t *)RTA_DATA(tb[IFLA_PROTINFO]); | |
132 | if (state <= BR_STATE_BLOCKING) | |
133 | fprintf(fp, "state %s", port_states[state]); | |
134 | else | |
135 | fprintf(fp, "state (%d)", state); | |
136 | } | |
137 | ||
138 | ||
139 | fprintf(fp, "\n"); | |
140 | fflush(fp); | |
141 | return 0; | |
142 | } |