dev_addr_lists.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * net/core/dev_addr_lists.c - Functions for handling net device lists
  3. * Copyright (c) 2010 Jiri Pirko <jpirko@redhat.com>
  4. *
  5. * This file contains functions for working with unicast, multicast and device
  6. * addresses lists.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <linux/netdevice.h>
  14. #include <linux/rtnetlink.h>
  15. #include <linux/list.h>
  16. #include <linux/proc_fs.h>
  17. /*
  18. * General list handling functions
  19. */
  20. static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
  21. unsigned char *addr, int addr_len,
  22. unsigned char addr_type, bool global)
  23. {
  24. struct netdev_hw_addr *ha;
  25. int alloc_size;
  26. if (addr_len > MAX_ADDR_LEN)
  27. return -EINVAL;
  28. list_for_each_entry(ha, &list->list, list) {
  29. if (!memcmp(ha->addr, addr, addr_len) &&
  30. ha->type == addr_type) {
  31. if (global) {
  32. /* check if addr is already used as global */
  33. if (ha->global_use)
  34. return 0;
  35. else
  36. ha->global_use = true;
  37. }
  38. ha->refcount++;
  39. return 0;
  40. }
  41. }
  42. alloc_size = sizeof(*ha);
  43. if (alloc_size < L1_CACHE_BYTES)
  44. alloc_size = L1_CACHE_BYTES;
  45. ha = kmalloc(alloc_size, GFP_ATOMIC);
  46. if (!ha)
  47. return -ENOMEM;
  48. memcpy(ha->addr, addr, addr_len);
  49. ha->type = addr_type;
  50. ha->refcount = 1;
  51. ha->global_use = global;
  52. ha->synced = false;
  53. list_add_tail_rcu(&ha->list, &list->list);
  54. list->count++;
  55. return 0;
  56. }
  57. static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
  58. int addr_len, unsigned char addr_type)
  59. {
  60. return __hw_addr_add_ex(list, addr, addr_len, addr_type, false);
  61. }
  62. static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
  63. unsigned char *addr, int addr_len,
  64. unsigned char addr_type, bool global)
  65. {
  66. struct netdev_hw_addr *ha;
  67. list_for_each_entry(ha, &list->list, list) {
  68. if (!memcmp(ha->addr, addr, addr_len) &&
  69. (ha->type == addr_type || !addr_type)) {
  70. if (global) {
  71. if (!ha->global_use)
  72. break;
  73. else
  74. ha->global_use = false;
  75. }
  76. if (--ha->refcount)
  77. return 0;
  78. list_del_rcu(&ha->list);
  79. kfree_rcu(ha, rcu_head);
  80. list->count--;
  81. return 0;
  82. }
  83. }
  84. return -ENOENT;
  85. }
  86. static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr,
  87. int addr_len, unsigned char addr_type)
  88. {
  89. return __hw_addr_del_ex(list, addr, addr_len, addr_type, false);
  90. }
  91. int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
  92. struct netdev_hw_addr_list *from_list,
  93. int addr_len, unsigned char addr_type)
  94. {
  95. int err;
  96. struct netdev_hw_addr *ha, *ha2;
  97. unsigned char type;
  98. list_for_each_entry(ha, &from_list->list, list) {
  99. type = addr_type ? addr_type : ha->type;
  100. err = __hw_addr_add(to_list, ha->addr, addr_len, type);
  101. if (err)
  102. goto unroll;
  103. }
  104. return 0;
  105. unroll:
  106. list_for_each_entry(ha2, &from_list->list, list) {
  107. if (ha2 == ha)
  108. break;
  109. type = addr_type ? addr_type : ha2->type;
  110. __hw_addr_del(to_list, ha2->addr, addr_len, type);
  111. }
  112. return err;
  113. }
  114. EXPORT_SYMBOL(__hw_addr_add_multiple);
  115. void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
  116. struct netdev_hw_addr_list *from_list,
  117. int addr_len, unsigned char addr_type)
  118. {
  119. struct netdev_hw_addr *ha;
  120. unsigned char type;
  121. list_for_each_entry(ha, &from_list->list, list) {
  122. type = addr_type ? addr_type : ha->type;
  123. __hw_addr_del(to_list, ha->addr, addr_len, type);
  124. }
  125. }
  126. EXPORT_SYMBOL(__hw_addr_del_multiple);
  127. int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
  128. struct netdev_hw_addr_list *from_list,
  129. int addr_len)
  130. {
  131. int err = 0;
  132. struct netdev_hw_addr *ha, *tmp;
  133. list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
  134. if (!ha->synced) {
  135. err = __hw_addr_add(to_list, ha->addr,
  136. addr_len, ha->type);
  137. if (err)
  138. break;
  139. ha->synced = true;
  140. ha->refcount++;
  141. } else if (ha->refcount == 1) {
  142. __hw_addr_del(to_list, ha->addr, addr_len, ha->type);
  143. __hw_addr_del(from_list, ha->addr, addr_len, ha->type);
  144. }
  145. }
  146. return err;
  147. }
  148. EXPORT_SYMBOL(__hw_addr_sync);
  149. void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
  150. struct netdev_hw_addr_list *from_list,
  151. int addr_len)
  152. {
  153. struct netdev_hw_addr *ha, *tmp;
  154. list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
  155. if (ha->synced) {
  156. __hw_addr_del(to_list, ha->addr,
  157. addr_len, ha->type);
  158. ha->synced = false;
  159. __hw_addr_del(from_list, ha->addr,
  160. addr_len, ha->type);
  161. }
  162. }
  163. }
  164. EXPORT_SYMBOL(__hw_addr_unsync);
  165. void __hw_addr_flush(struct netdev_hw_addr_list *list)
  166. {
  167. struct netdev_hw_addr *ha, *tmp;
  168. list_for_each_entry_safe(ha, tmp, &list->list, list) {
  169. list_del_rcu(&ha->list);
  170. kfree_rcu(ha, rcu_head);
  171. }
  172. list->count = 0;
  173. }
  174. EXPORT_SYMBOL(__hw_addr_flush);
  175. void __hw_addr_init(struct netdev_hw_addr_list *list)
  176. {
  177. INIT_LIST_HEAD(&list->list);
  178. list->count = 0;
  179. }
  180. EXPORT_SYMBOL(__hw_addr_init);
  181. /*
  182. * Device addresses handling functions
  183. */
  184. /**
  185. * dev_addr_flush - Flush device address list
  186. * @dev: device
  187. *
  188. * Flush device address list and reset ->dev_addr.
  189. *
  190. * The caller must hold the rtnl_mutex.
  191. */
  192. void dev_addr_flush(struct net_device *dev)
  193. {
  194. /* rtnl_mutex must be held here */
  195. __hw_addr_flush(&dev->dev_addrs);
  196. dev->dev_addr = NULL;
  197. }
  198. EXPORT_SYMBOL(dev_addr_flush);
  199. /**
  200. * dev_addr_init - Init device address list
  201. * @dev: device
  202. *
  203. * Init device address list and create the first element,
  204. * used by ->dev_addr.
  205. *
  206. * The caller must hold the rtnl_mutex.
  207. */
  208. int dev_addr_init(struct net_device *dev)
  209. {
  210. unsigned char addr[MAX_ADDR_LEN];
  211. struct netdev_hw_addr *ha;
  212. int err;
  213. /* rtnl_mutex must be held here */
  214. __hw_addr_init(&dev->dev_addrs);
  215. memset(addr, 0, sizeof(addr));
  216. err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
  217. NETDEV_HW_ADDR_T_LAN);
  218. if (!err) {
  219. /*
  220. * Get the first (previously created) address from the list
  221. * and set dev_addr pointer to this location.
  222. */
  223. ha = list_first_entry(&dev->dev_addrs.list,
  224. struct netdev_hw_addr, list);
  225. dev->dev_addr = ha->addr;
  226. }
  227. return err;
  228. }
  229. EXPORT_SYMBOL(dev_addr_init);
  230. /**
  231. * dev_addr_add - Add a device address
  232. * @dev: device
  233. * @addr: address to add
  234. * @addr_type: address type
  235. *
  236. * Add a device address to the device or increase the reference count if
  237. * it already exists.
  238. *
  239. * The caller must hold the rtnl_mutex.
  240. */
  241. int dev_addr_add(struct net_device *dev, unsigned char *addr,
  242. unsigned char addr_type)
  243. {
  244. int err;
  245. ASSERT_RTNL();
  246. err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type);
  247. if (!err)
  248. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  249. return err;
  250. }
  251. EXPORT_SYMBOL(dev_addr_add);
  252. /**
  253. * dev_addr_del - Release a device address.
  254. * @dev: device
  255. * @addr: address to delete
  256. * @addr_type: address type
  257. *
  258. * Release reference to a device address and remove it from the device
  259. * if the reference count drops to zero.
  260. *
  261. * The caller must hold the rtnl_mutex.
  262. */
  263. int dev_addr_del(struct net_device *dev, unsigned char *addr,
  264. unsigned char addr_type)
  265. {
  266. int err;
  267. struct netdev_hw_addr *ha;
  268. ASSERT_RTNL();
  269. /*
  270. * We can not remove the first address from the list because
  271. * dev->dev_addr points to that.
  272. */
  273. ha = list_first_entry(&dev->dev_addrs.list,
  274. struct netdev_hw_addr, list);
  275. if (ha->addr == dev->dev_addr && ha->refcount == 1)
  276. return -ENOENT;
  277. err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
  278. addr_type);
  279. if (!err)
  280. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  281. return err;
  282. }
  283. EXPORT_SYMBOL(dev_addr_del);
  284. /**
  285. * dev_addr_add_multiple - Add device addresses from another device
  286. * @to_dev: device to which addresses will be added
  287. * @from_dev: device from which addresses will be added
  288. * @addr_type: address type - 0 means type will be used from from_dev
  289. *
  290. * Add device addresses of the one device to another.
  291. **
  292. * The caller must hold the rtnl_mutex.
  293. */
  294. int dev_addr_add_multiple(struct net_device *to_dev,
  295. struct net_device *from_dev,
  296. unsigned char addr_type)
  297. {
  298. int err;
  299. ASSERT_RTNL();
  300. if (from_dev->addr_len != to_dev->addr_len)
  301. return -EINVAL;
  302. err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
  303. to_dev->addr_len, addr_type);
  304. if (!err)
  305. call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
  306. return err;
  307. }
  308. EXPORT_SYMBOL(dev_addr_add_multiple);
  309. /**
  310. * dev_addr_del_multiple - Delete device addresses by another device
  311. * @to_dev: device where the addresses will be deleted
  312. * @from_dev: device supplying the addresses to be deleted
  313. * @addr_type: address type - 0 means type will be used from from_dev
  314. *
  315. * Deletes addresses in to device by the list of addresses in from device.
  316. *
  317. * The caller must hold the rtnl_mutex.
  318. */
  319. int dev_addr_del_multiple(struct net_device *to_dev,
  320. struct net_device *from_dev,
  321. unsigned char addr_type)
  322. {
  323. ASSERT_RTNL();
  324. if (from_dev->addr_len != to_dev->addr_len)
  325. return -EINVAL;
  326. __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
  327. to_dev->addr_len, addr_type);
  328. call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
  329. return 0;
  330. }
  331. EXPORT_SYMBOL(dev_addr_del_multiple);
  332. /*
  333. * Unicast list handling functions
  334. */
  335. /**
  336. * dev_uc_add - Add a secondary unicast address
  337. * @dev: device
  338. * @addr: address to add
  339. *
  340. * Add a secondary unicast address to the device or increase
  341. * the reference count if it already exists.
  342. */
  343. int dev_uc_add(struct net_device *dev, unsigned char *addr)
  344. {
  345. int err;
  346. netif_addr_lock_bh(dev);
  347. err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
  348. NETDEV_HW_ADDR_T_UNICAST);
  349. if (!err)
  350. __dev_set_rx_mode(dev);
  351. netif_addr_unlock_bh(dev);
  352. return err;
  353. }
  354. EXPORT_SYMBOL(dev_uc_add);
  355. /**
  356. * dev_uc_del - Release secondary unicast address.
  357. * @dev: device
  358. * @addr: address to delete
  359. *
  360. * Release reference to a secondary unicast address and remove it
  361. * from the device if the reference count drops to zero.
  362. */
  363. int dev_uc_del(struct net_device *dev, unsigned char *addr)
  364. {
  365. int err;
  366. netif_addr_lock_bh(dev);
  367. err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
  368. NETDEV_HW_ADDR_T_UNICAST);
  369. if (!err)
  370. __dev_set_rx_mode(dev);
  371. netif_addr_unlock_bh(dev);
  372. return err;
  373. }
  374. EXPORT_SYMBOL(dev_uc_del);
  375. /**
  376. * dev_uc_sync - Synchronize device's unicast list to another device
  377. * @to: destination device
  378. * @from: source device
  379. *
  380. * Add newly added addresses to the destination device and release
  381. * addresses that have no users left. The source device must be
  382. * locked by netif_tx_lock_bh.
  383. *
  384. * This function is intended to be called from the dev->set_rx_mode
  385. * function of layered software devices.
  386. */
  387. int dev_uc_sync(struct net_device *to, struct net_device *from)
  388. {
  389. int err = 0;
  390. if (to->addr_len != from->addr_len)
  391. return -EINVAL;
  392. netif_addr_lock_bh(to);
  393. err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
  394. if (!err)
  395. __dev_set_rx_mode(to);
  396. netif_addr_unlock_bh(to);
  397. return err;
  398. }
  399. EXPORT_SYMBOL(dev_uc_sync);
  400. /**
  401. * dev_uc_unsync - Remove synchronized addresses from the destination device
  402. * @to: destination device
  403. * @from: source device
  404. *
  405. * Remove all addresses that were added to the destination device by
  406. * dev_uc_sync(). This function is intended to be called from the
  407. * dev->stop function of layered software devices.
  408. */
  409. void dev_uc_unsync(struct net_device *to, struct net_device *from)
  410. {
  411. if (to->addr_len != from->addr_len)
  412. return;
  413. netif_addr_lock_bh(from);
  414. netif_addr_lock(to);
  415. __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
  416. __dev_set_rx_mode(to);
  417. netif_addr_unlock(to);
  418. netif_addr_unlock_bh(from);
  419. }
  420. EXPORT_SYMBOL(dev_uc_unsync);
  421. /**
  422. * dev_uc_flush - Flush unicast addresses
  423. * @dev: device
  424. *
  425. * Flush unicast addresses.
  426. */
  427. void dev_uc_flush(struct net_device *dev)
  428. {
  429. netif_addr_lock_bh(dev);
  430. __hw_addr_flush(&dev->uc);
  431. netif_addr_unlock_bh(dev);
  432. }
  433. EXPORT_SYMBOL(dev_uc_flush);
  434. /**
  435. * dev_uc_flush - Init unicast address list
  436. * @dev: device
  437. *
  438. * Init unicast address list.
  439. */
  440. void dev_uc_init(struct net_device *dev)
  441. {
  442. __hw_addr_init(&dev->uc);
  443. }
  444. EXPORT_SYMBOL(dev_uc_init);
  445. /*
  446. * Multicast list handling functions
  447. */
  448. static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
  449. bool global)
  450. {
  451. int err;
  452. netif_addr_lock_bh(dev);
  453. err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
  454. NETDEV_HW_ADDR_T_MULTICAST, global);
  455. if (!err)
  456. __dev_set_rx_mode(dev);
  457. netif_addr_unlock_bh(dev);
  458. return err;
  459. }
  460. /**
  461. * dev_mc_add - Add a multicast address
  462. * @dev: device
  463. * @addr: address to add
  464. *
  465. * Add a multicast address to the device or increase
  466. * the reference count if it already exists.
  467. */
  468. int dev_mc_add(struct net_device *dev, unsigned char *addr)
  469. {
  470. return __dev_mc_add(dev, addr, false);
  471. }
  472. EXPORT_SYMBOL(dev_mc_add);
  473. /**
  474. * dev_mc_add_global - Add a global multicast address
  475. * @dev: device
  476. * @addr: address to add
  477. *
  478. * Add a global multicast address to the device.
  479. */
  480. int dev_mc_add_global(struct net_device *dev, unsigned char *addr)
  481. {
  482. return __dev_mc_add(dev, addr, true);
  483. }
  484. EXPORT_SYMBOL(dev_mc_add_global);
  485. static int __dev_mc_del(struct net_device *dev, unsigned char *addr,
  486. bool global)
  487. {
  488. int err;
  489. netif_addr_lock_bh(dev);
  490. err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
  491. NETDEV_HW_ADDR_T_MULTICAST, global);
  492. if (!err)
  493. __dev_set_rx_mode(dev);
  494. netif_addr_unlock_bh(dev);
  495. return err;
  496. }
  497. /**
  498. * dev_mc_del - Delete a multicast address.
  499. * @dev: device
  500. * @addr: address to delete
  501. *
  502. * Release reference to a multicast address and remove it
  503. * from the device if the reference count drops to zero.
  504. */
  505. int dev_mc_del(struct net_device *dev, unsigned char *addr)
  506. {
  507. return __dev_mc_del(dev, addr, false);
  508. }
  509. EXPORT_SYMBOL(dev_mc_del);
  510. /**
  511. * dev_mc_del_global - Delete a global multicast address.
  512. * @dev: device
  513. * @addr: address to delete
  514. *
  515. * Release reference to a multicast address and remove it
  516. * from the device if the reference count drops to zero.
  517. */
  518. int dev_mc_del_global(struct net_device *dev, unsigned char *addr)
  519. {
  520. return __dev_mc_del(dev, addr, true);
  521. }
  522. EXPORT_SYMBOL(dev_mc_del_global);
  523. /**
  524. * dev_mc_sync - Synchronize device's unicast list to another device
  525. * @to: destination device
  526. * @from: source device
  527. *
  528. * Add newly added addresses to the destination device and release
  529. * addresses that have no users left. The source device must be
  530. * locked by netif_tx_lock_bh.
  531. *
  532. * This function is intended to be called from the dev->set_multicast_list
  533. * or dev->set_rx_mode function of layered software devices.
  534. */
  535. int dev_mc_sync(struct net_device *to, struct net_device *from)
  536. {
  537. int err = 0;
  538. if (to->addr_len != from->addr_len)
  539. return -EINVAL;
  540. netif_addr_lock_bh(to);
  541. err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
  542. if (!err)
  543. __dev_set_rx_mode(to);
  544. netif_addr_unlock_bh(to);
  545. return err;
  546. }
  547. EXPORT_SYMBOL(dev_mc_sync);
  548. /**
  549. * dev_mc_unsync - Remove synchronized addresses from the destination device
  550. * @to: destination device
  551. * @from: source device
  552. *
  553. * Remove all addresses that were added to the destination device by
  554. * dev_mc_sync(). This function is intended to be called from the
  555. * dev->stop function of layered software devices.
  556. */
  557. void dev_mc_unsync(struct net_device *to, struct net_device *from)
  558. {
  559. if (to->addr_len != from->addr_len)
  560. return;
  561. netif_addr_lock_bh(from);
  562. netif_addr_lock(to);
  563. __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
  564. __dev_set_rx_mode(to);
  565. netif_addr_unlock(to);
  566. netif_addr_unlock_bh(from);
  567. }
  568. EXPORT_SYMBOL(dev_mc_unsync);
  569. /**
  570. * dev_mc_flush - Flush multicast addresses
  571. * @dev: device
  572. *
  573. * Flush multicast addresses.
  574. */
  575. void dev_mc_flush(struct net_device *dev)
  576. {
  577. netif_addr_lock_bh(dev);
  578. __hw_addr_flush(&dev->mc);
  579. netif_addr_unlock_bh(dev);
  580. }
  581. EXPORT_SYMBOL(dev_mc_flush);
  582. /**
  583. * dev_mc_flush - Init multicast address list
  584. * @dev: device
  585. *
  586. * Init multicast address list.
  587. */
  588. void dev_mc_init(struct net_device *dev)
  589. {
  590. __hw_addr_init(&dev->mc);
  591. }
  592. EXPORT_SYMBOL(dev_mc_init);
  593. #ifdef CONFIG_PROC_FS
  594. #include <linux/seq_file.h>
  595. static int dev_mc_seq_show(struct seq_file *seq, void *v)
  596. {
  597. struct netdev_hw_addr *ha;
  598. struct net_device *dev = v;
  599. if (v == SEQ_START_TOKEN)
  600. return 0;
  601. netif_addr_lock_bh(dev);
  602. netdev_for_each_mc_addr(ha, dev) {
  603. int i;
  604. seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
  605. dev->name, ha->refcount, ha->global_use);
  606. for (i = 0; i < dev->addr_len; i++)
  607. seq_printf(seq, "%02x", ha->addr[i]);
  608. seq_putc(seq, '\n');
  609. }
  610. netif_addr_unlock_bh(dev);
  611. return 0;
  612. }
  613. static const struct seq_operations dev_mc_seq_ops = {
  614. .start = dev_seq_start,
  615. .next = dev_seq_next,
  616. .stop = dev_seq_stop,
  617. .show = dev_mc_seq_show,
  618. };
  619. static int dev_mc_seq_open(struct inode *inode, struct file *file)
  620. {
  621. return seq_open_net(inode, file, &dev_mc_seq_ops,
  622. sizeof(struct seq_net_private));
  623. }
  624. static const struct file_operations dev_mc_seq_fops = {
  625. .owner = THIS_MODULE,
  626. .open = dev_mc_seq_open,
  627. .read = seq_read,
  628. .llseek = seq_lseek,
  629. .release = seq_release_net,
  630. };
  631. #endif
  632. static int __net_init dev_mc_net_init(struct net *net)
  633. {
  634. if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
  635. return -ENOMEM;
  636. return 0;
  637. }
  638. static void __net_exit dev_mc_net_exit(struct net *net)
  639. {
  640. proc_net_remove(net, "dev_mcast");
  641. }
  642. static struct pernet_operations __net_initdata dev_mc_net_ops = {
  643. .init = dev_mc_net_init,
  644. .exit = dev_mc_net_exit,
  645. };
  646. void __init dev_mcast_init(void)
  647. {
  648. register_pernet_subsys(&dev_mc_net_ops);
  649. }