ipt_CLUSTERIP.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /* Cluster IP hashmark target
  2. * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
  3. * based on ideas of Fabio Olive Leite <olive@unixforge.org>
  4. *
  5. * Development of this code funded by SuSE Linux AG, http://www.suse.com/
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. */
  12. #include <linux/module.h>
  13. #include <linux/proc_fs.h>
  14. #include <linux/jhash.h>
  15. #include <linux/bitops.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/ip.h>
  18. #include <linux/tcp.h>
  19. #include <linux/udp.h>
  20. #include <linux/icmp.h>
  21. #include <linux/if_arp.h>
  22. #include <linux/proc_fs.h>
  23. #include <linux/seq_file.h>
  24. #include <net/checksum.h>
  25. #include <linux/netfilter_arp.h>
  26. #include <linux/netfilter/x_tables.h>
  27. #include <linux/netfilter_ipv4/ip_tables.h>
  28. #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
  29. #include <net/netfilter/nf_conntrack_compat.h>
  30. #define CLUSTERIP_VERSION "0.8"
  31. #define DEBUG_CLUSTERIP
  32. #ifdef DEBUG_CLUSTERIP
  33. #define DEBUGP printk
  34. #else
  35. #define DEBUGP
  36. #endif
  37. MODULE_LICENSE("GPL");
  38. MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  39. MODULE_DESCRIPTION("iptables target for CLUSTERIP");
  40. struct clusterip_config {
  41. struct list_head list; /* list of all configs */
  42. atomic_t refcount; /* reference count */
  43. atomic_t entries; /* number of entries/rules
  44. * referencing us */
  45. __be32 clusterip; /* the IP address */
  46. u_int8_t clustermac[ETH_ALEN]; /* the MAC address */
  47. struct net_device *dev; /* device */
  48. u_int16_t num_total_nodes; /* total number of nodes */
  49. unsigned long local_nodes; /* node number array */
  50. #ifdef CONFIG_PROC_FS
  51. struct proc_dir_entry *pde; /* proc dir entry */
  52. #endif
  53. enum clusterip_hashmode hash_mode; /* which hashing mode */
  54. u_int32_t hash_initval; /* hash initialization */
  55. };
  56. static LIST_HEAD(clusterip_configs);
  57. /* clusterip_lock protects the clusterip_configs list */
  58. static DEFINE_RWLOCK(clusterip_lock);
  59. #ifdef CONFIG_PROC_FS
  60. static const struct file_operations clusterip_proc_fops;
  61. static struct proc_dir_entry *clusterip_procdir;
  62. #endif
  63. static inline void
  64. clusterip_config_get(struct clusterip_config *c)
  65. {
  66. atomic_inc(&c->refcount);
  67. }
  68. static inline void
  69. clusterip_config_put(struct clusterip_config *c)
  70. {
  71. if (atomic_dec_and_test(&c->refcount))
  72. kfree(c);
  73. }
  74. /* increase the count of entries(rules) using/referencing this config */
  75. static inline void
  76. clusterip_config_entry_get(struct clusterip_config *c)
  77. {
  78. atomic_inc(&c->entries);
  79. }
  80. /* decrease the count of entries using/referencing this config. If last
  81. * entry(rule) is removed, remove the config from lists, but don't free it
  82. * yet, since proc-files could still be holding references */
  83. static inline void
  84. clusterip_config_entry_put(struct clusterip_config *c)
  85. {
  86. if (atomic_dec_and_test(&c->entries)) {
  87. write_lock_bh(&clusterip_lock);
  88. list_del(&c->list);
  89. write_unlock_bh(&clusterip_lock);
  90. dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
  91. dev_put(c->dev);
  92. /* In case anyone still accesses the file, the open/close
  93. * functions are also incrementing the refcount on their own,
  94. * so it's safe to remove the entry even if it's in use. */
  95. #ifdef CONFIG_PROC_FS
  96. remove_proc_entry(c->pde->name, c->pde->parent);
  97. #endif
  98. }
  99. }
  100. static struct clusterip_config *
  101. __clusterip_config_find(__be32 clusterip)
  102. {
  103. struct list_head *pos;
  104. list_for_each(pos, &clusterip_configs) {
  105. struct clusterip_config *c = list_entry(pos,
  106. struct clusterip_config, list);
  107. if (c->clusterip == clusterip) {
  108. return c;
  109. }
  110. }
  111. return NULL;
  112. }
  113. static inline struct clusterip_config *
  114. clusterip_config_find_get(__be32 clusterip, int entry)
  115. {
  116. struct clusterip_config *c;
  117. read_lock_bh(&clusterip_lock);
  118. c = __clusterip_config_find(clusterip);
  119. if (!c) {
  120. read_unlock_bh(&clusterip_lock);
  121. return NULL;
  122. }
  123. atomic_inc(&c->refcount);
  124. if (entry)
  125. atomic_inc(&c->entries);
  126. read_unlock_bh(&clusterip_lock);
  127. return c;
  128. }
  129. static void
  130. clusterip_config_init_nodelist(struct clusterip_config *c,
  131. const struct ipt_clusterip_tgt_info *i)
  132. {
  133. int n;
  134. for (n = 0; n < i->num_local_nodes; n++) {
  135. set_bit(i->local_nodes[n] - 1, &c->local_nodes);
  136. }
  137. }
  138. static struct clusterip_config *
  139. clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
  140. struct net_device *dev)
  141. {
  142. struct clusterip_config *c;
  143. c = kzalloc(sizeof(*c), GFP_ATOMIC);
  144. if (!c)
  145. return NULL;
  146. c->dev = dev;
  147. c->clusterip = ip;
  148. memcpy(&c->clustermac, &i->clustermac, ETH_ALEN);
  149. c->num_total_nodes = i->num_total_nodes;
  150. clusterip_config_init_nodelist(c, i);
  151. c->hash_mode = i->hash_mode;
  152. c->hash_initval = i->hash_initval;
  153. atomic_set(&c->refcount, 1);
  154. atomic_set(&c->entries, 1);
  155. #ifdef CONFIG_PROC_FS
  156. {
  157. char buffer[16];
  158. /* create proc dir entry */
  159. sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
  160. c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
  161. clusterip_procdir);
  162. if (!c->pde) {
  163. kfree(c);
  164. return NULL;
  165. }
  166. }
  167. c->pde->proc_fops = &clusterip_proc_fops;
  168. c->pde->data = c;
  169. #endif
  170. write_lock_bh(&clusterip_lock);
  171. list_add(&c->list, &clusterip_configs);
  172. write_unlock_bh(&clusterip_lock);
  173. return c;
  174. }
  175. #ifdef CONFIG_PROC_FS
  176. static int
  177. clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
  178. {
  179. if (nodenum == 0 ||
  180. nodenum > c->num_total_nodes)
  181. return 1;
  182. /* check if we already have this number in our bitfield */
  183. if (test_and_set_bit(nodenum - 1, &c->local_nodes))
  184. return 1;
  185. return 0;
  186. }
  187. static int
  188. clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
  189. {
  190. if (nodenum == 0 ||
  191. nodenum > c->num_total_nodes)
  192. return 1;
  193. if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
  194. return 0;
  195. return 1;
  196. }
  197. #endif
  198. static inline u_int32_t
  199. clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
  200. {
  201. struct iphdr *iph = skb->nh.iph;
  202. unsigned long hashval;
  203. u_int16_t sport, dport;
  204. u_int16_t *ports;
  205. switch (iph->protocol) {
  206. case IPPROTO_TCP:
  207. case IPPROTO_UDP:
  208. case IPPROTO_UDPLITE:
  209. case IPPROTO_SCTP:
  210. case IPPROTO_DCCP:
  211. case IPPROTO_ICMP:
  212. ports = (void *)iph+iph->ihl*4;
  213. sport = ports[0];
  214. dport = ports[1];
  215. break;
  216. default:
  217. if (net_ratelimit()) {
  218. printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n",
  219. iph->protocol);
  220. }
  221. sport = dport = 0;
  222. }
  223. switch (config->hash_mode) {
  224. case CLUSTERIP_HASHMODE_SIP:
  225. hashval = jhash_1word(ntohl(iph->saddr),
  226. config->hash_initval);
  227. break;
  228. case CLUSTERIP_HASHMODE_SIP_SPT:
  229. hashval = jhash_2words(ntohl(iph->saddr), sport,
  230. config->hash_initval);
  231. break;
  232. case CLUSTERIP_HASHMODE_SIP_SPT_DPT:
  233. hashval = jhash_3words(ntohl(iph->saddr), sport, dport,
  234. config->hash_initval);
  235. break;
  236. default:
  237. /* to make gcc happy */
  238. hashval = 0;
  239. /* This cannot happen, unless the check function wasn't called
  240. * at rule load time */
  241. printk("CLUSTERIP: unknown mode `%u'\n", config->hash_mode);
  242. BUG();
  243. break;
  244. }
  245. /* node numbers are 1..n, not 0..n */
  246. return ((hashval % config->num_total_nodes)+1);
  247. }
  248. static inline int
  249. clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
  250. {
  251. return test_bit(hash - 1, &config->local_nodes);
  252. }
  253. /***********************************************************************
  254. * IPTABLES TARGET
  255. ***********************************************************************/
  256. static unsigned int
  257. target(struct sk_buff **pskb,
  258. const struct net_device *in,
  259. const struct net_device *out,
  260. unsigned int hooknum,
  261. const struct xt_target *target,
  262. const void *targinfo)
  263. {
  264. const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
  265. enum ip_conntrack_info ctinfo;
  266. u_int32_t *mark, hash;
  267. /* don't need to clusterip_config_get() here, since refcount
  268. * is only decremented by destroy() - and ip_tables guarantees
  269. * that the ->target() function isn't called after ->destroy() */
  270. mark = nf_ct_get_mark((*pskb), &ctinfo);
  271. if (mark == NULL) {
  272. printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
  273. /* FIXME: need to drop invalid ones, since replies
  274. * to outgoing connections of other nodes will be
  275. * marked as INVALID */
  276. return NF_DROP;
  277. }
  278. /* special case: ICMP error handling. conntrack distinguishes between
  279. * error messages (RELATED) and information requests (see below) */
  280. if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
  281. && (ctinfo == IP_CT_RELATED
  282. || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
  283. return XT_CONTINUE;
  284. /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
  285. * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
  286. * on, which all have an ID field [relevant for hashing]. */
  287. hash = clusterip_hashfn(*pskb, cipinfo->config);
  288. switch (ctinfo) {
  289. case IP_CT_NEW:
  290. *mark = hash;
  291. break;
  292. case IP_CT_RELATED:
  293. case IP_CT_RELATED+IP_CT_IS_REPLY:
  294. /* FIXME: we don't handle expectations at the
  295. * moment. they can arrive on a different node than
  296. * the master connection (e.g. FTP passive mode) */
  297. case IP_CT_ESTABLISHED:
  298. case IP_CT_ESTABLISHED+IP_CT_IS_REPLY:
  299. break;
  300. default:
  301. break;
  302. }
  303. #ifdef DEBUG_CLUSTERP
  304. DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
  305. #endif
  306. DEBUGP("hash=%u ct_hash=%u ", hash, *mark);
  307. if (!clusterip_responsible(cipinfo->config, hash)) {
  308. DEBUGP("not responsible\n");
  309. return NF_DROP;
  310. }
  311. DEBUGP("responsible\n");
  312. /* despite being received via linklayer multicast, this is
  313. * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
  314. (*pskb)->pkt_type = PACKET_HOST;
  315. return XT_CONTINUE;
  316. }
  317. static int
  318. checkentry(const char *tablename,
  319. const void *e_void,
  320. const struct xt_target *target,
  321. void *targinfo,
  322. unsigned int hook_mask)
  323. {
  324. struct ipt_clusterip_tgt_info *cipinfo = targinfo;
  325. const struct ipt_entry *e = e_void;
  326. struct clusterip_config *config;
  327. if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
  328. cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
  329. cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
  330. printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n",
  331. cipinfo->hash_mode);
  332. return 0;
  333. }
  334. if (e->ip.dmsk.s_addr != htonl(0xffffffff)
  335. || e->ip.dst.s_addr == 0) {
  336. printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
  337. return 0;
  338. }
  339. /* FIXME: further sanity checks */
  340. config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
  341. if (config) {
  342. if (cipinfo->config != NULL) {
  343. /* Case A: This is an entry that gets reloaded, since
  344. * it still has a cipinfo->config pointer. Simply
  345. * increase the entry refcount and return */
  346. if (cipinfo->config != config) {
  347. printk(KERN_ERR "CLUSTERIP: Reloaded entry "
  348. "has invalid config pointer!\n");
  349. return 0;
  350. }
  351. } else {
  352. /* Case B: This is a new rule referring to an existing
  353. * clusterip config. */
  354. cipinfo->config = config;
  355. }
  356. } else {
  357. /* Case C: This is a completely new clusterip config */
  358. if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
  359. printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
  360. return 0;
  361. } else {
  362. struct net_device *dev;
  363. if (e->ip.iniface[0] == '\0') {
  364. printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n");
  365. return 0;
  366. }
  367. dev = dev_get_by_name(e->ip.iniface);
  368. if (!dev) {
  369. printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
  370. return 0;
  371. }
  372. config = clusterip_config_init(cipinfo,
  373. e->ip.dst.s_addr, dev);
  374. if (!config) {
  375. printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
  376. dev_put(dev);
  377. return 0;
  378. }
  379. dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
  380. }
  381. cipinfo->config = config;
  382. }
  383. if (nf_ct_l3proto_try_module_get(target->family) < 0) {
  384. printk(KERN_WARNING "can't load conntrack support for "
  385. "proto=%d\n", target->family);
  386. return 0;
  387. }
  388. return 1;
  389. }
  390. /* drop reference count of cluster config when rule is deleted */
  391. static void destroy(const struct xt_target *target, void *targinfo)
  392. {
  393. struct ipt_clusterip_tgt_info *cipinfo = targinfo;
  394. /* if no more entries are referencing the config, remove it
  395. * from the list and destroy the proc entry */
  396. clusterip_config_entry_put(cipinfo->config);
  397. clusterip_config_put(cipinfo->config);
  398. nf_ct_l3proto_module_put(target->family);
  399. }
  400. static struct xt_target clusterip_tgt = {
  401. .name = "CLUSTERIP",
  402. .family = AF_INET,
  403. .target = target,
  404. .targetsize = sizeof(struct ipt_clusterip_tgt_info),
  405. .checkentry = checkentry,
  406. .destroy = destroy,
  407. .me = THIS_MODULE
  408. };
  409. /***********************************************************************
  410. * ARP MANGLING CODE
  411. ***********************************************************************/
  412. /* hardcoded for 48bit ethernet and 32bit ipv4 addresses */
  413. struct arp_payload {
  414. u_int8_t src_hw[ETH_ALEN];
  415. __be32 src_ip;
  416. u_int8_t dst_hw[ETH_ALEN];
  417. __be32 dst_ip;
  418. } __attribute__ ((packed));
  419. #ifdef CLUSTERIP_DEBUG
  420. static void arp_print(struct arp_payload *payload)
  421. {
  422. #define HBUFFERLEN 30
  423. char hbuffer[HBUFFERLEN];
  424. int j,k;
  425. const char hexbuf[]= "0123456789abcdef";
  426. for (k=0, j=0; k < HBUFFERLEN-3 && j < ETH_ALEN; j++) {
  427. hbuffer[k++]=hexbuf[(payload->src_hw[j]>>4)&15];
  428. hbuffer[k++]=hexbuf[payload->src_hw[j]&15];
  429. hbuffer[k++]=':';
  430. }
  431. hbuffer[--k]='\0';
  432. printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n",
  433. NIPQUAD(payload->src_ip), hbuffer,
  434. NIPQUAD(payload->dst_ip));
  435. }
  436. #endif
  437. static unsigned int
  438. arp_mangle(unsigned int hook,
  439. struct sk_buff **pskb,
  440. const struct net_device *in,
  441. const struct net_device *out,
  442. int (*okfn)(struct sk_buff *))
  443. {
  444. struct arphdr *arp = (*pskb)->nh.arph;
  445. struct arp_payload *payload;
  446. struct clusterip_config *c;
  447. /* we don't care about non-ethernet and non-ipv4 ARP */
  448. if (arp->ar_hrd != htons(ARPHRD_ETHER)
  449. || arp->ar_pro != htons(ETH_P_IP)
  450. || arp->ar_pln != 4 || arp->ar_hln != ETH_ALEN)
  451. return NF_ACCEPT;
  452. /* we only want to mangle arp requests and replies */
  453. if (arp->ar_op != htons(ARPOP_REPLY)
  454. && arp->ar_op != htons(ARPOP_REQUEST))
  455. return NF_ACCEPT;
  456. payload = (void *)(arp+1);
  457. /* if there is no clusterip configuration for the arp reply's
  458. * source ip, we don't want to mangle it */
  459. c = clusterip_config_find_get(payload->src_ip, 0);
  460. if (!c)
  461. return NF_ACCEPT;
  462. /* normally the linux kernel always replies to arp queries of
  463. * addresses on different interfacs. However, in the CLUSTERIP case
  464. * this wouldn't work, since we didn't subscribe the mcast group on
  465. * other interfaces */
  466. if (c->dev != out) {
  467. DEBUGP("CLUSTERIP: not mangling arp reply on different "
  468. "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name);
  469. clusterip_config_put(c);
  470. return NF_ACCEPT;
  471. }
  472. /* mangle reply hardware address */
  473. memcpy(payload->src_hw, c->clustermac, arp->ar_hln);
  474. #ifdef CLUSTERIP_DEBUG
  475. DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
  476. arp_print(payload);
  477. #endif
  478. clusterip_config_put(c);
  479. return NF_ACCEPT;
  480. }
  481. static struct nf_hook_ops cip_arp_ops = {
  482. .hook = arp_mangle,
  483. .pf = NF_ARP,
  484. .hooknum = NF_ARP_OUT,
  485. .priority = -1
  486. };
  487. /***********************************************************************
  488. * PROC DIR HANDLING
  489. ***********************************************************************/
  490. #ifdef CONFIG_PROC_FS
  491. struct clusterip_seq_position {
  492. unsigned int pos; /* position */
  493. unsigned int weight; /* number of bits set == size */
  494. unsigned int bit; /* current bit */
  495. unsigned long val; /* current value */
  496. };
  497. static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
  498. {
  499. struct proc_dir_entry *pde = s->private;
  500. struct clusterip_config *c = pde->data;
  501. unsigned int weight;
  502. u_int32_t local_nodes;
  503. struct clusterip_seq_position *idx;
  504. /* FIXME: possible race */
  505. local_nodes = c->local_nodes;
  506. weight = hweight32(local_nodes);
  507. if (*pos >= weight)
  508. return NULL;
  509. idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL);
  510. if (!idx)
  511. return ERR_PTR(-ENOMEM);
  512. idx->pos = *pos;
  513. idx->weight = weight;
  514. idx->bit = ffs(local_nodes);
  515. idx->val = local_nodes;
  516. clear_bit(idx->bit - 1, &idx->val);
  517. return idx;
  518. }
  519. static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
  520. {
  521. struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
  522. *pos = ++idx->pos;
  523. if (*pos >= idx->weight) {
  524. kfree(v);
  525. return NULL;
  526. }
  527. idx->bit = ffs(idx->val);
  528. clear_bit(idx->bit - 1, &idx->val);
  529. return idx;
  530. }
  531. static void clusterip_seq_stop(struct seq_file *s, void *v)
  532. {
  533. kfree(v);
  534. }
  535. static int clusterip_seq_show(struct seq_file *s, void *v)
  536. {
  537. struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
  538. if (idx->pos != 0)
  539. seq_putc(s, ',');
  540. seq_printf(s, "%u", idx->bit);
  541. if (idx->pos == idx->weight - 1)
  542. seq_putc(s, '\n');
  543. return 0;
  544. }
  545. static struct seq_operations clusterip_seq_ops = {
  546. .start = clusterip_seq_start,
  547. .next = clusterip_seq_next,
  548. .stop = clusterip_seq_stop,
  549. .show = clusterip_seq_show,
  550. };
  551. static int clusterip_proc_open(struct inode *inode, struct file *file)
  552. {
  553. int ret = seq_open(file, &clusterip_seq_ops);
  554. if (!ret) {
  555. struct seq_file *sf = file->private_data;
  556. struct proc_dir_entry *pde = PDE(inode);
  557. struct clusterip_config *c = pde->data;
  558. sf->private = pde;
  559. clusterip_config_get(c);
  560. }
  561. return ret;
  562. }
  563. static int clusterip_proc_release(struct inode *inode, struct file *file)
  564. {
  565. struct proc_dir_entry *pde = PDE(inode);
  566. struct clusterip_config *c = pde->data;
  567. int ret;
  568. ret = seq_release(inode, file);
  569. if (!ret)
  570. clusterip_config_put(c);
  571. return ret;
  572. }
  573. static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
  574. size_t size, loff_t *ofs)
  575. {
  576. #define PROC_WRITELEN 10
  577. char buffer[PROC_WRITELEN+1];
  578. struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
  579. struct clusterip_config *c = pde->data;
  580. unsigned long nodenum;
  581. if (copy_from_user(buffer, input, PROC_WRITELEN))
  582. return -EFAULT;
  583. if (*buffer == '+') {
  584. nodenum = simple_strtoul(buffer+1, NULL, 10);
  585. if (clusterip_add_node(c, nodenum))
  586. return -ENOMEM;
  587. } else if (*buffer == '-') {
  588. nodenum = simple_strtoul(buffer+1, NULL,10);
  589. if (clusterip_del_node(c, nodenum))
  590. return -ENOENT;
  591. } else
  592. return -EIO;
  593. return size;
  594. }
  595. static const struct file_operations clusterip_proc_fops = {
  596. .owner = THIS_MODULE,
  597. .open = clusterip_proc_open,
  598. .read = seq_read,
  599. .write = clusterip_proc_write,
  600. .llseek = seq_lseek,
  601. .release = clusterip_proc_release,
  602. };
  603. #endif /* CONFIG_PROC_FS */
  604. static int __init ipt_clusterip_init(void)
  605. {
  606. int ret;
  607. ret = xt_register_target(&clusterip_tgt);
  608. if (ret < 0)
  609. return ret;
  610. ret = nf_register_hook(&cip_arp_ops);
  611. if (ret < 0)
  612. goto cleanup_target;
  613. #ifdef CONFIG_PROC_FS
  614. clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
  615. if (!clusterip_procdir) {
  616. printk(KERN_ERR "CLUSTERIP: Unable to proc dir entry\n");
  617. ret = -ENOMEM;
  618. goto cleanup_hook;
  619. }
  620. #endif /* CONFIG_PROC_FS */
  621. printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
  622. CLUSTERIP_VERSION);
  623. return 0;
  624. #ifdef CONFIG_PROC_FS
  625. cleanup_hook:
  626. nf_unregister_hook(&cip_arp_ops);
  627. #endif /* CONFIG_PROC_FS */
  628. cleanup_target:
  629. xt_unregister_target(&clusterip_tgt);
  630. return ret;
  631. }
  632. static void __exit ipt_clusterip_fini(void)
  633. {
  634. printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
  635. CLUSTERIP_VERSION);
  636. #ifdef CONFIG_PROC_FS
  637. remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
  638. #endif
  639. nf_unregister_hook(&cip_arp_ops);
  640. xt_unregister_target(&clusterip_tgt);
  641. }
  642. module_init(ipt_clusterip_init);
  643. module_exit(ipt_clusterip_fini);