]>
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)
43 "Usage: ip maddr [ add | del ] MULTIADDR dev STRING\n"
44 " ip maddr show [ dev STRING ]\n");
48 static int parse_hex(char *str
, unsigned char *addr
, size_t size
)
52 while (*str
&& (len
< 2 * size
)) {
57 if (sscanf(str
, "%02x", &tmp
) != 1)
75 static void maddr_ins(struct ma_info
**lst
, struct ma_info
*m
)
79 for (; (mp
= *lst
) != NULL
; lst
= &mp
->next
) {
80 if (mp
->index
> m
->index
)
87 static void read_dev_mcast(struct ma_info
**result_p
)
90 FILE *fp
= fopen("/proc/net/dev_mcast", "r");
95 while (fgets(buf
, sizeof(buf
), fp
)) {
97 struct ma_info m
= { .addr
.family
= AF_PACKET
};
101 sscanf(buf
, "%d%s%d%d%s", &m
.index
, m
.name
, &m
.users
, &st
,
103 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
106 len
= parse_hex(hexa
, (unsigned char *)&m
.addr
.data
, sizeof(m
.addr
.data
));
108 struct ma_info
*ma
= malloc(sizeof(m
));
110 memcpy(ma
, &m
, sizeof(m
));
111 ma
->addr
.bytelen
= len
;
112 ma
->addr
.bitlen
= len
<<3;
114 ma
->features
= "static";
115 maddr_ins(result_p
, ma
);
121 static void read_igmp(struct ma_info
**result_p
)
124 .addr
.family
= AF_INET
,
129 FILE *fp
= fopen("/proc/net/igmp", "r");
133 if (!fgets(buf
, sizeof(buf
), fp
)) {
138 while (fgets(buf
, sizeof(buf
), fp
)) {
141 if (buf
[0] != '\t') {
144 sscanf(buf
, "%d%s", &m
.index
, m
.name
);
145 len
= strlen(m
.name
);
146 if (m
.name
[len
- 1] == ':')
147 m
.name
[len
- 1] = '\0';
151 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
154 sscanf(buf
, "%08x%d", (__u32
*)&m
.addr
.data
, &m
.users
);
156 ma
= malloc(sizeof(m
));
157 memcpy(ma
, &m
, sizeof(m
));
158 maddr_ins(result_p
, ma
);
164 static void read_igmp6(struct ma_info
**result_p
)
167 FILE *fp
= fopen("/proc/net/igmp6", "r");
172 while (fgets(buf
, sizeof(buf
), fp
)) {
174 struct ma_info m
= { .addr
.family
= AF_INET6
};
177 sscanf(buf
, "%d%s%s%d", &m
.index
, m
.name
, hexa
, &m
.users
);
179 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
182 len
= parse_hex(hexa
, (unsigned char *)&m
.addr
.data
, sizeof(m
.addr
.data
));
184 struct ma_info
*ma
= malloc(sizeof(m
));
186 memcpy(ma
, &m
, sizeof(m
));
188 ma
->addr
.bytelen
= len
;
189 ma
->addr
.bitlen
= len
<<3;
190 maddr_ins(result_p
, ma
);
196 static void print_maddr(FILE *fp
, struct ma_info
*list
)
198 print_string(PRINT_FP
, NULL
, "\t", NULL
);
200 open_json_object(NULL
);
201 if (list
->addr
.family
== AF_PACKET
) {
204 print_string(PRINT_FP
, NULL
, "link ", NULL
);
205 print_color_string(PRINT_ANY
, COLOR_MAC
, "link", "%s",
206 ll_addr_n2a((void *)list
->addr
.data
, list
->addr
.bytelen
,
209 print_string(PRINT_ANY
, "family", "%-5s ",
210 family_name(list
->addr
.family
));
211 print_color_string(PRINT_ANY
, ifa_family_color(list
->addr
.family
),
213 format_host(list
->addr
.family
,
214 -1, list
->addr
.data
));
217 if (list
->users
!= 1)
218 print_uint(PRINT_ANY
, "users", " users %u", list
->users
);
221 print_string(PRINT_ANY
, "features", " %s", list
->features
);
223 print_string(PRINT_FP
, NULL
, "\n", NULL
);
227 static void print_mlist(FILE *fp
, struct ma_info
*list
)
232 for (; list
; list
= list
->next
) {
234 if (list
->index
!= cur_index
|| oneline
) {
236 close_json_array(PRINT_JSON
, NULL
);
239 open_json_object(NULL
);
241 print_uint(PRINT_ANY
, "ifindex", "%d:", list
->index
);
242 print_color_string(PRINT_ANY
, COLOR_IFNAME
,
243 "ifname", "\t%s", list
->name
);
245 cur_index
= list
->index
;
247 open_json_array(PRINT_JSON
, "maddr");
250 print_maddr(fp
, list
);
253 close_json_array(PRINT_JSON
, NULL
);
260 static int multiaddr_list(int argc
, char **argv
)
262 struct ma_info
*list
= NULL
;
265 filter
.family
= preferred_family
;
269 if (strcmp(*argv
, "dev") == 0) {
271 } else if (matches(*argv
, "help") == 0)
274 duparg2("dev", *argv
);
280 if (!filter
.family
|| filter
.family
== AF_PACKET
)
281 read_dev_mcast(&list
);
282 if (!filter
.family
|| filter
.family
== AF_INET
)
284 if (!filter
.family
|| filter
.family
== AF_INET6
)
286 print_mlist(stdout
, list
);
290 static int multiaddr_modify(int cmd
, int argc
, char **argv
)
292 struct ifreq ifr
= {};
296 if (cmd
== RTM_NEWADDR
)
302 if (strcmp(*argv
, "dev") == 0) {
305 duparg("dev", *argv
);
306 if (get_ifname(ifr
.ifr_name
, *argv
))
307 invarg("\"dev\" not a valid ifname", *argv
);
309 if (matches(*argv
, "address") == 0) {
312 if (matches(*argv
, "help") == 0)
314 if (ifr
.ifr_hwaddr
.sa_data
[0])
315 duparg("address", *argv
);
316 len
= ll_addr_a2n(ifr
.ifr_hwaddr
.sa_data
,
317 sizeof(ifr
.ifr_hwaddr
.sa_data
),
322 if (len
!= ETH_ALEN
) {
323 fprintf(stderr
, "Error: Invalid address length %d - must be %d bytes\n", len
, ETH_ALEN
);
329 if (ifr
.ifr_name
[0] == 0) {
330 fprintf(stderr
, "Not enough information: \"dev\" is required.\n");
334 switch (preferred_family
) {
338 family
= preferred_family
;
344 fd
= socket(family
, SOCK_DGRAM
, 0);
346 perror("Cannot create socket");
349 if (ioctl(fd
, cmd
, (char *)&ifr
) != 0) {
359 int do_multiaddr(int argc
, char **argv
)
362 return multiaddr_list(0, NULL
);
363 if (matches(*argv
, "add") == 0)
364 return multiaddr_modify(RTM_NEWADDR
, argc
-1, argv
+1);
365 if (matches(*argv
, "delete") == 0)
366 return multiaddr_modify(RTM_DELADDR
, argc
-1, argv
+1);
367 if (matches(*argv
, "list") == 0 || matches(*argv
, "show") == 0
368 || matches(*argv
, "lst") == 0)
369 return multiaddr_list(argc
-1, argv
+1);
370 if (matches(*argv
, "help") == 0)
372 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip maddr help\".\n", *argv
);