* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: mcast.c,v 1.40 2002/02/08 03:57:19 davem Exp $
- *
* Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
*
* This program is free software; you can redistribute it and/or
/* Big mc list lock for all the sockets */
static DEFINE_RWLOCK(ipv6_sk_mc_lock);
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
-
static void igmp6_join_group(struct ifmcaddr6 *ma);
static void igmp6_leave_group(struct ifmcaddr6 *ma);
static void igmp6_timer_handler(unsigned long data);
#define IGMP6_UNSOLICITED_IVAL (10*HZ)
#define MLD_QRV_DEFAULT 2
-#define MLD_V1_SEEN(idev) (ipv6_devconf.force_mld_version == 1 || \
+#define MLD_V1_SEEN(idev) (dev_net((idev)->dev)->ipv6.devconf_all->force_mld_version == 1 || \
(idev)->cnf.force_mld_version == 1 || \
((idev)->mc_v1_seen && \
time_before(jiffies, (idev)->mc_v1_seen)))
((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
(MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
-#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value)
#define IPV6_MLD_MAX_MSF 64
* socket join on multicast group
*/
-int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
{
struct net_device *dev = NULL;
struct ipv6_mc_socklist *mc_lst;
/*
* socket leave on multicast group
*/
-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6_mc_socklist *mc_lst, **lnk;
int pmclocked = 0;
int err;
- if (pgsr->gsr_group.ss_family != AF_INET6 ||
- pgsr->gsr_source.ss_family != AF_INET6)
- return -EINVAL;
-
source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr;
group = &((struct sockaddr_in6 *)&pgsr->gsr_group)->sin6_addr;
return err;
}
-int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
- struct in6_addr *src_addr)
+int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
+ const struct in6_addr *src_addr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6_mc_socklist *mc;
/*
* device multicast group inc (add if not found)
*/
-int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
{
struct ifmcaddr6 *mc;
struct inet6_dev *idev;
/*
* device multicast group del
*/
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
{
struct ifmcaddr6 *ma, **map;
return -ENOENT;
}
-int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
{
struct inet6_dev *idev = in6_dev_get(dev);
int err;
/*
* check if the interface/address pair is valid
*/
-int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
- struct in6_addr *src_addr)
+int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
+ const struct in6_addr *src_addr)
{
struct inet6_dev *idev;
struct ifmcaddr6 *mc;
struct sk_buff *skb;
struct mld2_report *pmr;
struct in6_addr addr_buf;
+ const struct in6_addr *saddr;
int err;
u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 };
/* we assume size > sizeof(ra) here */
- skb = sock_alloc_send_skb(sk, size + LL_RESERVED_SPACE(dev), 1, &err);
+ skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
if (!skb)
return NULL;
* use unspecified address as the source address
* when a valid link-local address is not available.
*/
- memset(&addr_buf, 0, sizeof(addr_buf));
- }
+ saddr = &in6addr_any;
+ } else
+ saddr = &addr_buf;
- ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0);
+ ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
int err;
struct flowi fl;
- IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
+ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
mldlen = skb->tail - skb->transport_header;
pip6->payload_len = htons(payload_len);
dst_output);
out:
if (!err) {
- ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
- ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
- IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTMCASTPKTS);
+ ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+ IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
} else
- IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
if (likely(idev != NULL))
in6_dev_put(idev);
struct inet6_dev *idev;
struct sk_buff *skb;
struct icmp6hdr *hdr;
- struct in6_addr *snd_addr;
+ const struct in6_addr *snd_addr, *saddr;
struct in6_addr *addrp;
struct in6_addr addr_buf;
- struct in6_addr all_routers;
int err, len, payload_len, full_len;
u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0,
struct flowi fl;
rcu_read_lock();
- IP6_INC_STATS(__in6_dev_get(dev),
+ IP6_INC_STATS(net, __in6_dev_get(dev),
IPSTATS_MIB_OUTREQUESTS);
rcu_read_unlock();
- snd_addr = addr;
- if (type == ICMPV6_MGM_REDUCTION) {
- snd_addr = &all_routers;
- ipv6_addr_all_routers(&all_routers);
- }
+ if (type == ICMPV6_MGM_REDUCTION)
+ snd_addr = &in6addr_linklocal_allrouters;
+ else
+ snd_addr = addr;
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
payload_len = len + sizeof(ra);
full_len = sizeof(struct ipv6hdr) + payload_len;
- skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err);
+ skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
if (skb == NULL) {
rcu_read_lock();
- IP6_INC_STATS(__in6_dev_get(dev),
+ IP6_INC_STATS(net, __in6_dev_get(dev),
IPSTATS_MIB_OUTDISCARDS);
rcu_read_unlock();
return;
* use unspecified address as the source address
* when a valid link-local address is not available.
*/
- memset(&addr_buf, 0, sizeof(addr_buf));
- }
+ saddr = &in6addr_any;
+ } else
+ saddr = &addr_buf;
- ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
+ ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
ipv6_addr_copy(addrp, addr);
- hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
+ hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len,
IPPROTO_ICMPV6,
csum_partial((__u8 *) hdr, len, 0));
dst_output);
out:
if (!err) {
- ICMP6MSGOUT_INC_STATS(idev, type);
- ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
- IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
+ ICMP6MSGOUT_INC_STATS(net, idev, type);
+ ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
+ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
} else
- IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
+ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
if (likely(idev != NULL))
in6_dev_put(idev);
void ipv6_mc_destroy_dev(struct inet6_dev *idev)
{
struct ifmcaddr6 *i;
- struct in6_addr maddr;
/* Deactivate timers */
ipv6_mc_down(idev);
/* Delete all-nodes address. */
- ipv6_addr_all_nodes(&maddr);
-
/* We cannot call ipv6_dev_mc_dec() directly, our caller in
* addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
* fail.
*/
- __ipv6_dev_mc_dec(idev, &maddr);
+ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
- if (idev->cnf.forwarding) {
- ipv6_addr_all_routers(&maddr);
- __ipv6_dev_mc_dec(idev, &maddr);
- }
+ if (idev->cnf.forwarding)
+ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
write_lock_bh(&idev->lock);
while ((i = idev->mc_list) != NULL) {
struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
seq_printf(seq,
- "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n",
+ "%-4d %-15s %#p6 %5d %08X %ld\n",
state->dev->ifindex, state->dev->name,
- NIP6(im->mca_addr),
+ &im->mca_addr,
im->mca_users, im->mca_flags,
(im->mca_flags&MAF_TIMER_RUNNING) ?
jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0);
"Source Address", "INC", "EXC");
} else {
seq_printf(seq,
- "%3d %6.6s " NIP6_SEQFMT " " NIP6_SEQFMT " %6lu %6lu\n",
+ "%3d %6.6s %#p6 %#p6 %6lu %6lu\n",
state->dev->ifindex, state->dev->name,
- NIP6(state->im->mca_addr),
- NIP6(psf->sf_addr),
+ &state->im->mca_addr,
+ &psf->sf_addr,
psf->sf_count[MCAST_INCLUDE],
psf->sf_count[MCAST_EXCLUDE]);
}