]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipmaddr.c
2 * ipmaddr.c "ip maddress".
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
23 #include <linux/netdevice.h>
25 #include <linux/if_arp.h>
26 #include <linux/sockios.h>
30 #include "ip_common.h"
31 #include "json_print.h"
38 static void usage(void) __attribute__((noreturn
));
40 static void usage(void)
42 fprintf(stderr
, "Usage: ip maddr [ add | del ] MULTIADDR dev STRING\n");
43 fprintf(stderr
, " ip maddr show [ dev STRING ]\n");
47 static int parse_hex(char *str
, unsigned char *addr
, size_t size
)
51 while (*str
&& (len
< 2 * size
)) {
56 if (sscanf(str
, "%02x", &tmp
) != 1)
74 static void maddr_ins(struct ma_info
**lst
, struct ma_info
*m
)
78 for (; (mp
= *lst
) != NULL
; lst
= &mp
->next
) {
79 if (mp
->index
> m
->index
)
86 static void read_dev_mcast(struct ma_info
**result_p
)
89 FILE *fp
= fopen("/proc/net/dev_mcast", "r");
94 while (fgets(buf
, sizeof(buf
), fp
)) {
96 struct ma_info m
= { .addr
.family
= AF_PACKET
};
100 sscanf(buf
, "%d%s%d%d%s", &m
.index
, m
.name
, &m
.users
, &st
,
102 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
105 len
= parse_hex(hexa
, (unsigned char *)&m
.addr
.data
, sizeof(m
.addr
.data
));
107 struct ma_info
*ma
= malloc(sizeof(m
));
109 memcpy(ma
, &m
, sizeof(m
));
110 ma
->addr
.bytelen
= len
;
111 ma
->addr
.bitlen
= len
<<3;
113 ma
->features
= "static";
114 maddr_ins(result_p
, ma
);
120 static void read_igmp(struct ma_info
**result_p
)
123 .addr
.family
= AF_INET
,
128 FILE *fp
= fopen("/proc/net/igmp", "r");
132 if (!fgets(buf
, sizeof(buf
), fp
)) {
137 while (fgets(buf
, sizeof(buf
), fp
)) {
140 if (buf
[0] != '\t') {
143 sscanf(buf
, "%d%s", &m
.index
, m
.name
);
144 len
= strlen(m
.name
);
145 if (m
.name
[len
- 1] == ':')
146 m
.name
[len
- 1] = '\0';
150 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
153 sscanf(buf
, "%08x%d", (__u32
*)&m
.addr
.data
, &m
.users
);
155 ma
= malloc(sizeof(m
));
156 memcpy(ma
, &m
, sizeof(m
));
157 maddr_ins(result_p
, ma
);
163 static void read_igmp6(struct ma_info
**result_p
)
166 FILE *fp
= fopen("/proc/net/igmp6", "r");
171 while (fgets(buf
, sizeof(buf
), fp
)) {
173 struct ma_info m
= { .addr
.family
= AF_INET6
};
176 sscanf(buf
, "%d%s%s%d", &m
.index
, m
.name
, hexa
, &m
.users
);
178 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
181 len
= parse_hex(hexa
, (unsigned char *)&m
.addr
.data
, sizeof(m
.addr
.data
));
183 struct ma_info
*ma
= malloc(sizeof(m
));
185 memcpy(ma
, &m
, sizeof(m
));
187 ma
->addr
.bytelen
= len
;
188 ma
->addr
.bitlen
= len
<<3;
189 maddr_ins(result_p
, ma
);
195 static void print_maddr(FILE *fp
, struct ma_info
*list
)
197 print_string(PRINT_FP
, NULL
, "\t", NULL
);
199 open_json_object(NULL
);
200 if (list
->addr
.family
== AF_PACKET
) {
203 print_string(PRINT_FP
, NULL
, "link ", NULL
);
204 print_color_string(PRINT_ANY
, COLOR_MAC
, "link", "%s",
205 ll_addr_n2a((void *)list
->addr
.data
, list
->addr
.bytelen
,
208 print_string(PRINT_ANY
, "family", "%-5s ",
209 family_name(list
->addr
.family
));
210 print_color_string(PRINT_ANY
, ifa_family_color(list
->addr
.family
),
212 format_host(list
->addr
.family
,
213 -1, list
->addr
.data
));
216 if (list
->users
!= 1)
217 print_uint(PRINT_ANY
, "users", " users %u", list
->users
);
220 print_string(PRINT_ANY
, "features", " %s", list
->features
);
222 print_string(PRINT_FP
, NULL
, "\n", NULL
);
226 static void print_mlist(FILE *fp
, struct ma_info
*list
)
231 for (; list
; list
= list
->next
) {
233 if (list
->index
!= cur_index
|| oneline
) {
235 close_json_array(PRINT_JSON
, NULL
);
238 open_json_object(NULL
);
240 print_uint(PRINT_ANY
, "ifindex", "%d:", list
->index
);
241 print_color_string(PRINT_ANY
, COLOR_IFNAME
,
242 "ifname", "\t%s", list
->name
);
244 cur_index
= list
->index
;
246 open_json_array(PRINT_JSON
, "maddr");
249 print_maddr(fp
, list
);
252 close_json_array(PRINT_JSON
, NULL
);
259 static int multiaddr_list(int argc
, char **argv
)
261 struct ma_info
*list
= NULL
;
264 filter
.family
= preferred_family
;
268 if (strcmp(*argv
, "dev") == 0) {
270 } else if (matches(*argv
, "help") == 0)
273 duparg2("dev", *argv
);
279 if (!filter
.family
|| filter
.family
== AF_PACKET
)
280 read_dev_mcast(&list
);
281 if (!filter
.family
|| filter
.family
== AF_INET
)
283 if (!filter
.family
|| filter
.family
== AF_INET6
)
285 print_mlist(stdout
, list
);
289 static int multiaddr_modify(int cmd
, int argc
, char **argv
)
291 struct ifreq ifr
= {};
295 if (cmd
== RTM_NEWADDR
)
301 if (strcmp(*argv
, "dev") == 0) {
304 duparg("dev", *argv
);
305 if (get_ifname(ifr
.ifr_name
, *argv
))
306 invarg("\"dev\" not a valid ifname", *argv
);
308 if (matches(*argv
, "address") == 0) {
311 if (matches(*argv
, "help") == 0)
313 if (ifr
.ifr_hwaddr
.sa_data
[0])
314 duparg("address", *argv
);
315 if (ll_addr_a2n(ifr
.ifr_hwaddr
.sa_data
,
317 fprintf(stderr
, "Error: \"%s\" is not a legal ll address.\n", *argv
);
323 if (ifr
.ifr_name
[0] == 0) {
324 fprintf(stderr
, "Not enough information: \"dev\" is required.\n");
328 switch (preferred_family
) {
332 family
= preferred_family
;
338 fd
= socket(family
, SOCK_DGRAM
, 0);
340 perror("Cannot create socket");
343 if (ioctl(fd
, cmd
, (char *)&ifr
) != 0) {
353 int do_multiaddr(int argc
, char **argv
)
356 return multiaddr_list(0, NULL
);
357 if (matches(*argv
, "add") == 0)
358 return multiaddr_modify(RTM_NEWADDR
, argc
-1, argv
+1);
359 if (matches(*argv
, "delete") == 0)
360 return multiaddr_modify(RTM_DELADDR
, argc
-1, argv
+1);
361 if (matches(*argv
, "list") == 0 || matches(*argv
, "show") == 0
362 || matches(*argv
, "lst") == 0)
363 return multiaddr_list(argc
-1, argv
+1);
364 if (matches(*argv
, "help") == 0)
366 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip maddr help\".\n", *argv
);