]>
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>
37 static void usage(void) __attribute__((noreturn
));
39 static void usage(void)
41 fprintf(stderr
, "Usage: ip maddr [ add | del ] MULTIADDR dev STRING\n");
42 fprintf(stderr
, " ip maddr show [ dev STRING ]\n");
46 static int parse_hex(char *str
, unsigned char *addr
)
54 if (sscanf(str
, "%02x", &tmp
) != 1)
73 void maddr_ins(struct ma_info
**lst
, struct ma_info
*m
)
77 for (; (mp
=*lst
) != NULL
; lst
= &mp
->next
) {
78 if (mp
->index
> m
->index
)
85 void read_dev_mcast(struct ma_info
**result_p
)
88 FILE *fp
= fopen("/proc/net/dev_mcast", "r");
93 while (fgets(buf
, sizeof(buf
), fp
)) {
99 memset(&m
, 0, sizeof(m
));
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 m
.addr
.family
= AF_PACKET
;
107 len
= parse_hex(hexa
, (unsigned char*)&m
.addr
.data
);
109 struct ma_info
*ma
= malloc(sizeof(m
));
111 memcpy(ma
, &m
, sizeof(m
));
112 ma
->addr
.bytelen
= len
;
113 ma
->addr
.bitlen
= len
<<3;
115 ma
->features
= "static";
116 maddr_ins(result_p
, ma
);
122 void read_igmp(struct ma_info
**result_p
)
126 FILE *fp
= fopen("/proc/net/igmp", "r");
130 memset(&m
, 0, sizeof(m
));
131 fgets(buf
, sizeof(buf
), fp
);
133 m
.addr
.family
= AF_INET
;
137 while (fgets(buf
, sizeof(buf
), fp
)) {
138 struct ma_info
*ma
= malloc(sizeof(m
));
140 if (buf
[0] != '\t') {
141 sscanf(buf
, "%d%s", &m
.index
, m
.name
);
145 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
148 sscanf(buf
, "%08x%d", (__u32
*)&m
.addr
.data
, &m
.users
);
150 ma
= malloc(sizeof(m
));
151 memcpy(ma
, &m
, sizeof(m
));
152 maddr_ins(result_p
, ma
);
158 void read_igmp6(struct ma_info
**result_p
)
161 FILE *fp
= fopen("/proc/net/igmp6", "r");
166 while (fgets(buf
, sizeof(buf
), fp
)) {
171 memset(&m
, 0, sizeof(m
));
172 sscanf(buf
, "%d%s%s%d", &m
.index
, m
.name
, hexa
, &m
.users
);
174 if (filter
.dev
&& strcmp(filter
.dev
, m
.name
))
177 m
.addr
.family
= AF_INET6
;
179 len
= parse_hex(hexa
, (unsigned char*)&m
.addr
.data
);
181 struct ma_info
*ma
= malloc(sizeof(m
));
183 memcpy(ma
, &m
, sizeof(m
));
185 ma
->addr
.bytelen
= len
;
186 ma
->addr
.bitlen
= len
<<3;
187 maddr_ins(result_p
, ma
);
193 static void print_maddr(FILE *fp
, struct ma_info
*list
)
197 if (list
->addr
.family
== AF_PACKET
) {
199 fprintf(fp
, "link %s", ll_addr_n2a((unsigned char*)list
->addr
.data
,
200 list
->addr
.bytelen
, 0,
204 switch(list
->addr
.family
) {
206 fprintf(fp
, "inet ");
209 fprintf(fp
, "inet6 ");
212 fprintf(fp
, "family %d ", list
->addr
.family
);
216 format_host(list
->addr
.family
,
219 abuf
, sizeof(abuf
)));
221 if (list
->users
!= 1)
222 fprintf(fp
, " users %d", list
->users
);
224 fprintf(fp
, " %s", list
->features
);
228 static void print_mlist(FILE *fp
, struct ma_info
*list
)
232 for (; list
; list
= list
->next
) {
234 cur_index
= list
->index
;
235 fprintf(fp
, "%d:\t%s%s", cur_index
, list
->name
, _SL_
);
236 } else if (cur_index
!= list
->index
) {
237 cur_index
= list
->index
;
238 fprintf(fp
, "%d:\t%s\n", cur_index
, list
->name
);
240 print_maddr(fp
, list
);
244 static int multiaddr_list(int argc
, char **argv
)
246 struct ma_info
*list
= NULL
;
249 filter
.family
= preferred_family
;
253 if (strcmp(*argv
, "dev") == 0) {
256 if (matches(*argv
, "help") == 0)
259 duparg2("dev", *argv
);
265 if (!filter
.family
|| filter
.family
== AF_PACKET
)
266 read_dev_mcast(&list
);
267 if (!filter
.family
|| filter
.family
== AF_INET
)
269 if (!filter
.family
|| filter
.family
== AF_INET6
)
271 print_mlist(stdout
, list
);
275 int multiaddr_modify(int cmd
, int argc
, char **argv
)
280 memset(&ifr
, 0, sizeof(ifr
));
282 if (cmd
== RTM_NEWADDR
)
288 if (strcmp(*argv
, "dev") == 0) {
291 duparg("dev", *argv
);
292 strncpy(ifr
.ifr_name
, *argv
, IFNAMSIZ
);
294 if (matches(*argv
, "address") == 0) {
297 if (matches(*argv
, "help") == 0)
299 if (ifr
.ifr_hwaddr
.sa_data
[0])
300 duparg("address", *argv
);
301 if (ll_addr_a2n(ifr
.ifr_hwaddr
.sa_data
,
303 fprintf(stderr
, "Error: \"%s\" is not a legal ll address.\n", *argv
);
309 if (ifr
.ifr_name
[0] == 0) {
310 fprintf(stderr
, "Not enough information: \"dev\" is required.\n");
314 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
316 perror("Cannot create socket");
319 if (ioctl(fd
, cmd
, (char*)&ifr
) != 0) {
329 int do_multiaddr(int argc
, char **argv
)
332 return multiaddr_list(0, NULL
);
333 if (matches(*argv
, "add") == 0)
334 return multiaddr_modify(RTM_NEWADDR
, argc
-1, argv
+1);
335 if (matches(*argv
, "delete") == 0)
336 return multiaddr_modify(RTM_DELADDR
, argc
-1, argv
+1);
337 if (matches(*argv
, "list") == 0 || matches(*argv
, "show") == 0
338 || matches(*argv
, "lst") == 0)
339 return multiaddr_list(argc
-1, argv
+1);
340 if (matches(*argv
, "help") == 0)
342 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip maddr help\".\n", *argv
);