]>
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>
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
24 #include <linux/netdevice.h>
26 #include <linux/if_arp.h>
27 #include <linux/sockios.h>
31 #include "ip_common.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
)) {
55 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
)) {
100 memset(&m
, 0, sizeof(m
));
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 m
.addr
.family
= AF_PACKET
;
108 len
= parse_hex(hexa
, (unsigned char*)&m
.addr
.data
, sizeof (m
.addr
.data
));
110 struct ma_info
*ma
= malloc(sizeof(m
));
112 memcpy(ma
, &m
, sizeof(m
));
113 ma
->addr
.bytelen
= len
;
114 ma
->addr
.bitlen
= len
<<3;
116 ma
->features
= "static";
117 maddr_ins(result_p
, ma
);
123 static void read_igmp(struct ma_info
**result_p
)
127 FILE *fp
= fopen("/proc/net/igmp", "r");
131 memset(&m
, 0, sizeof(m
));
132 if (!fgets(buf
, sizeof(buf
), fp
)) {
137 m
.addr
.family
= AF_INET
;
141 while (fgets(buf
, sizeof(buf
), fp
)) {
144 if (buf
[0] != '\t') {
145 sscanf(buf
, "%d%s", &m
.index
, m
.name
);
149 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
152 sscanf(buf
, "%08x%d", (__u32
*)&m
.addr
.data
, &m
.users
);
154 ma
= malloc(sizeof(m
));
155 memcpy(ma
, &m
, sizeof(m
));
156 maddr_ins(result_p
, ma
);
162 static void read_igmp6(struct ma_info
**result_p
)
165 FILE *fp
= fopen("/proc/net/igmp6", "r");
170 while (fgets(buf
, sizeof(buf
), fp
)) {
175 memset(&m
, 0, sizeof(m
));
176 sscanf(buf
, "%d%s%s%d", &m
.index
, m
.name
, hexa
, &m
.users
);
178 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
181 m
.addr
.family
= AF_INET6
;
183 len
= parse_hex(hexa
, (unsigned char*)&m
.addr
.data
, sizeof (m
.addr
.data
));
185 struct ma_info
*ma
= malloc(sizeof(m
));
187 memcpy(ma
, &m
, sizeof(m
));
189 ma
->addr
.bytelen
= len
;
190 ma
->addr
.bitlen
= len
<<3;
191 maddr_ins(result_p
, ma
);
197 static void print_maddr(FILE *fp
, struct ma_info
*list
)
201 if (list
->addr
.family
== AF_PACKET
) {
203 fprintf(fp
, "link %s", ll_addr_n2a((unsigned char*)list
->addr
.data
,
204 list
->addr
.bytelen
, 0,
208 switch(list
->addr
.family
) {
210 fprintf(fp
, "inet ");
213 fprintf(fp
, "inet6 ");
216 fprintf(fp
, "family %d ", list
->addr
.family
);
220 format_host(list
->addr
.family
,
223 abuf
, sizeof(abuf
)));
225 if (list
->users
!= 1)
226 fprintf(fp
, " users %d", list
->users
);
228 fprintf(fp
, " %s", list
->features
);
232 static void print_mlist(FILE *fp
, struct ma_info
*list
)
236 for (; list
; list
= list
->next
) {
238 cur_index
= list
->index
;
239 fprintf(fp
, "%d:\t%s%s", cur_index
, list
->name
, _SL_
);
240 } else if (cur_index
!= list
->index
) {
241 cur_index
= list
->index
;
242 fprintf(fp
, "%d:\t%s\n", cur_index
, list
->name
);
244 print_maddr(fp
, list
);
248 static int multiaddr_list(int argc
, char **argv
)
250 struct ma_info
*list
= NULL
;
253 filter
.family
= preferred_family
;
257 if (strcmp(*argv
, "dev") == 0) {
260 if (matches(*argv
, "help") == 0)
263 duparg2("dev", *argv
);
269 if (!filter
.family
|| filter
.family
== AF_PACKET
)
270 read_dev_mcast(&list
);
271 if (!filter
.family
|| filter
.family
== AF_INET
)
273 if (!filter
.family
|| filter
.family
== AF_INET6
)
275 print_mlist(stdout
, list
);
279 static int multiaddr_modify(int cmd
, int argc
, char **argv
)
284 memset(&ifr
, 0, sizeof(ifr
));
286 if (cmd
== RTM_NEWADDR
)
292 if (strcmp(*argv
, "dev") == 0) {
295 duparg("dev", *argv
);
296 strncpy(ifr
.ifr_name
, *argv
, IFNAMSIZ
);
298 if (matches(*argv
, "address") == 0) {
301 if (matches(*argv
, "help") == 0)
303 if (ifr
.ifr_hwaddr
.sa_data
[0])
304 duparg("address", *argv
);
305 if (ll_addr_a2n(ifr
.ifr_hwaddr
.sa_data
,
307 fprintf(stderr
, "Error: \"%s\" is not a legal ll address.\n", *argv
);
313 if (ifr
.ifr_name
[0] == 0) {
314 fprintf(stderr
, "Not enough information: \"dev\" is required.\n");
318 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
320 perror("Cannot create socket");
323 if (ioctl(fd
, cmd
, (char*)&ifr
) != 0) {
333 int do_multiaddr(int argc
, char **argv
)
336 return multiaddr_list(0, NULL
);
337 if (matches(*argv
, "add") == 0)
338 return multiaddr_modify(RTM_NEWADDR
, argc
-1, argv
+1);
339 if (matches(*argv
, "delete") == 0)
340 return multiaddr_modify(RTM_DELADDR
, argc
-1, argv
+1);
341 if (matches(*argv
, "list") == 0 || matches(*argv
, "show") == 0
342 || matches(*argv
, "lst") == 0)
343 return multiaddr_list(argc
-1, argv
+1);
344 if (matches(*argv
, "help") == 0)
346 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip maddr help\".\n", *argv
);