Blame view

net/core/dev_mcast.c 5.52 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
2
   *	Linux NET3:	Multicast List maintenance.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
   *
   *	Authors:
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
5
   *		Tim Kordas <tjk@nostromo.eeap.cwru.edu>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
   *		Richard Underwood <richard@wuzz.demon.co.uk>
   *
   *	Stir fried together from the IP multicast and CAP patches above
113aa838e   Alan Cox   net: Rationalise ...
9
   *		Alan Cox <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
17
18
19
20
21
22
   *
   *	Fixes:
   *		Alan Cox	:	Update the device on a real delete
   *					rather than any time but...
   *		Alan Cox	:	IFF_ALLMULTI support.
   *		Alan Cox	: 	New format set_multicast_list() calls.
   *		Gleb Natapov    :       Remove dev_mc_lock.
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
bf0d52492   Dave Jones   [NET]: Remove unn...
23
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <linux/bitops.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  #include <linux/string.h>
  #include <linux/mm.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
  #include <linux/in.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/if_ether.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/init.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
43
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
  #include <net/ip.h>
  #include <net/route.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <net/arp.h>
  
  
  /*
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
52
   *	Device multicast list maintenance.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
   *
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
54
55
56
   *	This is used both by IP and by the user level maintenance functions.
   *	Unlike BSD we maintain a usage count on a given multicast address so
   *	that a casual user application can add/delete multicasts used by
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
   *	protocols without doing damage to the protocols when it deletes the
   *	entries. It also helps IP as it tracks overlapping maps.
   *
   *	Device mc lists are changed by bh at least if IPv6 is enabled,
   *	so that it must be bh protected.
   *
932ff279a   Herbert Xu   [NET]: Add netif_...
63
   *	We block accesses to device mc filters with netif_tx_lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
   */
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
   *	Delete a device level multicast
   */
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
69

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
  {
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
72
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

b9e408576   David S. Miller   netdev: Do not us...
74
  	netif_addr_lock_bh(dev);
61cbc2fca   Patrick McHardy   [NET]: Fix second...
75
76
  	err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
  				addr, alen, glbl);
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
77
  	if (!err) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  		/*
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
79
80
  		 *	We have altered the list, so the card
  		 *	loaded filter is now wrong. Fix it
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  		 */
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
82

4417da668   Patrick McHardy   [NET]: dev: secon...
83
  		__dev_set_rx_mode(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	}
b9e408576   David S. Miller   netdev: Do not us...
85
  	netif_addr_unlock_bh(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
  	return err;
  }
  
  /*
   *	Add a device level multicast
   */
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
92

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
  {
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
95
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96

b9e408576   David S. Miller   netdev: Do not us...
97
  	netif_addr_lock_bh(dev);
61cbc2fca   Patrick McHardy   [NET]: Fix second...
98
99
  	err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
  	if (!err)
4417da668   Patrick McHardy   [NET]: dev: secon...
100
  		__dev_set_rx_mode(dev);
b9e408576   David S. Miller   netdev: Do not us...
101
  	netif_addr_unlock_bh(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  	return err;
  }
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
104
105
106
107
108
109
110
111
112
113
  /**
   *	dev_mc_sync	- Synchronize device's multicast list to another device
   *	@to: destination device
   *	@from: source device
   *
   * 	Add newly added addresses to the destination device and release
   * 	addresses that have no users left. The source device must be
   * 	locked by netif_tx_lock_bh.
   *
   *	This function is intended to be called from the dev->set_multicast_list
e83a2ea85   Chris Leech   [VLAN]: set_rx_mo...
114
   *	or dev->set_rx_mode function of layered software devices.
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
115
116
117
   */
  int dev_mc_sync(struct net_device *to, struct net_device *from)
  {
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
118
  	int err = 0;
b9e408576   David S. Miller   netdev: Do not us...
119
  	netif_addr_lock_bh(to);
e83a2ea85   Chris Leech   [VLAN]: set_rx_mo...
120
121
  	err = __dev_addr_sync(&to->mc_list, &to->mc_count,
  			      &from->mc_list, &from->mc_count);
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
122
123
  	if (!err)
  		__dev_set_rx_mode(to);
b9e408576   David S. Miller   netdev: Do not us...
124
  	netif_addr_unlock_bh(to);
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  
  	return err;
  }
  EXPORT_SYMBOL(dev_mc_sync);
  
  
  /**
   * 	dev_mc_unsync	- Remove synchronized addresses from the destination
   * 			  device
   *	@to: destination device
   *	@from: source device
   *
   * 	Remove all addresses that were added to the destination device by
   * 	dev_mc_sync(). This function is intended to be called from the
   * 	dev->stop function of layered software devices.
   */
  void dev_mc_unsync(struct net_device *to, struct net_device *from)
  {
b9e408576   David S. Miller   netdev: Do not us...
143
  	netif_addr_lock_bh(from);
e308a5d80   David S. Miller   netdev: Add netde...
144
  	netif_addr_lock(to);
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
145

e83a2ea85   Chris Leech   [VLAN]: set_rx_mo...
146
147
  	__dev_addr_unsync(&to->mc_list, &to->mc_count,
  			  &from->mc_list, &from->mc_count);
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
148
  	__dev_set_rx_mode(to);
e308a5d80   David S. Miller   netdev: Add netde...
149
  	netif_addr_unlock(to);
b9e408576   David S. Miller   netdev: Do not us...
150
  	netif_addr_unlock_bh(from);
a0a400d79   Patrick McHardy   [NET]: dev_mcast:...
151
152
  }
  EXPORT_SYMBOL(dev_mc_unsync);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  #ifdef CONFIG_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
  static int dev_mc_seq_show(struct seq_file *seq, void *v)
  {
3fba5a8b1   Patrick McHardy   [NET]: dev_mcast:...
156
  	struct dev_addr_list *m;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  	struct net_device *dev = v;
95a363582   Pavel Emelyanov   [NET]: Use existi...
158
159
  	if (v == SEQ_START_TOKEN)
  		return 0;
b9e408576   David S. Miller   netdev: Do not us...
160
  	netif_addr_lock_bh(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
167
168
169
170
171
172
  	for (m = dev->mc_list; m; m = m->next) {
  		int i;
  
  		seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
  			   dev->name, m->dmi_users, m->dmi_gusers);
  
  		for (i = 0; i < m->dmi_addrlen; i++)
  			seq_printf(seq, "%02x", m->dmi_addr[i]);
  
  		seq_putc(seq, '
  ');
  	}
b9e408576   David S. Miller   netdev: Do not us...
173
  	netif_addr_unlock_bh(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
  	return 0;
  }
f690808e1   Stephen Hemminger   [NET]: make seq_o...
176
  static const struct seq_operations dev_mc_seq_ops = {
95a363582   Pavel Emelyanov   [NET]: Use existi...
177
178
179
  	.start = dev_seq_start,
  	.next  = dev_seq_next,
  	.stop  = dev_seq_stop,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
  	.show  = dev_mc_seq_show,
  };
  
  static int dev_mc_seq_open(struct inode *inode, struct file *file)
  {
e372c4140   Denis V. Lunev   [NET]: Consolidat...
185
186
  	return seq_open_net(inode, file, &dev_mc_seq_ops,
  			    sizeof(struct seq_net_private));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
188
  static const struct file_operations dev_mc_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
  	.owner	 = THIS_MODULE,
  	.open    = dev_mc_seq_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
e372c4140   Denis V. Lunev   [NET]: Consolidat...
193
  	.release = seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
  };
  
  #endif
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
197
  static int __net_init dev_mc_net_init(struct net *net)
881d966b4   Eric W. Biederman   [NET]: Make the d...
198
199
200
201
202
  {
  	if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
  		return -ENOMEM;
  	return 0;
  }
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
203
  static void __net_exit dev_mc_net_exit(struct net *net)
881d966b4   Eric W. Biederman   [NET]: Make the d...
204
205
206
  {
  	proc_net_remove(net, "dev_mcast");
  }
022cbae61   Denis V. Lunev   [NET]: Move unnee...
207
  static struct pernet_operations __net_initdata dev_mc_net_ops = {
881d966b4   Eric W. Biederman   [NET]: Make the d...
208
209
210
  	.init = dev_mc_net_init,
  	.exit = dev_mc_net_exit,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  void __init dev_mcast_init(void)
  {
881d966b4   Eric W. Biederman   [NET]: Make the d...
213
  	register_pernet_subsys(&dev_mc_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
  }
  
  EXPORT_SYMBOL(dev_mc_add);
  EXPORT_SYMBOL(dev_mc_delete);