]>
git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/mcast.c
6f97d39d950dc7981dfcf5c1fb6d4dc81a6d6174
2 * Copyright (c) 2007 Bruce M. Simpson <bms@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
31 * Print the running system's current multicast group memberships.
32 * As this relies on getifmaddrs(), it may not be used with a core file.
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/sysctl.h>
38 #include <sys/ioctl.h>
39 #include <sys/socket.h>
40 #include <sys/errno.h>
43 #include <net/if_var.h>
44 #include <net/if_mib.h>
45 #include <net/if_types.h>
46 #include <net/if_dl.h>
47 #include <net/route.h>
48 #include <netinet/in.h>
49 #include <netinet/if_ether.h>
50 #include <arpa/inet.h>
70 struct sockaddr_storage ss
;
72 struct sockaddr_dl sdl
;
73 struct sockaddr_in sin
;
74 struct sockaddr_in6 sin6
;
76 typedef union sockunion sockunion_t
;
79 * This may have been defined in <net/if.h>. Note that if <net/if.h> is
80 * to be included it must be included before this header file.
83 #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
87 struct ifmaddrs
*ifma_next
;
88 struct sockaddr
*ifma_name
;
89 struct sockaddr
*ifma_addr
;
90 struct sockaddr
*ifma_lladdr
;
93 void ifmalist_dump_af(const struct ifmaddrs
* const ifmap
, int const af
);
95 #define SALIGN (sizeof(long) - 1)
96 #define SA_RLEN(sa) (sa ? ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \
98 #define MAX_SYSCTL_TRY 5
99 #define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
101 int getifmaddrs(struct ifmaddrs
**);
102 void freeifmaddrs(struct ifmaddrs
*);
106 getifmaddrs(struct ifmaddrs
**pif
)
119 struct ifma_msghdr2
*ifmam
;
120 struct ifmaddrs
*ifa
, *ift
;
121 struct rt_msghdr
*rtm
;
126 mib
[2] = 0; /* protocol */
127 mib
[3] = 0; /* wildcard address family */
128 mib
[4] = NET_RT_IFLIST2
;
129 mib
[5] = 0; /* no flags */
131 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
133 if ((buf
= malloc(needed
)) == NULL
)
135 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0) {
136 if (errno
!= ENOMEM
|| ++ntry
>= MAX_SYSCTL_TRY
) {
143 } while (buf
== NULL
);
145 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
146 rtm
= (struct rt_msghdr
*)(void *)next
;
147 if (rtm
->rtm_version
!= RTM_VERSION
)
149 switch (rtm
->rtm_type
) {
151 ifmam
= (struct ifma_msghdr2
*)(void *)rtm
;
152 if ((ifmam
->ifmam_addrs
& RTA_IFA
) == 0)
155 p
= (char *)(ifmam
+ 1);
156 for (i
= 0; i
< RTAX_MAX
; i
++) {
157 if ((RTA_MASKS
& ifmam
->ifmam_addrs
&
160 sa
= (struct sockaddr
*)(void *)p
;
169 data
= malloc(sizeof(struct ifmaddrs
) * icnt
+ dcnt
);
175 ifa
= (struct ifmaddrs
*)(void *)data
;
176 data
+= sizeof(struct ifmaddrs
) * icnt
;
178 memset(ifa
, 0, sizeof(struct ifmaddrs
) * icnt
);
181 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
182 rtm
= (struct rt_msghdr
*)(void *)next
;
183 if (rtm
->rtm_version
!= RTM_VERSION
)
186 switch (rtm
->rtm_type
) {
188 ifmam
= (struct ifma_msghdr2
*)(void *)rtm
;
189 if ((ifmam
->ifmam_addrs
& RTA_IFA
) == 0)
192 p
= (char *)(ifmam
+ 1);
193 for (i
= 0; i
< RTAX_MAX
; i
++) {
194 if ((RTA_MASKS
& ifmam
->ifmam_addrs
&
197 sa
= (struct sockaddr
*)(void *)p
;
202 (struct sockaddr
*)(void *)data
;
203 memcpy(data
, p
, len
);
209 (struct sockaddr
*)(void *)data
;
210 memcpy(data
, p
, len
);
216 (struct sockaddr
*)(void *)data
;
217 memcpy(data
, p
, len
);
227 ift
->ifma_next
= ift
+ 1;
228 ift
= ift
->ifma_next
;
237 ift
->ifma_next
= NULL
;
247 freeifmaddrs(struct ifmaddrs
*ifmp
)
254 ifmalist_dump_af(const struct ifmaddrs
* const ifmap
, int const af
)
256 const struct ifmaddrs
*ifma
;
258 char myifname
[IFNAMSIZ
];
260 char addrbuf
[INET6_ADDRSTRLEN
];
263 char *pafname
, *pifname
, *plladdr
= NULL
, *pgroup
= NULL
;
278 pafname
= "Link-layer";
284 fprintf(stdout
, "%s Multicast Group Memberships\n", pafname
);
285 fprintf(stdout
, "%-20s\t%-16s\t%s\n", "Group", "Link-layer Address",
288 for (ifma
= ifmap
; ifma
; ifma
= ifma
->ifma_next
) {
290 if (ifma
->ifma_name
== NULL
|| ifma
->ifma_addr
== NULL
)
294 psa
= (sockunion_t
*)ifma
->ifma_addr
;
295 if (psa
->sa
.sa_family
!= af
)
298 switch (psa
->sa
.sa_family
) {
300 pgroup
= inet_ntoa(psa
->sin
.sin_addr
);
304 in6addr
= &psa
->sin6
.sin6_addr
;
305 inet_ntop(psa
->sa
.sa_family
, in6addr
, addrbuf
,
311 if ((psa
->sdl
.sdl_alen
== ETHER_ADDR_LEN
) ||
312 (psa
->sdl
.sdl_type
== IFT_ETHER
)) {
314 ether_ntoa((struct ether_addr
*)&psa
->sdl
.sdl_data
);
317 pgroup
= addr2ascii(AF_LINK
,
319 sizeof(struct sockaddr_dl
),
328 /* Link-layer mapping, if any */
329 psa
= (sockunion_t
*)ifma
->ifma_lladdr
;
331 if (psa
->sa
.sa_family
== AF_LINK
) {
332 if ((psa
->sdl
.sdl_alen
== ETHER_ADDR_LEN
) ||
333 (psa
->sdl
.sdl_type
== IFT_ETHER
)) {
336 ether_ntoa((struct ether_addr
*)&psa
->sdl
.sdl_data
);
339 /* something more exotic */
340 plladdr
= addr2ascii(AF_LINK
,
342 sizeof(struct sockaddr_dl
),
349 /* not a link-layer address */
350 plladdr
= "<invalid>";
352 for (i
= 0; psa
->sa
.sa_len
> 2 && i
< psa
->sa
.sa_len
- 2; i
++)
353 printf("0x%x ", psa
->sa
.sa_data
[i
]);
360 /* Interface upon which the membership exists */
361 psa
= (sockunion_t
*)ifma
->ifma_name
;
362 if (psa
!= NULL
&& psa
->sa
.sa_family
== AF_LINK
) {
363 strlcpy(myifname
, link_ntoa(&psa
->sdl
), IFNAMSIZ
);
364 pcolon
= strchr(myifname
, ':');
372 fprintf(stdout
, "%-20s\t%-16s\t%s\n", pgroup
, plladdr
, pifname
);
379 struct ifmaddrs
*ifmap
;
381 if (getifmaddrs(&ifmap
))
382 err(EX_OSERR
, "getifmaddrs");
384 ifmalist_dump_af(ifmap
, AF_LINK
);
386 ifmalist_dump_af(ifmap
, AF_INET
);
389 ifmalist_dump_af(ifmap
, AF_INET6
);