From 825a2ff1896ec3ead94bebef60c71f57254da58a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 3 Jul 2007 16:53:09 +0100 Subject: AX88796 network driver Support for the Asix AX88796 network controller, an NE2000 compatible 10/100 ethernet device with internal PHY. The driver supports PHY settings via either ioctl() or the ethtool driver ops. Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- include/net/ax88796.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 include/net/ax88796.h (limited to 'include/net') diff --git a/include/net/ax88796.h b/include/net/ax88796.h new file mode 100644 index 000000000000..ee786a043b3d --- /dev/null +++ b/include/net/ax88796.h @@ -0,0 +1,27 @@ +/* include/net/ax88796.h + * + * Copyright 2005 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#ifndef __NET_AX88796_PLAT_H +#define __NET_AX88796_PLAT_H + +#define AXFLG_HAS_EEPROM (1<<0) +#define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */ + +struct ax_plat_data { + unsigned int flags; + unsigned char wordlength; /* 1 or 2 */ + unsigned char dcr_val; /* default value for DCR */ + unsigned char rcr_val; /* default value for RCR */ + unsigned char gpoc_val; /* default value for GPOC */ + u32 *reg_offsets; /* register offsets */ +}; + +#endif /* __NET_AX88796_PLAT_H */ -- cgit v1.2.3 From ef222013fc8c1a2fcba5c7ab169be8ffcb778ec4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jul 2007 06:42:04 +0200 Subject: [Bluetooth] Add hci_recv_fragment() helper function Most drivers must handle fragmented HCI data packets and events. This patch adds a generic function for their reassembly to the Bluetooth core layer and thus allows to shrink the complexity of the drivers. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 3 ++ net/bluetooth/hci_core.c | 97 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 2 deletions(-) (limited to 'include/net') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c0fc39620f36..7c78744ec0fd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -109,6 +109,7 @@ struct hci_dev { struct sk_buff_head cmd_q; struct sk_buff *sent_cmd; + struct sk_buff *reassembly[3]; struct semaphore req_lock; wait_queue_head_t req_wait_q; @@ -437,6 +438,8 @@ static inline int hci_recv_frame(struct sk_buff *skb) return 0; } +int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); + int hci_register_sysfs(struct hci_dev *hdev); void hci_unregister_sysfs(struct hci_dev *hdev); void hci_conn_add_sysfs(struct hci_conn *conn); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aa4b56a8c3ea..9c71cffbc6b0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev); int hci_register_dev(struct hci_dev *hdev) { struct list_head *head = &hci_dev_list, *p; - int id = 0; + int i, id = 0; BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); @@ -865,6 +865,9 @@ int hci_register_dev(struct hci_dev *hdev) skb_queue_head_init(&hdev->cmd_q); skb_queue_head_init(&hdev->raw_q); + for (i = 0; i < 3; i++) + hdev->reassembly[i] = NULL; + init_waitqueue_head(&hdev->req_wait_q); init_MUTEX(&hdev->req_lock); @@ -889,6 +892,8 @@ EXPORT_SYMBOL(hci_register_dev); /* Unregister HCI device */ int hci_unregister_dev(struct hci_dev *hdev) { + int i; + BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); hci_unregister_sysfs(hdev); @@ -899,9 +904,13 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_dev_do_close(hdev); + for (i = 0; i < 3; i++) + kfree_skb(hdev->reassembly[i]); + hci_notify(hdev, HCI_DEV_UNREG); __hci_dev_put(hdev); + return 0; } EXPORT_SYMBOL(hci_unregister_dev); @@ -922,6 +931,90 @@ int hci_resume_dev(struct hci_dev *hdev) } EXPORT_SYMBOL(hci_resume_dev); +/* Receive packet type fragment */ +#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2]) + +int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) +{ + if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) + return -EILSEQ; + + while (count) { + struct sk_buff *skb = __reassembly(hdev, type); + struct { int expect; } *scb; + int len = 0; + + if (!skb) { + /* Start of the frame */ + + switch (type) { + case HCI_EVENT_PKT: + if (count >= HCI_EVENT_HDR_SIZE) { + struct hci_event_hdr *h = data; + len = HCI_EVENT_HDR_SIZE + h->plen; + } else + return -EILSEQ; + break; + + case HCI_ACLDATA_PKT: + if (count >= HCI_ACL_HDR_SIZE) { + struct hci_acl_hdr *h = data; + len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); + } else + return -EILSEQ; + break; + + case HCI_SCODATA_PKT: + if (count >= HCI_SCO_HDR_SIZE) { + struct hci_sco_hdr *h = data; + len = HCI_SCO_HDR_SIZE + h->dlen; + } else + return -EILSEQ; + break; + } + + skb = bt_skb_alloc(len, GFP_ATOMIC); + if (!skb) { + BT_ERR("%s no memory for packet", hdev->name); + return -ENOMEM; + } + + skb->dev = (void *) hdev; + bt_cb(skb)->pkt_type = type; + + __reassembly(hdev, type) = skb; + + scb = (void *) skb->cb; + scb->expect = len; + } else { + /* Continuation */ + + scb = (void *) skb->cb; + len = scb->expect; + } + + len = min(len, count); + + memcpy(skb_put(skb, len), data, len); + + scb->expect -= len; + + if (scb->expect == 0) { + /* Complete frame */ + + __reassembly(hdev, type) = NULL; + + bt_cb(skb)->pkt_type = type; + hci_recv_frame(skb); + } + + count -= len; data += len; + } + + return 0; +} +EXPORT_SYMBOL(hci_recv_fragment); + /* ---- Interface to upper protocols ---- */ /* Register/Unregister protocols. @@ -1029,7 +1122,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p skb = bt_skb_alloc(len, GFP_ATOMIC); if (!skb) { - BT_ERR("%s Can't allocate memory for HCI command", hdev->name); + BT_ERR("%s no memory for command", hdev->name); return -ENOMEM; } -- cgit v1.2.3 From e06e7c615877026544ad7f8b309d1a3706410383 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 10 Jun 2007 17:22:39 -0700 Subject: [IPV4]: The scheduled removal of multipath cached routing support. With help from Chris Wedgwood. Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 19 -- include/linux/Kbuild | 1 - include/linux/ip_mp_alg.h | 22 -- include/linux/rtnetlink.h | 2 +- include/net/dst.h | 1 - include/net/ip_fib.h | 16 -- include/net/ip_mp_alg.h | 96 --------- include/net/route.h | 1 - net/ipv4/Kconfig | 42 ---- net/ipv4/Makefile | 5 - net/ipv4/fib_frontend.c | 4 - net/ipv4/fib_semantics.c | 16 -- net/ipv4/multipath.c | 55 ----- net/ipv4/multipath_drr.c | 249 ---------------------- net/ipv4/multipath_random.c | 114 ---------- net/ipv4/multipath_rr.c | 95 --------- net/ipv4/multipath_wrandom.c | 329 ----------------------------- net/ipv4/route.c | 259 +---------------------- 18 files changed, 12 insertions(+), 1314 deletions(-) delete mode 100644 include/linux/ip_mp_alg.h delete mode 100644 include/net/ip_mp_alg.h delete mode 100644 net/ipv4/multipath.c delete mode 100644 net/ipv4/multipath_drr.c delete mode 100644 net/ipv4/multipath_random.c delete mode 100644 net/ipv4/multipath_rr.c delete mode 100644 net/ipv4/multipath_wrandom.c (limited to 'include/net') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3a159dac04f5..484250dcdbe0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -262,25 +262,6 @@ Who: Richard Purdie --------------------------- -What: Multipath cached routing support in ipv4 -When: in 2.6.23 -Why: Code was merged, then submitter immediately disappeared leaving - us with no maintainer and lots of bugs. The code should not have - been merged in the first place, and many aspects of it's - implementation are blocking more critical core networking - development. It's marked EXPERIMENTAL and no distribution - enables it because it cause obscure crashes due to unfixable bugs - (interfaces don't return errors so memory allocation can't be - handled, calling contexts of these interfaces make handling - errors impossible too because they get called after we've - totally commited to creating a route object, for example). - This problem has existed for years and no forward progress - has ever been made, and nobody steps up to try and salvage - this code, so we're going to finally just get rid of it. -Who: David S. Miller - ---------------------------- - What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer) When: December 2007 Why: These functions are a leftover from 2.4 times. They have several diff --git a/include/linux/Kbuild b/include/linux/Kbuild index afae306b177c..d94451682761 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -91,7 +91,6 @@ header-y += in6.h header-y += in_route.h header-y += ioctl.h header-y += ipmi_msgdefs.h -header-y += ip_mp_alg.h header-y += ipsec.h header-y += ipx.h header-y += irda.h diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h deleted file mode 100644 index e234e2008f5d..000000000000 --- a/include/linux/ip_mp_alg.h +++ /dev/null @@ -1,22 +0,0 @@ -/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values. - * - * Copyright (C) 2004, 2005 Einar Lueck - * Copyright (C) 2005 David S. Miller - */ - -#ifndef _LINUX_IP_MP_ALG_H -#define _LINUX_IP_MP_ALG_H - -enum ip_mp_alg { - IP_MP_ALG_NONE, - IP_MP_ALG_RR, - IP_MP_ALG_DRR, - IP_MP_ALG_RANDOM, - IP_MP_ALG_WRANDOM, - __IP_MP_ALG_MAX -}; - -#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1) - -#endif /* _LINUX_IP_MP_ALG_H */ - diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 1fae30af91f3..612785848532 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -261,7 +261,7 @@ enum rtattr_type_t RTA_FLOW, RTA_CACHEINFO, RTA_SESSION, - RTA_MP_ALGO, + RTA_MP_ALGO, /* no longer used */ RTA_TABLE, __RTA_MAX }; diff --git a/include/net/dst.h b/include/net/dst.h index 82270f9332db..e9ff4a4caef9 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -47,7 +47,6 @@ struct dst_entry #define DST_NOXFRM 2 #define DST_NOPOLICY 4 #define DST_NOHASH 8 -#define DST_BALANCED 0x10 unsigned long expires; unsigned short header_len; /* more space at head required */ diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 69252cbe05b0..8cadc77c7df4 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -39,7 +39,6 @@ struct fib_config { int fc_mx_len; int fc_mp_len; u32 fc_flow; - u32 fc_mp_alg; u32 fc_nlflags; struct nl_info fc_nlinfo; }; @@ -85,9 +84,6 @@ struct fib_info { int fib_nhs; #ifdef CONFIG_IP_ROUTE_MULTIPATH int fib_power; -#endif -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - u32 fib_mp_alg; #endif struct fib_nh fib_nh[0]; #define fib_dev fib_nh[0].nh_dev @@ -103,10 +99,6 @@ struct fib_result { unsigned char nh_sel; unsigned char type; unsigned char scope; -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - __be32 network; - __be32 netmask; -#endif struct fib_info *fi; #ifdef CONFIG_IP_MULTIPLE_TABLES struct fib_rule *r; @@ -145,14 +137,6 @@ struct fib_result_nl { #define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev) #define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif) -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED -#define FIB_RES_NETWORK(res) ((res).network) -#define FIB_RES_NETMASK(res) ((res).netmask) -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ -#define FIB_RES_NETWORK(res) (0) -#define FIB_RES_NETMASK(res) (0) -#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ - struct fib_table { struct hlist_node tb_hlist; u32 tb_id; diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h deleted file mode 100644 index 25b56571e54b..000000000000 --- a/include/net/ip_mp_alg.h +++ /dev/null @@ -1,96 +0,0 @@ -/* ip_mp_alg.h: IPV4 multipath algorithm support. - * - * Copyright (C) 2004, 2005 Einar Lueck - * Copyright (C) 2005 David S. Miller - */ - -#ifndef _NET_IP_MP_ALG_H -#define _NET_IP_MP_ALG_H - -#include -#include -#include - -struct fib_nh; - -struct ip_mp_alg_ops { - void (*mp_alg_select_route)(const struct flowi *flp, - struct rtable *rth, struct rtable **rp); - void (*mp_alg_flush)(void); - void (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask, - unsigned char prefixlen, - const struct fib_nh *nh); - void (*mp_alg_remove)(struct rtable *rth); -}; - -extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg); -extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg); - -extern struct ip_mp_alg_ops *ip_mp_alg_table[]; - -static inline int multipath_select_route(const struct flowi *flp, - struct rtable *rth, - struct rtable **rp) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; - - /* mp_alg_select_route _MUST_ be implemented */ - if (ops && (rth->u.dst.flags & DST_BALANCED)) { - ops->mp_alg_select_route(flp, rth, rp); - return 1; - } -#endif - return 0; -} - -static inline void multipath_flush(void) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - int i; - - for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) { - struct ip_mp_alg_ops *ops = ip_mp_alg_table[i]; - - if (ops && ops->mp_alg_flush) - ops->mp_alg_flush(); - } -#endif -} - -static inline void multipath_set_nhinfo(struct rtable *rth, - __be32 network, __be32 netmask, - unsigned char prefixlen, - const struct fib_nh *nh) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; - - if (ops && ops->mp_alg_set_nhinfo) - ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh); -#endif -} - -static inline void multipath_remove(struct rtable *rth) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; - - if (ops && ops->mp_alg_remove && - (rth->u.dst.flags & DST_BALANCED)) - ops->mp_alg_remove(rth); -#endif -} - -static inline int multipath_comparekeys(const struct flowi *flp1, - const struct flowi *flp2) -{ - return flp1->fl4_dst == flp2->fl4_dst && - flp1->fl4_src == flp2->fl4_src && - flp1->oif == flp2->oif && - flp1->mark == flp2->mark && - !((flp1->fl4_tos ^ flp2->fl4_tos) & - (IPTOS_RT_MASK | RTO_ONLINK)); -} - -#endif /* _NET_IP_MP_ALG_H */ diff --git a/include/net/route.h b/include/net/route.h index 749e4dfe5ff3..188b8936bb27 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -62,7 +62,6 @@ struct rtable unsigned rt_flags; __u16 rt_type; - __u16 rt_multipath_alg; __be32 rt_dst; /* Path destination */ __be32 rt_src; /* Path source */ diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 010fbb2d45e9..fb7909774254 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -116,48 +116,6 @@ config IP_ROUTE_MULTIPATH equal "cost" and chooses one of them in a non-deterministic fashion if a matching packet arrives. -config IP_ROUTE_MULTIPATH_CACHED - bool "IP: equal cost multipath with caching support (EXPERIMENTAL)" - depends on IP_ROUTE_MULTIPATH - help - Normally, equal cost multipath routing is not supported by the - routing cache. If you say Y here, alternative routes are cached - and on cache lookup a route is chosen in a configurable fashion. - - If unsure, say N. - -config IP_ROUTE_MULTIPATH_RR - tristate "MULTIPATH: round robin algorithm" - depends on IP_ROUTE_MULTIPATH_CACHED - help - Multipath routes are chosen according to Round Robin - -config IP_ROUTE_MULTIPATH_RANDOM - tristate "MULTIPATH: random algorithm" - depends on IP_ROUTE_MULTIPATH_CACHED - help - Multipath routes are chosen in a random fashion. Actually, - there is no weight for a route. The advantage of this policy - is that it is implemented stateless and therefore introduces only - a very small delay. - -config IP_ROUTE_MULTIPATH_WRANDOM - tristate "MULTIPATH: weighted random algorithm" - depends on IP_ROUTE_MULTIPATH_CACHED - help - Multipath routes are chosen in a weighted random fashion. - The per route weights are the weights visible via ip route 2. As the - corresponding state management introduces some overhead routing delay - is increased. - -config IP_ROUTE_MULTIPATH_DRR - tristate "MULTIPATH: interface round robin algorithm" - depends on IP_ROUTE_MULTIPATH_CACHED - help - Connections are distributed in a round robin fashion over the - available interfaces. This policy makes sense if the connections - should be primarily distributed on interfaces and not on routes. - config IP_ROUTE_VERBOSE bool "IP: verbose route monitoring" depends on IP_ADVANCED_ROUTER diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 4ff6c151d7f3..fbf1674e0c2a 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -29,14 +29,9 @@ obj-$(CONFIG_INET_TUNNEL) += tunnel4.o obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o obj-$(CONFIG_IP_PNP) += ipconfig.o -obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o -obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o -obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o -obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ obj-$(CONFIG_IP_VS) += ipvs/ obj-$(CONFIG_INET_DIAG) += inet_diag.o -obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 311d633f7f39..2eb909be8041 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -453,7 +453,6 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = { [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, [RTA_PROTOINFO] = { .type = NLA_U32 }, [RTA_FLOW] = { .type = NLA_U32 }, - [RTA_MP_ALGO] = { .type = NLA_U32 }, }; static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -515,9 +514,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, case RTA_FLOW: cfg->fc_flow = nla_get_u32(attr); break; - case RTA_MP_ALGO: - cfg->fc_mp_alg = nla_get_u32(attr); - break; case RTA_TABLE: cfg->fc_table = nla_get_u32(attr); break; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index bb94550d95c3..c434119deb52 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -697,13 +696,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto err_inval; } #endif -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (cfg->fc_mp_alg) { - if (cfg->fc_mp_alg < IP_MP_ALG_NONE || - cfg->fc_mp_alg > IP_MP_ALG_MAX) - goto err_inval; - } -#endif err = -ENOBUFS; if (fib_info_cnt >= fib_hash_size) { @@ -791,10 +783,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) #endif } -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - fi->fib_mp_alg = cfg->fc_mp_alg; -#endif - if (fib_props[cfg->fc_type].error) { if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) goto err_inval; @@ -940,10 +928,6 @@ out_fill_res: res->type = fa->fa_type; res->scope = fa->fa_scope; res->fi = fa->fa_info; -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - res->netmask = mask; - res->network = zone & inet_make_mask(prefixlen); -#endif atomic_inc(&res->fi->fib_clntref); return 0; } diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c deleted file mode 100644 index 4e9ca7c76407..000000000000 --- a/net/ipv4/multipath.c +++ /dev/null @@ -1,55 +0,0 @@ -/* multipath.c: IPV4 multipath algorithm support. - * - * Copyright (C) 2004, 2005 Einar Lueck - * Copyright (C) 2005 David S. Miller - */ - -#include -#include -#include -#include - -#include - -static DEFINE_SPINLOCK(alg_table_lock); -struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1]; - -int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n) -{ - struct ip_mp_alg_ops **slot; - int err; - - if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX || - !ops->mp_alg_select_route) - return -EINVAL; - - spin_lock(&alg_table_lock); - slot = &ip_mp_alg_table[n]; - if (*slot != NULL) { - err = -EBUSY; - } else { - *slot = ops; - err = 0; - } - spin_unlock(&alg_table_lock); - - return err; -} -EXPORT_SYMBOL(multipath_alg_register); - -void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n) -{ - struct ip_mp_alg_ops **slot; - - if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX) - return; - - spin_lock(&alg_table_lock); - slot = &ip_mp_alg_table[n]; - if (*slot == ops) - *slot = NULL; - spin_unlock(&alg_table_lock); - - synchronize_net(); -} -EXPORT_SYMBOL(multipath_alg_unregister); diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c deleted file mode 100644 index b03c5ca2c823..000000000000 --- a/net/ipv4/multipath_drr.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Device round robin policy for multipath. - * - * - * Version: $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $ - * - * Authors: Einar Lueck - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct multipath_device { - int ifi; /* interface index of device */ - atomic_t usecount; - int allocated; -}; - -#define MULTIPATH_MAX_DEVICECANDIDATES 10 - -static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES]; -static DEFINE_SPINLOCK(state_lock); - -static int inline __multipath_findslot(void) -{ - int i; - - for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) { - if (state[i].allocated == 0) - return i; - } - return -1; -} - -static int inline __multipath_finddev(int ifindex) -{ - int i; - - for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) { - if (state[i].allocated != 0 && - state[i].ifi == ifindex) - return i; - } - return -1; -} - -static int drr_dev_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - int devidx; - - switch (event) { - case NETDEV_UNREGISTER: - case NETDEV_DOWN: - spin_lock_bh(&state_lock); - - devidx = __multipath_finddev(dev->ifindex); - if (devidx != -1) { - state[devidx].allocated = 0; - state[devidx].ifi = 0; - atomic_set(&state[devidx].usecount, 0); - } - - spin_unlock_bh(&state_lock); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block drr_dev_notifier = { - .notifier_call = drr_dev_event, -}; - - -static void drr_safe_inc(atomic_t *usecount) -{ - int n; - - atomic_inc(usecount); - - n = atomic_read(usecount); - if (n <= 0) { - int i; - - spin_lock_bh(&state_lock); - - for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) - atomic_set(&state[i].usecount, 0); - - spin_unlock_bh(&state_lock); - } -} - -static void drr_select_route(const struct flowi *flp, - struct rtable *first, struct rtable **rp) -{ - struct rtable *nh, *result, *cur_min; - int min_usecount = -1; - int devidx = -1; - int cur_min_devidx = -1; - - /* 1. make sure all alt. nexthops have the same GC related data */ - /* 2. determine the new candidate to be returned */ - result = NULL; - cur_min = NULL; - for (nh = rcu_dereference(first); nh; - nh = rcu_dereference(nh->u.dst.rt_next)) { - if ((nh->u.dst.flags & DST_BALANCED) != 0 && - multipath_comparekeys(&nh->fl, flp)) { - int nh_ifidx = nh->u.dst.dev->ifindex; - - nh->u.dst.lastuse = jiffies; - nh->u.dst.__use++; - if (result != NULL) - continue; - - /* search for the output interface */ - - /* this is not SMP safe, only add/remove are - * SMP safe as wrong usecount updates have no big - * impact - */ - devidx = __multipath_finddev(nh_ifidx); - if (devidx == -1) { - /* add the interface to the array - * SMP safe - */ - spin_lock_bh(&state_lock); - - /* due to SMP: search again */ - devidx = __multipath_finddev(nh_ifidx); - if (devidx == -1) { - /* add entry for device */ - devidx = __multipath_findslot(); - if (devidx == -1) { - /* unlikely but possible */ - continue; - } - - state[devidx].allocated = 1; - state[devidx].ifi = nh_ifidx; - atomic_set(&state[devidx].usecount, 0); - min_usecount = 0; - } - - spin_unlock_bh(&state_lock); - } - - if (min_usecount == 0) { - /* if the device has not been used it is - * the primary target - */ - drr_safe_inc(&state[devidx].usecount); - result = nh; - } else { - int count = - atomic_read(&state[devidx].usecount); - - if (min_usecount == -1 || - count < min_usecount) { - cur_min = nh; - cur_min_devidx = devidx; - min_usecount = count; - } - } - } - } - - if (!result) { - if (cur_min) { - drr_safe_inc(&state[cur_min_devidx].usecount); - result = cur_min; - } else { - result = first; - } - } - - *rp = result; -} - -static struct ip_mp_alg_ops drr_ops = { - .mp_alg_select_route = drr_select_route, -}; - -static int __init drr_init(void) -{ - int err = register_netdevice_notifier(&drr_dev_notifier); - - if (err) - return err; - - err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR); - if (err) - goto fail; - - return 0; - -fail: - unregister_netdevice_notifier(&drr_dev_notifier); - return err; -} - -static void __exit drr_exit(void) -{ - unregister_netdevice_notifier(&drr_dev_notifier); - multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR); -} - -module_init(drr_init); -module_exit(drr_exit); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c deleted file mode 100644 index c312785d14d0..000000000000 --- a/net/ipv4/multipath_random.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Random policy for multipath. - * - * - * Version: $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $ - * - * Authors: Einar Lueck - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MULTIPATH_MAX_CANDIDATES 40 - -static void random_select_route(const struct flowi *flp, - struct rtable *first, - struct rtable **rp) -{ - struct rtable *rt; - struct rtable *decision; - unsigned char candidate_count = 0; - - /* count all candidate */ - for (rt = rcu_dereference(first); rt; - rt = rcu_dereference(rt->u.dst.rt_next)) { - if ((rt->u.dst.flags & DST_BALANCED) != 0 && - multipath_comparekeys(&rt->fl, flp)) - ++candidate_count; - } - - /* choose a random candidate */ - decision = first; - if (candidate_count > 1) { - unsigned char i = 0; - unsigned char candidate_no = (unsigned char) - (random32() % candidate_count); - - /* find chosen candidate and adjust GC data for all candidates - * to ensure they stay in cache - */ - for (rt = first; rt; rt = rt->u.dst.rt_next) { - if ((rt->u.dst.flags & DST_BALANCED) != 0 && - multipath_comparekeys(&rt->fl, flp)) { - rt->u.dst.lastuse = jiffies; - - if (i == candidate_no) - decision = rt; - - if (i >= candidate_count) - break; - - i++; - } - } - } - - decision->u.dst.__use++; - *rp = decision; -} - -static struct ip_mp_alg_ops random_ops = { - .mp_alg_select_route = random_select_route, -}; - -static int __init random_init(void) -{ - return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM); -} - -static void __exit random_exit(void) -{ - multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM); -} - -module_init(random_init); -module_exit(random_exit); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c deleted file mode 100644 index 0ad22524f450..000000000000 --- a/net/ipv4/multipath_rr.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Round robin policy for multipath. - * - * - * Version: $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $ - * - * Authors: Einar Lueck - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void rr_select_route(const struct flowi *flp, - struct rtable *first, struct rtable **rp) -{ - struct rtable *nh, *result, *min_use_cand = NULL; - int min_use = -1; - - /* 1. make sure all alt. nexthops have the same GC related data - * 2. determine the new candidate to be returned - */ - result = NULL; - for (nh = rcu_dereference(first); nh; - nh = rcu_dereference(nh->u.dst.rt_next)) { - if ((nh->u.dst.flags & DST_BALANCED) != 0 && - multipath_comparekeys(&nh->fl, flp)) { - nh->u.dst.lastuse = jiffies; - - if (min_use == -1 || nh->u.dst.__use < min_use) { - min_use = nh->u.dst.__use; - min_use_cand = nh; - } - } - } - result = min_use_cand; - if (!result) - result = first; - - result->u.dst.__use++; - *rp = result; -} - -static struct ip_mp_alg_ops rr_ops = { - .mp_alg_select_route = rr_select_route, -}; - -static int __init rr_init(void) -{ - return multipath_alg_register(&rr_ops, IP_MP_ALG_RR); -} - -static void __exit rr_exit(void) -{ - multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR); -} - -module_init(rr_init); -module_exit(rr_exit); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c deleted file mode 100644 index 57c503694539..000000000000 --- a/net/ipv4/multipath_wrandom.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Weighted random policy for multipath. - * - * - * Version: $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $ - * - * Authors: Einar Lueck - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MULTIPATH_STATE_SIZE 15 - -struct multipath_candidate { - struct multipath_candidate *next; - int power; - struct rtable *rt; -}; - -struct multipath_dest { - struct list_head list; - - const struct fib_nh *nh_info; - __be32 netmask; - __be32 network; - unsigned char prefixlen; - - struct rcu_head rcu; -}; - -struct multipath_bucket { - struct list_head head; - spinlock_t lock; -}; - -struct multipath_route { - struct list_head list; - - int oif; - __be32 gw; - struct list_head dests; - - struct rcu_head rcu; -}; - -/* state: primarily weight per route information */ -static struct multipath_bucket state[MULTIPATH_STATE_SIZE]; - -static unsigned char __multipath_lookup_weight(const struct flowi *fl, - const struct rtable *rt) -{ - const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE; - struct multipath_route *r; - struct multipath_route *target_route = NULL; - struct multipath_dest *d; - int weight = 1; - - /* lookup the weight information for a certain route */ - rcu_read_lock(); - - /* find state entry for gateway or add one if necessary */ - list_for_each_entry_rcu(r, &state[state_idx].head, list) { - if (r->gw == rt->rt_gateway && - r->oif == rt->idev->dev->ifindex) { - target_route = r; - break; - } - } - - if (!target_route) { - /* this should not happen... but we are prepared */ - printk( KERN_CRIT"%s: missing state for gateway: %u and " \ - "device %d\n", __FUNCTION__, rt->rt_gateway, - rt->idev->dev->ifindex); - goto out; - } - - /* find state entry for destination */ - list_for_each_entry_rcu(d, &target_route->dests, list) { - __be32 targetnetwork = fl->fl4_dst & - inet_make_mask(d->prefixlen); - - if ((targetnetwork & d->netmask) == d->network) { - weight = d->nh_info->nh_weight; - goto out; - } - } - -out: - rcu_read_unlock(); - return weight; -} - -static void wrandom_init_state(void) -{ - int i; - - for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { - INIT_LIST_HEAD(&state[i].head); - spin_lock_init(&state[i].lock); - } -} - -static void wrandom_select_route(const struct flowi *flp, - struct rtable *first, - struct rtable **rp) -{ - struct rtable *rt; - struct rtable *decision; - struct multipath_candidate *first_mpc = NULL; - struct multipath_candidate *mpc, *last_mpc = NULL; - int power = 0; - int last_power; - int selector; - const size_t size_mpc = sizeof(struct multipath_candidate); - - /* collect all candidates and identify their weights */ - for (rt = rcu_dereference(first); rt; - rt = rcu_dereference(rt->u.dst.rt_next)) { - if ((rt->u.dst.flags & DST_BALANCED) != 0 && - multipath_comparekeys(&rt->fl, flp)) { - struct multipath_candidate* mpc = - (struct multipath_candidate*) - kmalloc(size_mpc, GFP_ATOMIC); - - if (!mpc) - return; - - power += __multipath_lookup_weight(flp, rt) * 10000; - - mpc->power = power; - mpc->rt = rt; - mpc->next = NULL; - - if (!first_mpc) - first_mpc = mpc; - else - last_mpc->next = mpc; - - last_mpc = mpc; - } - } - - /* choose a weighted random candidate */ - decision = first; - selector = random32() % power; - last_power = 0; - - /* select candidate, adjust GC data and cleanup local state */ - decision = first; - last_mpc = NULL; - for (mpc = first_mpc; mpc; mpc = mpc->next) { - mpc->rt->u.dst.lastuse = jiffies; - if (last_power <= selector && selector < mpc->power) - decision = mpc->rt; - - last_power = mpc->power; - kfree(last_mpc); - last_mpc = mpc; - } - - /* concurrent __multipath_flush may lead to !last_mpc */ - kfree(last_mpc); - - decision->u.dst.__use++; - *rp = decision; -} - -static void wrandom_set_nhinfo(__be32 network, - __be32 netmask, - unsigned char prefixlen, - const struct fib_nh *nh) -{ - const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE; - struct multipath_route *r, *target_route = NULL; - struct multipath_dest *d, *target_dest = NULL; - - /* store the weight information for a certain route */ - spin_lock_bh(&state[state_idx].lock); - - /* find state entry for gateway or add one if necessary */ - list_for_each_entry_rcu(r, &state[state_idx].head, list) { - if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) { - target_route = r; - break; - } - } - - if (!target_route) { - const size_t size_rt = sizeof(struct multipath_route); - target_route = (struct multipath_route *) - kmalloc(size_rt, GFP_ATOMIC); - - target_route->gw = nh->nh_gw; - target_route->oif = nh->nh_oif; - memset(&target_route->rcu, 0, sizeof(struct rcu_head)); - INIT_LIST_HEAD(&target_route->dests); - - list_add_rcu(&target_route->list, &state[state_idx].head); - } - - /* find state entry for destination or add one if necessary */ - list_for_each_entry_rcu(d, &target_route->dests, list) { - if (d->nh_info == nh) { - target_dest = d; - break; - } - } - - if (!target_dest) { - const size_t size_dst = sizeof(struct multipath_dest); - target_dest = (struct multipath_dest*) - kmalloc(size_dst, GFP_ATOMIC); - - target_dest->nh_info = nh; - target_dest->network = network; - target_dest->netmask = netmask; - target_dest->prefixlen = prefixlen; - memset(&target_dest->rcu, 0, sizeof(struct rcu_head)); - - list_add_rcu(&target_dest->list, &target_route->dests); - } - /* else: we already stored this info for another destination => - * we are finished - */ - - spin_unlock_bh(&state[state_idx].lock); -} - -static void __multipath_free(struct rcu_head *head) -{ - struct multipath_route *rt = container_of(head, struct multipath_route, - rcu); - kfree(rt); -} - -static void __multipath_free_dst(struct rcu_head *head) -{ - struct multipath_dest *dst = container_of(head, - struct multipath_dest, - rcu); - kfree(dst); -} - -static void wrandom_flush(void) -{ - int i; - - /* defere delete to all entries */ - for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { - struct multipath_route *r; - - spin_lock_bh(&state[i].lock); - list_for_each_entry_rcu(r, &state[i].head, list) { - struct multipath_dest *d; - list_for_each_entry_rcu(d, &r->dests, list) { - list_del_rcu(&d->list); - call_rcu(&d->rcu, - __multipath_free_dst); - } - list_del_rcu(&r->list); - call_rcu(&r->rcu, - __multipath_free); - } - - spin_unlock_bh(&state[i].lock); - } -} - -static struct ip_mp_alg_ops wrandom_ops = { - .mp_alg_select_route = wrandom_select_route, - .mp_alg_flush = wrandom_flush, - .mp_alg_set_nhinfo = wrandom_set_nhinfo, -}; - -static int __init wrandom_init(void) -{ - wrandom_init_state(); - - return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM); -} - -static void __exit wrandom_exit(void) -{ - multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM); -} - -module_init(wrandom_init); -module_exit(wrandom_exit); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 29ca63e81ced..85285021518b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -101,7 +101,6 @@ #include #include #include -#include #include #include #ifdef CONFIG_SYSCTL @@ -495,13 +494,11 @@ static const struct file_operations rt_cpu_seq_fops = { static __inline__ void rt_free(struct rtable *rt) { - multipath_remove(rt); call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); } static __inline__ void rt_drop(struct rtable *rt) { - multipath_remove(rt); ip_rt_put(rt); call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); } @@ -574,52 +571,6 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) (fl1->iif ^ fl2->iif)) == 0; } -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED -static struct rtable **rt_remove_balanced_route(struct rtable **chain_head, - struct rtable *expentry, - int *removed_count) -{ - int passedexpired = 0; - struct rtable **nextstep = NULL; - struct rtable **rthp = chain_head; - struct rtable *rth; - - if (removed_count) - *removed_count = 0; - - while ((rth = *rthp) != NULL) { - if (rth == expentry) - passedexpired = 1; - - if (((*rthp)->u.dst.flags & DST_BALANCED) != 0 && - compare_keys(&(*rthp)->fl, &expentry->fl)) { - if (*rthp == expentry) { - *rthp = rth->u.dst.rt_next; - continue; - } else { - *rthp = rth->u.dst.rt_next; - rt_free(rth); - if (removed_count) - ++(*removed_count); - } - } else { - if (!((*rthp)->u.dst.flags & DST_BALANCED) && - passedexpired && !nextstep) - nextstep = &rth->u.dst.rt_next; - - rthp = &rth->u.dst.rt_next; - } - } - - rt_free(expentry); - if (removed_count) - ++(*removed_count); - - return nextstep; -} -#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ - - /* This runs via a timer and thus is always in BH context. */ static void rt_check_expire(unsigned long dummy) { @@ -658,22 +609,8 @@ static void rt_check_expire(unsigned long dummy) } /* Cleanup aged off entries. */ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - /* remove all related balanced entries if necessary */ - if (rth->u.dst.flags & DST_BALANCED) { - rthp = rt_remove_balanced_route( - &rt_hash_table[i].chain, - rth, NULL); - if (!rthp) - break; - } else { - *rthp = rth->u.dst.rt_next; - rt_free(rth); - } -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ *rthp = rth->u.dst.rt_next; rt_free(rth); -#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ } spin_unlock(rt_hash_lock_addr(i)); @@ -721,9 +658,6 @@ void rt_cache_flush(int delay) if (delay < 0) delay = ip_rt_min_delay; - /* flush existing multipath state*/ - multipath_flush(); - spin_lock_bh(&rt_flush_lock); if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { @@ -842,30 +776,9 @@ static int rt_garbage_collect(void) rthp = &rth->u.dst.rt_next; continue; } -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - /* remove all related balanced entries - * if necessary - */ - if (rth->u.dst.flags & DST_BALANCED) { - int r; - - rthp = rt_remove_balanced_route( - &rt_hash_table[k].chain, - rth, - &r); - goal -= r; - if (!rthp) - break; - } else { - *rthp = rth->u.dst.rt_next; - rt_free(rth); - goal--; - } -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ *rthp = rth->u.dst.rt_next; rt_free(rth); goal--; -#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ } spin_unlock_bh(rt_hash_lock_addr(k)); if (goal <= 0) @@ -939,12 +852,7 @@ restart: spin_lock_bh(rt_hash_lock_addr(hash)); while ((rth = *rthp) != NULL) { -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (!(rth->u.dst.flags & DST_BALANCED) && - compare_keys(&rth->fl, &rt->fl)) { -#else if (compare_keys(&rth->fl, &rt->fl)) { -#endif /* Put it first */ *rthp = rth->u.dst.rt_next; /* @@ -1774,10 +1682,6 @@ static inline int __mkroute_input(struct sk_buff *skb, atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (res->fi->fib_nhs > 1) - rth->u.dst.flags |= DST_BALANCED; -#endif if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) rth->u.dst.flags |= DST_NOPOLICY; if (IN_DEV_CONF_GET(out_dev, NOXFRM)) @@ -1812,11 +1716,11 @@ static inline int __mkroute_input(struct sk_buff *skb, return err; } -static inline int ip_mkroute_input_def(struct sk_buff *skb, - struct fib_result* res, - const struct flowi *fl, - struct in_device *in_dev, - __be32 daddr, __be32 saddr, u32 tos) +static inline int ip_mkroute_input(struct sk_buff *skb, + struct fib_result* res, + const struct flowi *fl, + struct in_device *in_dev, + __be32 daddr, __be32 saddr, u32 tos) { struct rtable* rth = NULL; int err; @@ -1837,63 +1741,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb, return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); } -static inline int ip_mkroute_input(struct sk_buff *skb, - struct fib_result* res, - const struct flowi *fl, - struct in_device *in_dev, - __be32 daddr, __be32 saddr, u32 tos) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - struct rtable* rth = NULL, *rtres; - unsigned char hop, hopcount; - int err = -EINVAL; - unsigned int hash; - - if (res->fi) - hopcount = res->fi->fib_nhs; - else - hopcount = 1; - - /* distinguish between multipath and singlepath */ - if (hopcount < 2) - return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, - saddr, tos); - - /* add all alternatives to the routing cache */ - for (hop = 0; hop < hopcount; hop++) { - res->nh_sel = hop; - - /* put reference to previous result */ - if (hop) - ip_rt_put(rtres); - - /* create a routing cache entry */ - err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, - &rth); - if (err) - return err; - - /* put it into the cache */ - hash = rt_hash(daddr, saddr, fl->iif); - err = rt_intern_hash(hash, rth, &rtres); - if (err) - return err; - - /* forward hop information to multipath impl. */ - multipath_set_nhinfo(rth, - FIB_RES_NETWORK(*res), - FIB_RES_NETMASK(*res), - res->prefixlen, - &FIB_RES_NH(*res)); - } - skb->dst = &rtres->u.dst; - return err; -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ - return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos); -#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ -} - - /* * NOTE. We drop all the packets that has local source * addresses, because every properly looped back packet @@ -2211,13 +2058,6 @@ static inline int __mkroute_output(struct rtable **result, atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (res->fi) { - rth->rt_multipath_alg = res->fi->fib_mp_alg; - if (res->fi->fib_nhs > 1) - rth->u.dst.flags |= DST_BALANCED; - } -#endif if (IN_DEV_CONF_GET(in_dev, NOXFRM)) rth->u.dst.flags |= DST_NOXFRM; if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) @@ -2277,12 +2117,12 @@ static inline int __mkroute_output(struct rtable **result, return err; } -static inline int ip_mkroute_output_def(struct rtable **rp, - struct fib_result* res, - const struct flowi *fl, - const struct flowi *oldflp, - struct net_device *dev_out, - unsigned flags) +static inline int ip_mkroute_output(struct rtable **rp, + struct fib_result* res, + const struct flowi *fl, + const struct flowi *oldflp, + struct net_device *dev_out, + unsigned flags) { struct rtable *rth = NULL; int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); @@ -2295,68 +2135,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp, return err; } -static inline int ip_mkroute_output(struct rtable** rp, - struct fib_result* res, - const struct flowi *fl, - const struct flowi *oldflp, - struct net_device *dev_out, - unsigned flags) -{ -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - unsigned char hop; - unsigned hash; - int err = -EINVAL; - struct rtable *rth = NULL; - - if (res->fi && res->fi->fib_nhs > 1) { - unsigned char hopcount = res->fi->fib_nhs; - - for (hop = 0; hop < hopcount; hop++) { - struct net_device *dev2nexthop; - - res->nh_sel = hop; - - /* hold a work reference to the output device */ - dev2nexthop = FIB_RES_DEV(*res); - dev_hold(dev2nexthop); - - /* put reference to previous result */ - if (hop) - ip_rt_put(*rp); - - err = __mkroute_output(&rth, res, fl, oldflp, - dev2nexthop, flags); - - if (err != 0) - goto cleanup; - - hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, - oldflp->oif); - err = rt_intern_hash(hash, rth, rp); - - /* forward hop information to multipath impl. */ - multipath_set_nhinfo(rth, - FIB_RES_NETWORK(*res), - FIB_RES_NETMASK(*res), - res->prefixlen, - &FIB_RES_NH(*res)); - cleanup: - /* release work reference to output device */ - dev_put(dev2nexthop); - - if (err != 0) - return err; - } - return err; - } else { - return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, - flags); - } -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ - return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags); -#endif -} - /* * Major route resolver routine. */ @@ -2570,17 +2348,6 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) rth->fl.mark == flp->mark && !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK))) { - - /* check for multipath routes and choose one if - * necessary - */ - if (multipath_select_route(flp, rth, rp)) { - dst_hold(&(*rp)->u.dst); - RT_CACHE_STAT_INC(out_hit); - rcu_read_unlock_bh(); - return 0; - } - rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); rth->u.dst.__use++; @@ -2728,10 +2495,6 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, #ifdef CONFIG_NET_CLS_ROUTE if (rt->u.dst.tclassid) NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); -#endif -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (rt->rt_multipath_alg != IP_MP_ALG_NONE) - NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg); #endif if (rt->fl.iif) NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); -- cgit v1.2.3 From 05646c91109bfd129361d57dc5d98464ab6f6578 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 10 Jun 2007 17:25:24 -0700 Subject: [TIPC]: Optimize stream send routine to avoid fragmentation This patch enhances TIPC's stream socket send routine so that it avoids transmitting data in chunks that require fragmentation and reassembly, thereby improving performance at both the sending and receiving ends of the connection. The "maximum packet size" hint that records MTU info allows the socket to decide how big a chunk it should send; in the event that the hint has become stale, fragmentation may still occur, but the data will be passed correctly and the hint will be updated in time for the following send. Note: The 66060 byte pseudo-MTU used for intra-node connections requires the send routine to perform an additional check to ensure it does not exceed TIPC"s limit of 66000 bytes of user data per chunk. Signed-off-by: Allan Stephens Signed-off-by: Jon Paul Maloy Signed-off-by: David S. Miller --- include/net/tipc/tipc_port.h | 6 ++++-- net/tipc/link.c | 16 ++++++++-------- net/tipc/port.c | 10 +++++----- net/tipc/port.h | 6 ++---- net/tipc/socket.c | 25 +++++++++++++++++-------- 5 files changed, 36 insertions(+), 27 deletions(-) (limited to 'include/net') diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h index 333bba6dc522..cfc4ba46de8f 100644 --- a/include/net/tipc/tipc_port.h +++ b/include/net/tipc/tipc_port.h @@ -1,8 +1,8 @@ /* * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports * - * Copyright (c) 1994-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 1994-2007, Ericsson AB + * Copyright (c) 2005-2007, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,7 @@ * @conn_unacked: number of unacknowledged messages received from peer port * @published: non-zero if port has one or more associated names * @congested: non-zero if cannot send because of link or port congestion + * @max_pkt: maximum packet size "hint" used when building messages sent by port * @ref: unique reference to port in TIPC object registry * @phdr: preformatted message header used when sending messages */ @@ -68,6 +69,7 @@ struct tipc_port { u32 conn_unacked; int published; u32 congested; + u32 max_pkt; u32 ref; struct tipc_msg phdr; }; diff --git a/net/tipc/link.c b/net/tipc/link.c index 2124f32ef29f..5adfdfd49d61 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1,8 +1,8 @@ /* * net/tipc/link.c: TIPC link code * - * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2004-2006, Wind River Systems + * Copyright (c) 1996-2007, Ericsson AB + * Copyright (c) 2004-2007, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1260,7 +1260,7 @@ again: * (Must not hold any locks while building message.) */ - res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, + res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, !sender->user_port, &buf); read_lock_bh(&tipc_net_lock); @@ -1271,7 +1271,7 @@ again: if (likely(l_ptr)) { if (likely(buf)) { res = link_send_buf_fast(l_ptr, buf, - &sender->max_pkt); + &sender->publ.max_pkt); if (unlikely(res < 0)) buf_discard(buf); exit: @@ -1299,12 +1299,12 @@ exit: * then re-try fast path or fragment the message */ - sender->max_pkt = link_max_pkt(l_ptr); + sender->publ.max_pkt = link_max_pkt(l_ptr); tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); - if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) + if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt) goto again; return link_send_sections_long(sender, msg_sect, @@ -1357,7 +1357,7 @@ static int link_send_sections_long(struct port *sender, again: fragm_no = 1; - max_pkt = sender->max_pkt - INT_H_SIZE; + max_pkt = sender->publ.max_pkt - INT_H_SIZE; /* leave room for tunnel header in case of link changeover */ fragm_sz = max_pkt - INT_H_SIZE; /* leave room for fragmentation header in each fragment */ @@ -1463,7 +1463,7 @@ error: goto reject; } if (link_max_pkt(l_ptr) < max_pkt) { - sender->max_pkt = link_max_pkt(l_ptr); + sender->publ.max_pkt = link_max_pkt(l_ptr); tipc_node_unlock(node); for (; buf_chain; buf_chain = buf) { buf = buf_chain->next; diff --git a/net/tipc/port.c b/net/tipc/port.c index bcd5da00737b..5d2b9ce84d0a 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -1,8 +1,8 @@ /* * net/tipc/port.c: TIPC port code * - * Copyright (c) 1992-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 1992-2007, Ericsson AB + * Copyright (c) 2004-2007, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -239,6 +239,8 @@ u32 tipc_createport_raw(void *usr_handle, } tipc_port_lock(ref); + p_ptr->publ.usr_handle = usr_handle; + p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; p_ptr->publ.ref = ref; msg = &p_ptr->publ.phdr; msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); @@ -248,11 +250,9 @@ u32 tipc_createport_raw(void *usr_handle, msg_set_importance(msg,importance); p_ptr->last_in_seqno = 41; p_ptr->sent = 1; - p_ptr->publ.usr_handle = usr_handle; INIT_LIST_HEAD(&p_ptr->wait_list); INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); p_ptr->congested_link = NULL; - p_ptr->max_pkt = MAX_PKT_DEFAULT; p_ptr->dispatcher = dispatcher; p_ptr->wakeup = wakeup; p_ptr->user_port = NULL; @@ -1243,7 +1243,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) res = TIPC_OK; exit: tipc_port_unlock(p_ptr); - p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); + p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref); return res; } diff --git a/net/tipc/port.h b/net/tipc/port.h index 7ef4d64b32f7..e5f8c16429bd 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -1,8 +1,8 @@ /* * net/tipc/port.h: Include file for TIPC port code * - * Copyright (c) 1994-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 1994-2007, Ericsson AB + * Copyright (c) 2004-2007, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,7 +81,6 @@ struct user_port { * @acked: * @publications: list of publications for port * @pub_count: total # of publications port has made during its lifetime - * @max_pkt: maximum packet size "hint" used when building messages sent by port * @probing_state: * @probing_interval: * @last_in_seqno: @@ -102,7 +101,6 @@ struct port { u32 acked; struct list_head publications; u32 pub_count; - u32 max_pkt; u32 probing_state; u32 probing_interval; u32 last_in_seqno; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index ac7f2aacc77b..4a8f37f48764 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -607,23 +607,24 @@ exit: static int send_stream(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { + struct tipc_port *tport; struct msghdr my_msg; struct iovec my_iov; struct iovec *curr_iov; int curr_iovlen; char __user *curr_start; + u32 hdr_size; int curr_left; int bytes_to_send; int bytes_sent; int res; - if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) - return send_packet(iocb, sock, m, total_len); - - /* Can only send large data streams if already connected */ + /* Handle special cases where there is no connection */ if (unlikely(sock->state != SS_CONNECTED)) { - if (sock->state == SS_DISCONNECTING) + if (sock->state == SS_UNCONNECTED) + return send_packet(iocb, sock, m, total_len); + else if (sock->state == SS_DISCONNECTING) return -EPIPE; else return -ENOTCONN; @@ -648,17 +649,25 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, my_msg.msg_name = NULL; bytes_sent = 0; + tport = tipc_sk(sock->sk)->p; + hdr_size = msg_hdr_sz(&tport->phdr); + while (curr_iovlen--) { curr_start = curr_iov->iov_base; curr_left = curr_iov->iov_len; while (curr_left) { - bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE) - ? curr_left : TIPC_MAX_USER_MSG_SIZE; + bytes_to_send = tport->max_pkt - hdr_size; + if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE) + bytes_to_send = TIPC_MAX_USER_MSG_SIZE; + if (curr_left < bytes_to_send) + bytes_to_send = curr_left; my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { - return bytes_sent ? bytes_sent : res; + if (bytes_sent != 0) + res = bytes_sent; + return res; } curr_left -= bytes_to_send; curr_start += bytes_to_send; -- cgit v1.2.3 From 8de0a15483b357d0f0b821330ec84d1660cadc4e Mon Sep 17 00:00:00 2001 From: Ville Tervo Date: Wed, 11 Jul 2007 09:23:41 +0200 Subject: [Bluetooth] Keep rfcomm_dev on the list until it is freed This patch changes the RFCOMM TTY release process so that the TTY is kept on the list until it is really freed. A new device flag is used to keep track of released TTYs. Signed-off-by: Ville Tervo Signed-off-by: Marcel Holtmann --- include/net/bluetooth/rfcomm.h | 1 + net/bluetooth/rfcomm/tty.c | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'include/net') diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 3c563f02907c..25aa575db807 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc #define RFCOMM_RELEASE_ONHUP 1 #define RFCOMM_HANGUP_NOW 2 #define RFCOMM_TTY_ATTACHED 3 +#define RFCOMM_TTY_RELEASED 4 struct rfcomm_dev_req { s16 dev_id; diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index ba469b038ea0..23ba61a13bdd 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) BT_DBG("dev %p dlc %p", dev, dlc); + write_lock_bh(&rfcomm_dev_lock); + list_del_init(&dev->list); + write_unlock_bh(&rfcomm_dev_lock); + rfcomm_dlc_lock(dlc); /* Detach DLC if it's owned by this dev */ if (dlc->owner == dev) @@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) read_lock(&rfcomm_dev_lock); dev = __rfcomm_dev_get(id); - if (dev) - rfcomm_dev_hold(dev); + + if (dev) { + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) + dev = NULL; + else + rfcomm_dev_hold(dev); + } read_unlock(&rfcomm_dev_lock); @@ -265,6 +274,12 @@ out: dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); + if (IS_ERR(dev->tty_dev)) { + list_del(&dev->list); + kfree(dev); + return PTR_ERR(dev->tty_dev); + } + return dev->id; } @@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) { BT_DBG("dev %p", dev); - write_lock_bh(&rfcomm_dev_lock); - list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); - + set_bit(RFCOMM_TTY_RELEASED, &dev->flags); rfcomm_dev_put(dev); } @@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); + BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) return -EPERM; @@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); + BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); if (!(dev = rfcomm_dev_get(req.dev_id))) return -ENODEV; @@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg) list_for_each(p, &rfcomm_dev_list) { struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) + continue; (di + n)->id = dev->id; (di + n)->flags = dev->flags; (di + n)->state = dev->dlc->state; -- cgit v1.2.3 From 38f7b870d4a6a5d3ec21557e849620cb7d032965 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 13 Jun 2007 12:03:51 -0700 Subject: [RTNETLINK]: Link creation API Add rtnetlink API for creating, changing and deleting software devices. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/if_link.h | 13 ++ include/linux/netdevice.h | 3 + include/net/rtnetlink.h | 58 ++++++++ net/core/rtnetlink.c | 342 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 409 insertions(+), 7 deletions(-) (limited to 'include/net') diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 604c2434f71c..3144babd2357 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -76,6 +76,8 @@ enum #define IFLA_WEIGHT IFLA_WEIGHT IFLA_OPERSTATE, IFLA_LINKMODE, + IFLA_LINKINFO, +#define IFLA_LINKINFO IFLA_LINKINFO __IFLA_MAX }; @@ -140,4 +142,15 @@ struct ifla_cacheinfo __u32 retrans_time; }; +enum +{ + IFLA_INFO_UNSPEC, + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, + __IFLA_INFO_MAX, +}; + +#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) + #endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 94cc77cd3aa3..e7913ee5581c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -540,6 +540,9 @@ struct net_device struct device dev; /* space for optional statistics and wireless sysfs groups */ struct attribute_group *sysfs_groups[3]; + + /* rtnetlink link ops */ + const struct rtnl_link_ops *rtnl_link_ops; }; #define to_net_dev(d) container_of(d, struct net_device, dev) diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 3b3d4745618d..3861c05cdf0f 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -22,4 +22,62 @@ static inline int rtnl_msg_family(struct nlmsghdr *nlh) return AF_UNSPEC; } +/** + * struct rtnl_link_ops - rtnetlink link operations + * + * @list: Used internally + * @kind: Identifier + * @maxtype: Highest device specific netlink attribute number + * @policy: Netlink policy for device specific attribute validation + * @validate: Optional validation function for netlink/changelink parameters + * @priv_size: sizeof net_device private space + * @setup: net_device setup function + * @newlink: Function for configuring and registering a new device + * @changelink: Function for changing parameters of an existing device + * @dellink: Function to remove a device + * @get_size: Function to calculate required room for dumping device + * specific netlink attributes + * @fill_info: Function to dump device specific netlink attributes + * @get_xstats_size: Function to calculate required room for dumping devic + * specific statistics + * @fill_xstats: Function to dump device specific statistics + */ +struct rtnl_link_ops { + struct list_head list; + + const char *kind; + + size_t priv_size; + void (*setup)(struct net_device *dev); + + int maxtype; + const struct nla_policy *policy; + int (*validate)(struct nlattr *tb[], + struct nlattr *data[]); + + int (*newlink)(struct net_device *dev, + struct nlattr *tb[], + struct nlattr *data[]); + int (*changelink)(struct net_device *dev, + struct nlattr *tb[], + struct nlattr *data[]); + void (*dellink)(struct net_device *dev); + + size_t (*get_size)(const struct net_device *dev); + int (*fill_info)(struct sk_buff *skb, + const struct net_device *dev); + + size_t (*get_xstats_size)(const struct net_device *dev); + int (*fill_xstats)(struct sk_buff *skb, + const struct net_device *dev); +}; + +extern int __rtnl_link_register(struct rtnl_link_ops *ops); +extern void __rtnl_link_unregister(struct rtnl_link_ops *ops); + +extern int rtnl_link_register(struct rtnl_link_ops *ops); +extern void rtnl_link_unregister(struct rtnl_link_ops *ops); + +#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) + #endif diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 25ca219154e0..06c0c5afabf0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -243,6 +243,143 @@ void rtnl_unregister_all(int protocol) EXPORT_SYMBOL_GPL(rtnl_unregister_all); +static LIST_HEAD(link_ops); + +/** + * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. + * @ops: struct rtnl_link_ops * to register + * + * The caller must hold the rtnl_mutex. This function should be used + * by drivers that create devices during module initialization. It + * must be called before registering the devices. + * + * Returns 0 on success or a negative error code. + */ +int __rtnl_link_register(struct rtnl_link_ops *ops) +{ + list_add_tail(&ops->list, &link_ops); + return 0; +} + +EXPORT_SYMBOL_GPL(__rtnl_link_register); + +/** + * rtnl_link_register - Register rtnl_link_ops with rtnetlink. + * @ops: struct rtnl_link_ops * to register + * + * Returns 0 on success or a negative error code. + */ +int rtnl_link_register(struct rtnl_link_ops *ops) +{ + int err; + + rtnl_lock(); + err = __rtnl_link_register(ops); + rtnl_unlock(); + return err; +} + +EXPORT_SYMBOL_GPL(rtnl_link_register); + +/** + * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. + * @ops: struct rtnl_link_ops * to unregister + * + * The caller must hold the rtnl_mutex. This function should be used + * by drivers that unregister devices during module unloading. It must + * be called after unregistering the devices. + */ +void __rtnl_link_unregister(struct rtnl_link_ops *ops) +{ + list_del(&ops->list); +} + +EXPORT_SYMBOL_GPL(__rtnl_link_unregister); + +/** + * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. + * @ops: struct rtnl_link_ops * to unregister + */ +void rtnl_link_unregister(struct rtnl_link_ops *ops) +{ + rtnl_lock(); + __rtnl_link_unregister(ops); + rtnl_unlock(); +} + +EXPORT_SYMBOL_GPL(rtnl_link_unregister); + +static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) +{ + const struct rtnl_link_ops *ops; + + list_for_each_entry(ops, &link_ops, list) { + if (!strcmp(ops->kind, kind)) + return ops; + } + return NULL; +} + +static size_t rtnl_link_get_size(const struct net_device *dev) +{ + const struct rtnl_link_ops *ops = dev->rtnl_link_ops; + size_t size; + + if (!ops) + return 0; + + size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ + nlmsg_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ + + if (ops->get_size) + /* IFLA_INFO_DATA + nested data */ + size += nlmsg_total_size(sizeof(struct nlattr)) + + ops->get_size(dev); + + if (ops->get_xstats_size) + size += ops->get_xstats_size(dev); /* IFLA_INFO_XSTATS */ + + return size; +} + +static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) +{ + const struct rtnl_link_ops *ops = dev->rtnl_link_ops; + struct nlattr *linkinfo, *data; + int err = -EMSGSIZE; + + linkinfo = nla_nest_start(skb, IFLA_LINKINFO); + if (linkinfo == NULL) + goto out; + + if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) + goto err_cancel_link; + if (ops->fill_xstats) { + err = ops->fill_xstats(skb, dev); + if (err < 0) + goto err_cancel_link; + } + if (ops->fill_info) { + data = nla_nest_start(skb, IFLA_INFO_DATA); + if (data == NULL) + goto err_cancel_link; + err = ops->fill_info(skb, dev); + if (err < 0) + goto err_cancel_data; + nla_nest_end(skb, data); + } + + nla_nest_end(skb, linkinfo); + return 0; + +err_cancel_data: + nla_nest_cancel(skb, data); +err_cancel_link: + nla_nest_cancel(skb, linkinfo); +out: + return err; +} + static const int rtm_min[RTM_NR_FAMILIES] = { [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), @@ -437,7 +574,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->tx_compressed = b->tx_compressed; }; -static inline size_t if_nlmsg_size(void) +static inline size_t if_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ @@ -452,7 +589,8 @@ static inline size_t if_nlmsg_size(void) + nla_total_size(4) /* IFLA_LINK */ + nla_total_size(4) /* IFLA_MASTER */ + nla_total_size(1) /* IFLA_OPERSTATE */ - + nla_total_size(1); /* IFLA_LINKMODE */ + + nla_total_size(1) /* IFLA_LINKMODE */ + + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ } static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, @@ -522,6 +660,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, } } + if (dev->rtnl_link_ops) { + if (rtnl_link_fill(skb, dev) < 0) + goto nla_put_failure; + } + return nlmsg_end(skb, nlh); nla_put_failure: @@ -553,6 +696,8 @@ cont: static const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, + [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, + [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, [IFLA_MTU] = { .type = NLA_U32 }, [IFLA_TXQLEN] = { .type = NLA_U32 }, @@ -561,10 +706,15 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_LINKMODE] = { .type = NLA_U8 }, }; +static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { + [IFLA_INFO_KIND] = { .type = NLA_STRING }, + [IFLA_INFO_DATA] = { .type = NLA_NESTED }, +}; + static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, - struct nlattr **tb, char *ifname) + struct nlattr **tb, char *ifname, int modified) { - int modified = 0, send_addr_notify = 0; + int send_addr_notify = 0; int err; if (tb[IFLA_MAP]) { @@ -729,13 +879,189 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) goto errout_dev; - err = do_setlink(dev, ifm, tb, ifname); + err = do_setlink(dev, ifm, tb, ifname, 0); errout_dev: dev_put(dev); errout: return err; } +static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + const struct rtnl_link_ops *ops; + struct net_device *dev; + struct ifinfomsg *ifm; + char ifname[IFNAMSIZ]; + struct nlattr *tb[IFLA_MAX+1]; + int err; + + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); + if (err < 0) + return err; + + if (tb[IFLA_IFNAME]) + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); + + ifm = nlmsg_data(nlh); + if (ifm->ifi_index > 0) + dev = __dev_get_by_index(ifm->ifi_index); + else if (tb[IFLA_IFNAME]) + dev = __dev_get_by_name(ifname); + else + return -EINVAL; + + if (!dev) + return -ENODEV; + + ops = dev->rtnl_link_ops; + if (!ops) + return -EOPNOTSUPP; + + ops->dellink(dev); + return 0; +} + +static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + const struct rtnl_link_ops *ops; + struct net_device *dev; + struct ifinfomsg *ifm; + char kind[MODULE_NAME_LEN]; + char ifname[IFNAMSIZ]; + struct nlattr *tb[IFLA_MAX+1]; + struct nlattr *linkinfo[IFLA_INFO_MAX+1]; + int err; + +replay: + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); + if (err < 0) + return err; + + if (tb[IFLA_IFNAME]) + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); + else + ifname[0] = '\0'; + + ifm = nlmsg_data(nlh); + if (ifm->ifi_index > 0) + dev = __dev_get_by_index(ifm->ifi_index); + else if (ifname[0]) + dev = __dev_get_by_name(ifname); + else + dev = NULL; + + if (tb[IFLA_LINKINFO]) { + err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, + tb[IFLA_LINKINFO], ifla_info_policy); + if (err < 0) + return err; + } else + memset(linkinfo, 0, sizeof(linkinfo)); + + if (linkinfo[IFLA_INFO_KIND]) { + nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); + ops = rtnl_link_ops_get(kind); + } else { + kind[0] = '\0'; + ops = NULL; + } + + if (1) { + struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; + + if (ops) { + if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { + err = nla_parse_nested(attr, ops->maxtype, + linkinfo[IFLA_INFO_DATA], + ops->policy); + if (err < 0) + return err; + data = attr; + } + if (ops->validate) { + err = ops->validate(tb, data); + if (err < 0) + return err; + } + } + + if (dev) { + int modified = 0; + + if (nlh->nlmsg_flags & NLM_F_EXCL) + return -EEXIST; + if (nlh->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + + if (linkinfo[IFLA_INFO_DATA]) { + if (!ops || ops != dev->rtnl_link_ops || + !ops->changelink) + return -EOPNOTSUPP; + + err = ops->changelink(dev, tb, data); + if (err < 0) + return err; + modified = 1; + } + + return do_setlink(dev, ifm, tb, ifname, modified); + } + + if (!(nlh->nlmsg_flags & NLM_F_CREATE)) + return -ENODEV; + + if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) + return -EOPNOTSUPP; + if (tb[IFLA_ADDRESS] || tb[IFLA_BROADCAST] || tb[IFLA_MAP] || + tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) + return -EOPNOTSUPP; + + if (!ops) { +#ifdef CONFIG_KMOD + if (kind[0]) { + __rtnl_unlock(); + request_module("rtnl-link-%s", kind); + rtnl_lock(); + ops = rtnl_link_ops_get(kind); + if (ops) + goto replay; + } +#endif + return -EOPNOTSUPP; + } + + if (!ifname[0]) + snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); + dev = alloc_netdev(ops->priv_size, ifname, ops->setup); + if (!dev) + return -ENOMEM; + + if (strchr(dev->name, '%')) { + err = dev_alloc_name(dev, dev->name); + if (err < 0) + goto err_free; + } + dev->rtnl_link_ops = ops; + + if (tb[IFLA_MTU]) + dev->mtu = nla_get_u32(tb[IFLA_MTU]); + if (tb[IFLA_TXQLEN]) + dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); + if (tb[IFLA_WEIGHT]) + dev->weight = nla_get_u32(tb[IFLA_WEIGHT]); + if (tb[IFLA_OPERSTATE]) + set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); + if (tb[IFLA_LINKMODE]) + dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); + + err = ops->newlink(dev, tb, data); +err_free: + if (err < 0) + free_netdev(dev); + return err; + } +} + static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct ifinfomsg *ifm; @@ -756,7 +1082,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) } else return -EINVAL; - nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); + nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); if (nskb == NULL) { err = -ENOBUFS; goto errout; @@ -806,7 +1132,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); + skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); if (skb == NULL) goto errout; @@ -961,6 +1287,8 @@ void __init rtnetlink_init(void) rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); + rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); + rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); -- cgit v1.2.3 From 1092cb219774a82b1f16781aec7b8d4ec727c981 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 25 Jun 2007 13:49:35 -0700 Subject: [NETLINK]: attr: add nested compat attribute type Add a nested compat attribute type that can be used to convert attributes that contain a structure to nested attributes in a backwards compatible way. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netlink.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ net/netlink/attr.c | 11 +++++++ 2 files changed, 95 insertions(+) (limited to 'include/net') diff --git a/include/net/netlink.h b/include/net/netlink.h index 7b510a9edb91..d7b824be5422 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -118,6 +118,9 @@ * Nested Attributes Construction: * nla_nest_start(skb, type) start a nested attribute * nla_nest_end(skb, nla) finalize a nested attribute + * nla_nest_compat_start(skb, type, start a nested compat attribute + * len, data) + * nla_nest_compat_end(skb, type) finalize a nested compat attribute * nla_nest_cancel(skb, nla) cancel nested attribute construction * * Attribute Length Calculations: @@ -152,6 +155,7 @@ * nla_find_nested() find attribute in nested attributes * nla_parse() parse and validate stream of attrs * nla_parse_nested() parse nested attribuets + * nla_parse_nested_compat() parse nested compat attributes * nla_for_each_attr() loop over all attributes * nla_for_each_nested() loop over the nested attributes *========================================================================= @@ -170,6 +174,7 @@ enum { NLA_FLAG, NLA_MSECS, NLA_NESTED, + NLA_NESTED_COMPAT, NLA_NUL_STRING, NLA_BINARY, __NLA_TYPE_MAX, @@ -190,6 +195,7 @@ enum { * NLA_NUL_STRING Maximum length of string (excluding NUL) * NLA_FLAG Unused * NLA_BINARY Maximum length of attribute payload + * NLA_NESTED_COMPAT Exact length of structure payload * All other Exact length of attribute payload * * Example: @@ -733,6 +739,39 @@ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, { return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); } + +/** + * nla_parse_nested_compat - parse nested compat attributes + * @tb: destination array with maxtype+1 elements + * @maxtype: maximum attribute type to be expected + * @nla: attribute containing the nested attributes + * @data: pointer to point to contained structure + * @len: length of contained structure + * @policy: validation policy + * + * Parse a nested compat attribute. The compat attribute contains a structure + * and optionally a set of nested attributes. On success the data pointer + * points to the nested data and tb contains the parsed attributes + * (see nla_parse). + */ +static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype, + struct nlattr *nla, + const struct nla_policy *policy, + int len) +{ + if (nla_len(nla) < len) + return -1; + if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr)) + return nla_parse_nested(tb, maxtype, + nla_data(nla) + NLA_ALIGN(len), + policy); + memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); + return 0; +} + +#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \ +({ data = nla_len(nla) >= len ? nla_data(nla) : NULL; \ + __nla_parse_nested_compat(tb, maxtype, nla, policy, len); }) /** * nla_put_u8 - Add a u16 netlink attribute to a socket buffer * @skb: socket buffer to add attribute to @@ -964,6 +1003,51 @@ static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start) return skb->len; } +/** + * nla_nest_compat_start - Start a new level of nested compat attributes + * @skb: socket buffer to add attributes to + * @attrtype: attribute type of container + * @attrlen: length of structure + * @data: pointer to structure + * + * Start a nested compat attribute that contains both a structure and + * a set of nested attributes. + * + * Returns the container attribute + */ +static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb, + int attrtype, int attrlen, + const void *data) +{ + struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb); + + if (nla_put(skb, attrtype, attrlen, data) < 0) + return NULL; + if (nla_nest_start(skb, attrtype) == NULL) { + nlmsg_trim(skb, start); + return NULL; + } + return start; +} + +/** + * nla_nest_compat_end - Finalize nesting of compat attributes + * @skb: socket buffer the attribtues are stored in + * @start: container attribute + * + * Corrects the container attribute header to include the all + * appeneded attributes. + * + * Returns the total data length of the skb. + */ +static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start) +{ + struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len); + + start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start; + return nla_nest_end(skb, nest); +} + /** * nla_nest_cancel - Cancel nesting of attributes * @skb: socket buffer the message is stored in diff --git a/net/netlink/attr.c b/net/netlink/attr.c index c591212793ee..e4d7bed99c2e 100644 --- a/net/netlink/attr.c +++ b/net/netlink/attr.c @@ -72,6 +72,17 @@ static int validate_nla(struct nlattr *nla, int maxtype, return -ERANGE; break; + case NLA_NESTED_COMPAT: + if (attrlen < pt->len) + return -ERANGE; + if (attrlen < NLA_ALIGN(pt->len)) + break; + if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN) + return -ERANGE; + nla = nla_data(nla) + NLA_ALIGN(pt->len); + if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla)) + return -ERANGE; + break; default: if (pt->len) minlen = pt->len; -- cgit v1.2.3 From 136ebf08b46f839e2dc9db34322b654e5d9b9936 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Tue, 26 Jun 2007 23:51:41 -0700 Subject: [IPV6] MIP6: Kill unnecessary ifdefs. Kill unnecessary CONFIG_IPV6_MIP6. o It is redundant for RAW socket to keep MH out with the config then it can handle any protocol. o Clean-up at AH. Signed-off-by: Masahide NAKAMURA Signed-off-by: David S. Miller --- include/net/flow.h | 4 ---- include/net/xfrm.h | 2 -- net/ipv6/ah6.c | 4 ++-- net/ipv6/raw.c | 4 ---- 4 files changed, 2 insertions(+), 12 deletions(-) (limited to 'include/net') diff --git a/include/net/flow.h b/include/net/flow.h index f3cc1f812619..af59fa5cc1f8 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -67,20 +67,16 @@ struct flowi { __be32 spi; -#ifdef CONFIG_IPV6_MIP6 struct { __u8 type; } mht; -#endif } uli_u; #define fl_ip_sport uli_u.ports.sport #define fl_ip_dport uli_u.ports.dport #define fl_icmp_type uli_u.icmpt.type #define fl_icmp_code uli_u.icmpt.code #define fl_ipsec_spi uli_u.spi -#ifdef CONFIG_IPV6_MIP6 #define fl_mh_type uli_u.mht.type -#endif __u32 secid; /* used by xfrm; see secid.txt */ } __attribute__((__aligned__(BITS_PER_LONG/8))); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 311f25af5e1a..7720c1182bb4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -509,11 +509,9 @@ __be16 xfrm_flowi_sport(struct flowi *fl) case IPPROTO_ICMPV6: port = htons(fl->fl_icmp_type); break; -#ifdef CONFIG_IPV6_MIP6 case IPPROTO_MH: port = htons(fl->fl_mh_type); break; -#endif default: port = 0; /*XXX*/ } diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 128f94c79c64..01fa302d281e 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -132,6 +132,8 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des bad: return; } +#else +static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {} #endif /** @@ -189,10 +191,8 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) while (exthdr.raw < end) { switch (nexthdr) { case NEXTHDR_DEST: -#ifdef CONFIG_IPV6_MIP6 if (dir == XFRM_POLICY_OUT) ipv6_rearrange_destopt(iph, exthdr.opth); -#endif case NEXTHDR_HOP: if (!zero_out_mutable_opts(exthdr.opth)) { LIMIT_NETDEBUG( diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a58459a76684..a22c9c93d931 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -611,9 +611,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) struct iovec *iov; u8 __user *type = NULL; u8 __user *code = NULL; -#ifdef CONFIG_IPV6_MIP6 u8 len = 0; -#endif int probed = 0; int i; @@ -646,7 +644,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) probed = 1; } break; -#ifdef CONFIG_IPV6_MIP6 case IPPROTO_MH: if (iov->iov_base && iov->iov_len < 1) break; @@ -660,7 +657,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) len += iov->iov_len; break; -#endif default: probed = 1; break; -- cgit v1.2.3 From 59fbb3a61e02deaeaa4fb50792217921f3002d64 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Tue, 26 Jun 2007 23:56:32 -0700 Subject: [IPV6] MIP6: Loadable module support for MIPv6. This patch makes MIPv6 loadable module named "mip6". Here is a modprobe.conf(5) example to load it automatically when user application uses XFRM state for MIPv6: alias xfrm-type-10-43 mip6 alias xfrm-type-10-60 mip6 Some MIPv6 feature is not included by this modular, however, it should not be affected to other features like either IPsec or IPv6 with and without the patch. We may discuss XFRM, MH (RAW socket) and ancillary data/sockopt separately for future work. Loadable features: * MH receiving check (to send ICMP error back) * RO header parsing and building (i.e. RH2 and HAO in DSTOPTS) * XFRM policy/state database handling for RO These are NOT covered as loadable: * Home Address flags and its rule on source address selection * XFRM sub policy (depends on its own kernel option) * XFRM functions to receive RO as IPv6 extension header * MH sending/receiving through raw socket if user application opens it (since raw socket allows to do so) * RH2 sending as ancillary data * RH2 operation with setsockopt(2) Signed-off-by: Masahide NAKAMURA Signed-off-by: David S. Miller --- include/linux/ipv6.h | 2 +- include/net/addrconf.h | 2 +- include/net/mip6.h | 4 ---- include/net/rawv6.h | 9 +++++++++ net/ipv6/Kconfig | 2 +- net/ipv6/Makefile | 2 +- net/ipv6/addrconf.c | 4 ++-- net/ipv6/af_inet6.c | 10 +--------- net/ipv6/ah6.c | 8 ++++---- net/ipv6/datagram.c | 2 +- net/ipv6/exthdrs.c | 19 ++++++++++--------- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_output.c | 2 +- net/ipv6/ipv6_sockglue.c | 2 +- net/ipv6/mip6.c | 22 +++++++++++++++++++--- net/ipv6/raw.c | 34 +++++++++++++++++++++++++++++++--- net/ipv6/xfrm6_policy.c | 4 ++-- net/ipv6/xfrm6_state.c | 4 ++-- 18 files changed, 88 insertions(+), 46 deletions(-) (limited to 'include/net') diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 648bd1f0912d..213b63be3c8f 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -247,7 +247,7 @@ struct inet6_skb_parm { __u16 lastopt; __u32 nhoff; __u16 flags; -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) __u16 dsthao; #endif diff --git a/include/net/addrconf.h b/include/net/addrconf.h index f3531d0bcd05..33b593e17441 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -61,7 +61,7 @@ extern int addrconf_set_dstaddr(void __user *arg); extern int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict); -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) extern int ipv6_chk_home_addr(struct in6_addr *addr); #endif extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, diff --git a/include/net/mip6.h b/include/net/mip6.h index 68263c6d9996..63272610a24a 100644 --- a/include/net/mip6.h +++ b/include/net/mip6.h @@ -54,8 +54,4 @@ struct ip6_mh { #define IP6_MH_TYPE_BERROR 7 /* Binding Error */ #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR -extern int mip6_init(void); -extern void mip6_fini(void); -extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb); - #endif diff --git a/include/net/rawv6.h b/include/net/rawv6.h index af8960878ef4..a5819891d525 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + #define RAWV6_HTABLE_SIZE MAX_INET_PROTOS extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; extern rwlock_t raw_v6_lock; @@ -23,6 +25,13 @@ extern void rawv6_err(struct sock *sk, int type, int code, int offset, __be32 info); +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) +int rawv6_mh_filter_register(int (*filter)(struct sock *sock, + struct sk_buff *skb)); +int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, + struct sk_buff *skb)); +#endif + #endif #endif diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 8e5d54f23b49..eb0b8085949b 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -109,7 +109,7 @@ config INET6_IPCOMP If unsure, say Y. config IPV6_MIP6 - bool "IPv6: Mobility (EXPERIMENTAL)" + tristate "IPv6: Mobility (EXPERIMENTAL)" depends on IPV6 && EXPERIMENTAL select XFRM ---help--- diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index bb33309044c9..87c23a73d284 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -14,7 +14,6 @@ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ xfrm6_output.o ipv6-$(CONFIG_NETFILTER) += netfilter.o ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o -ipv6-$(CONFIG_IPV6_MIP6) += mip6.o ipv6-$(CONFIG_PROC_FS) += proc.o ipv6-objs += $(ipv6-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o +obj-$(CONFIG_IPV6_MIP6) += mip6.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IPV6_SIT) += sit.o diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 79b79f3de24c..11c0028863b0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1034,7 +1034,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, } /* Rule 4: Prefer home address */ -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) if (hiscore.rule < 4) { if (ifa_result->flags & IFA_F_HOMEADDRESS) hiscore.attrs |= IPV6_SADDR_SCORE_HOA; @@ -2835,7 +2835,7 @@ void if6_proc_exit(void) } #endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) /* Check if address is a home address configured on any interface. */ int ipv6_chk_home_addr(struct in6_addr *addr) { diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6dd377253cf7..eed09373a45d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -58,9 +58,6 @@ #ifdef CONFIG_IPV6_TUNNEL #include #endif -#ifdef CONFIG_IPV6_MIP6 -#include -#endif #include #include @@ -853,9 +850,6 @@ static int __init inet6_init(void) ipv6_frag_init(); ipv6_nodata_init(); ipv6_destopt_init(); -#ifdef CONFIG_IPV6_MIP6 - mip6_init(); -#endif /* Init v6 transport protocols. */ udpv6_init(); @@ -921,9 +915,7 @@ static void __exit inet6_exit(void) /* Cleanup code parts. */ ipv6_packet_cleanup(); -#ifdef CONFIG_IPV6_MIP6 - mip6_fini(); -#endif + addrconf_cleanup(); ip6_flowlabel_cleanup(); ip6_route_cleanup(); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 01fa302d281e..cc6884a40be4 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -74,7 +74,7 @@ bad: return 0; } -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) /** * ipv6_rearrange_destopt - rearrange IPv6 destination options header * @iph: IPv6 header @@ -228,7 +228,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) u8 nexthdr; char tmp_base[8]; struct { -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) struct in6_addr saddr; #endif struct in6_addr daddr; @@ -255,7 +255,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) err = -ENOMEM; goto error; } -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) memcpy(tmp_ext, &top_iph->saddr, extlen); #else memcpy(tmp_ext, &top_iph->daddr, extlen); @@ -294,7 +294,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) memcpy(top_iph, tmp_base, sizeof(tmp_base)); if (tmp_ext) { -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) memcpy(&top_iph->saddr, tmp_ext, extlen); #else memcpy(&top_iph->daddr, tmp_ext, extlen); diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index b1fe7ac5dc90..ba1386dd4168 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -658,7 +658,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, switch (rthdr->type) { case IPV6_SRCRT_TYPE_0: -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: #endif break; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 14be0b9b77a5..173a4bb52255 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -42,7 +42,7 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #include #endif @@ -90,6 +90,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) bad: return -1; } +EXPORT_SYMBOL_GPL(ipv6_find_tlv); /* * Parsing tlv encoded headers. @@ -196,7 +197,7 @@ bad: Destination options header. *****************************/ -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) { struct sk_buff *skb = *skbp; @@ -270,7 +271,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) #endif static struct tlvtype_proc tlvprocdestopt_lst[] = { -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) { .type = IPV6_TLV_HAO, .func = ipv6_dest_hao, @@ -283,7 +284,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; struct inet6_skb_parm *opt = IP6CB(skb); -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) __u16 dstbuf; #endif struct dst_entry *dst; @@ -298,7 +299,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) } opt->lastopt = opt->dst1 = skb_network_header_len(skb); -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) dstbuf = opt->dst1; #endif @@ -308,7 +309,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) skb = *skbp; skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; opt = IP6CB(skb); -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) opt->nhoff = dstbuf; #else opt->nhoff = opt->dst1; @@ -427,7 +428,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) looped_back: if (hdr->segments_left == 0) { switch (hdr->type) { -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: /* Silently discard type 2 header unless it was * processed by own @@ -463,7 +464,7 @@ looped_back: return -1; } break; -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: /* Silently discard invalid RTH type 2 */ if (hdr->hdrlen != 2 || hdr->segments_left != 1) { @@ -520,7 +521,7 @@ looped_back: addr += i - 1; switch (hdr->type) { -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr, diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e9bcce9e7bdf..4765a29f98a8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -272,7 +272,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st return 0; } -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) static void mip6_addr_swap(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4704b5fc3085..31dafaf0b652 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -543,7 +543,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) found_rhdr = 1; break; case NEXTHDR_DEST: -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) break; #endif diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index aa3d07c52a8f..b636c38411fb 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -417,7 +417,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, struct ipv6_rt_hdr *rthdr = opt->srcrt; switch (rthdr->type) { case IPV6_SRCRT_TYPE_0: -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: #endif break; diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 13b7160fb892..20c78ecff6a1 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -86,7 +87,7 @@ static int mip6_mh_len(int type) return len; } -int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) +static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) { struct ip6_mh *mh; @@ -471,7 +472,7 @@ static struct xfrm_type mip6_rthdr_type = .remote_addr = mip6_xfrm_addr, }; -int __init mip6_init(void) +static int __init mip6_init(void) { printk(KERN_INFO "Mobile IPv6\n"); @@ -483,18 +484,33 @@ int __init mip6_init(void) printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); goto mip6_rthdr_xfrm_fail; } + if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { + printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__); + goto mip6_rawv6_mh_fail; + } + + return 0; + mip6_rawv6_mh_fail: + xfrm_unregister_type(&mip6_rthdr_type, AF_INET6); mip6_rthdr_xfrm_fail: xfrm_unregister_type(&mip6_destopt_type, AF_INET6); mip6_destopt_xfrm_fail: return -EAGAIN; } -void __exit mip6_fini(void) +static void __exit mip6_fini(void) { + if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) + printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__); if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); } + +module_init(mip6_init); +module_exit(mip6_fini); + +MODULE_LICENSE("GPL"); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a22c9c93d931..aac6aeb8de8c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -49,7 +49,7 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #include #endif @@ -137,6 +137,28 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) return 0; } +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) +static int (*mh_filter)(struct sock *sock, struct sk_buff *skb); + +int rawv6_mh_filter_register(int (*filter)(struct sock *sock, + struct sk_buff *skb)) +{ + rcu_assign_pointer(mh_filter, filter); + return 0; +} +EXPORT_SYMBOL(rawv6_mh_filter_register); + +int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, + struct sk_buff *skb)) +{ + rcu_assign_pointer(mh_filter, NULL); + synchronize_rcu(); + return 0; +} +EXPORT_SYMBOL(rawv6_mh_filter_unregister); + +#endif + /* * demultiplex raw sockets. * (should consider queueing the skb in the sock receive_queue @@ -178,16 +200,22 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) case IPPROTO_ICMPV6: filtered = icmpv6_filter(sk, skb); break; -#ifdef CONFIG_IPV6_MIP6 + +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPPROTO_MH: + { /* XXX: To validate MH only once for each packet, * this is placed here. It should be after checking * xfrm policy, however it doesn't. The checking xfrm * policy is placed in rawv6_rcv() because it is * required for each socket. */ - filtered = mip6_mh_filter(sk, skb); + int (*filter)(struct sock *sock, struct sk_buff *skb); + + filter = rcu_dereference(mh_filter); + filtered = filter ? filter(sk, skb) : 0; break; + } #endif default: filtered = 0; diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 1faa2ea80afc..3ec0c4770ee3 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -18,7 +18,7 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #include #endif @@ -318,7 +318,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) fl->proto = nexthdr; return; -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPPROTO_MH: if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { struct ip6_mh *mh; diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index baa461b9f74e..cdadb4847469 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -65,7 +65,7 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) goto end; /* Rule 2: select MIPv6 RO or inbound trigger */ -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) for (i = 0; i < n; i++) { if (src[i] && (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || @@ -130,7 +130,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) goto end; /* Rule 2: select MIPv6 RO or inbound trigger */ -#ifdef CONFIG_IPV6_MIP6 +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) for (i = 0; i < n; i++) { if (src[i] && (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || -- cgit v1.2.3 From d3d6dd3adaaad71eae20902ed81808a66a40a5b9 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Tue, 26 Jun 2007 23:57:49 -0700 Subject: [XFRM]: Add module alias for transformation type. It is clean-up for XFRM type modules and adds aliases with its protocol: ESP, AH, IPCOMP, IPIP and IPv6 for IPsec ROUTING and DSTOPTS for MIPv6 It is almost the same thing as XFRM mode alias, but it is added new defines XFRM_PROTO_XXX for preprocessing since some protocols are defined as enum. Signed-off-by: Masahide NAKAMURA Acked-by: Ingo Oeser Signed-off-by: David S. Miller --- include/net/xfrm.h | 10 ++++++++++ net/ipv4/ah4.c | 1 + net/ipv4/esp4.c | 1 + net/ipv4/ipcomp.c | 1 + net/ipv4/xfrm4_tunnel.c | 1 + net/ipv6/ah6.c | 1 + net/ipv6/esp6.c | 1 + net/ipv6/ipcomp6.c | 2 +- net/ipv6/mip6.c | 2 ++ net/ipv6/xfrm6_tunnel.c | 1 + 10 files changed, 20 insertions(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 7720c1182bb4..ee3827f053d7 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -19,9 +19,19 @@ #include #include +#define XFRM_PROTO_ESP 50 +#define XFRM_PROTO_AH 51 +#define XFRM_PROTO_COMP 108 +#define XFRM_PROTO_IPIP 4 +#define XFRM_PROTO_IPV6 41 +#define XFRM_PROTO_ROUTING IPPROTO_ROUTING +#define XFRM_PROTO_DSTOPTS IPPROTO_DSTOPTS + #define XFRM_ALIGN8(len) (((len) + 7) & ~7) #define MODULE_ALIAS_XFRM_MODE(family, encap) \ MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap)) +#define MODULE_ALIAS_XFRM_TYPE(family, proto) \ + MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto)) extern struct sock *xfrm_nl; extern u32 sysctl_xfrm_aevent_etime; diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 6da8ff597ad3..7a23e59c374a 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -339,3 +339,4 @@ static void __exit ah4_fini(void) module_init(ah4_init); module_exit(ah4_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 47c95e8ef045..98767a4f1185 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -481,3 +481,4 @@ static void __exit esp4_fini(void) module_init(esp4_init); module_exit(esp4_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP); diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index ab86137c71d2..e787044a8514 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -485,3 +485,4 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173"); MODULE_AUTHOR("James Morris "); +MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP); diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 568510304553..9275c79119b6 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -109,3 +109,4 @@ static void __exit ipip_fini(void) module_init(ipip_init); module_exit(ipip_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index cc6884a40be4..53f46ab6af70 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -554,3 +554,4 @@ module_init(ah6_init); module_exit(ah6_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 7107bb7e2e62..2db31ce3c7e6 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -421,3 +421,4 @@ module_init(esp6_init); module_exit(esp6_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 1ee50b5782e1..473f165310ea 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -500,4 +500,4 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173"); MODULE_AUTHOR("Mitsuru KANDA "); - +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP); diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 20c78ecff6a1..8a1399ce38ce 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -514,3 +514,5 @@ module_init(mip6_init); module_exit(mip6_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS); +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 5502cc948dfb..6f87dd568ded 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -379,3 +379,4 @@ static void __exit xfrm6_tunnel_fini(void) module_init(xfrm6_tunnel_init); module_exit(xfrm6_tunnel_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6); -- cgit v1.2.3 From 628529b6ee334fedc8d25ce56205bb99566572b9 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 2 Jul 2007 22:41:14 -0700 Subject: [XFRM] Introduce standalone SAD lookup This allows other in-kernel functions to do SAD lookups. The only known user at the moment is pktgen. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++++ net/xfrm/xfrm_state.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'include/net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ee3827f053d7..d3a898b18fb4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -928,6 +928,10 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); +extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr, + xfrm_address_t *saddr, + unsigned short family, + u8 mode, u8 proto, u32 reqid); extern int xfrm_state_check_expire(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_add(struct xfrm_state *x); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index dfacb9c2a6e3..e070c3f938fb 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -686,6 +686,37 @@ out: return x; } +struct xfrm_state * +xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, + unsigned short family, u8 mode, u8 proto, u32 reqid) +{ + unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); + struct xfrm_state *rx = NULL, *x = NULL; + struct hlist_node *entry; + + spin_lock(&xfrm_state_lock); + hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { + if (x->props.family == family && + x->props.reqid == reqid && + !(x->props.flags & XFRM_STATE_WILDRECV) && + xfrm_state_addr_check(x, daddr, saddr, family) && + mode == x->props.mode && + proto == x->id.proto && + x->km.state == XFRM_STATE_VALID) { + rx = x; + break; + } + } + + if (rx) + xfrm_state_hold(rx); + spin_unlock(&xfrm_state_lock); + + + return rx; +} +EXPORT_SYMBOL(xfrm_stateonly_find); + static void __xfrm_state_insert(struct xfrm_state *x) { unsigned int h; -- cgit v1.2.3 From 4bdf39911e7a887c4499161422423cbaf16684e8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 2 Jul 2007 22:47:37 -0700 Subject: [NET_SCHED]: Remove unnecessary stats_lock pointers Remove stats_lock pointers from qdisc-internal structures, in all cases it points to dev->queue_lock. The only case where it is necessary is for top-level qdiscs, where it might also point to dev->ingress_lock in case of the ingress qdisc. Also remove it from actions completely, it always points to the actions internal lock. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/act_api.h | 2 -- net/sched/act_api.c | 7 +++---- net/sched/act_police.c | 8 +++----- net/sched/sch_atm.c | 1 - net/sched/sch_cbq.c | 8 +++----- net/sched/sch_hfsc.c | 10 +++------- 6 files changed, 12 insertions(+), 24 deletions(-) (limited to 'include/net') diff --git a/include/net/act_api.h b/include/net/act_api.h index 8b06c2f3657f..2f0273feabd3 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -19,7 +19,6 @@ struct tcf_common { struct gnet_stats_basic tcfc_bstats; struct gnet_stats_queue tcfc_qstats; struct gnet_stats_rate_est tcfc_rate_est; - spinlock_t *tcfc_stats_lock; spinlock_t tcfc_lock; }; #define tcf_next common.tcfc_next @@ -32,7 +31,6 @@ struct tcf_common { #define tcf_bstats common.tcfc_bstats #define tcf_qstats common.tcfc_qstats #define tcf_rate_est common.tcfc_rate_est -#define tcf_stats_lock common.tcfc_stats_lock #define tcf_lock common.tcfc_lock struct tcf_police { diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 72bb9bd1a22a..32cc191d9f90 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -230,13 +230,12 @@ struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_acti p->tcfc_bindcnt = 1; spin_lock_init(&p->tcfc_lock); - p->tcfc_stats_lock = &p->tcfc_lock; p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); p->tcfc_tm.install = jiffies; p->tcfc_tm.lastuse = jiffies; if (est) gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, - p->tcfc_stats_lock, est); + &p->tcfc_lock, est); a->priv = (void *) p; return p; } @@ -595,12 +594,12 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, if (compat_mode) { if (a->type == TCA_OLD_COMPAT) err = gnet_stats_start_copy_compat(skb, 0, - TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d); + TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d); else return 0; } else err = gnet_stats_start_copy(skb, TCA_ACT_STATS, - h->tcf_stats_lock, &d); + &h->tcf_lock, &d); if (err < 0) goto errout; diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 580698db578a..3e8716dd738c 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -183,7 +183,6 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, ret = ACT_P_CREATED; police->tcf_refcnt = 1; spin_lock_init(&police->tcf_lock); - police->tcf_stats_lock = &police->tcf_lock; if (bind) police->tcf_bindcnt = 1; override: @@ -231,7 +230,7 @@ override: if (est) gen_replace_estimator(&police->tcf_bstats, &police->tcf_rate_est, - police->tcf_stats_lock, est); + &police->tcf_lock, est); spin_unlock_bh(&police->tcf_lock); if (ret != ACT_P_CREATED) @@ -450,7 +449,6 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) police->tcf_refcnt = 1; spin_lock_init(&police->tcf_lock); - police->tcf_stats_lock = &police->tcf_lock; if (parm->rate.rate) { police->tcfp_R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); @@ -490,7 +488,7 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) police->tcf_action = parm->action; if (est) gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, - police->tcf_stats_lock, est); + &police->tcf_lock, est); h = tcf_hash(police->tcf_index, POL_TAB_MASK); write_lock_bh(&police_lock); police->tcf_next = tcf_police_ht[h]; @@ -591,7 +589,7 @@ int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) struct gnet_dump d; if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, - TCA_XSTATS, police->tcf_stats_lock, + TCA_XSTATS, &police->tcf_lock, &d) < 0) goto errout; diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index d1c383fca82c..16fe802a66f7 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -71,7 +71,6 @@ struct atm_flow_data { int ref; /* reference count */ struct gnet_stats_basic bstats; struct gnet_stats_queue qstats; - spinlock_t *stats_lock; struct atm_flow_data *next; struct atm_flow_data *excess; /* flow for excess traffic; NULL to set CLP instead */ diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index bf1ea9e75cd9..b093d8fce789 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -148,7 +148,6 @@ struct cbq_class struct gnet_stats_basic bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; - spinlock_t *stats_lock; struct tc_cbq_xstats xstats; struct tcf_proto *filter_list; @@ -1442,7 +1441,6 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt) q->link.ewma_log = TC_CBQ_DEF_EWMA; q->link.avpkt = q->link.allot/2; q->link.minidle = -0x7FFFFFFF; - q->link.stats_lock = &sch->dev->queue_lock; qdisc_watchdog_init(&q->watchdog, sch); hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); @@ -1871,7 +1869,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t if (tca[TCA_RATE-1]) gen_replace_estimator(&cl->bstats, &cl->rate_est, - cl->stats_lock, tca[TCA_RATE-1]); + &sch->dev->queue_lock, + tca[TCA_RATE-1]); return 0; } @@ -1929,7 +1928,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t cl->allot = parent->allot; cl->quantum = cl->allot; cl->weight = cl->R_tab->rate.rate; - cl->stats_lock = &sch->dev->queue_lock; sch_tree_lock(sch); cbq_link_class(cl); @@ -1959,7 +1957,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t if (tca[TCA_RATE-1]) gen_new_estimator(&cl->bstats, &cl->rate_est, - cl->stats_lock, tca[TCA_RATE-1]); + &sch->dev->queue_lock, tca[TCA_RATE-1]); *arg = (unsigned long)cl; return 0; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 7ccdf63a0cb5..7130a2441b0d 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -122,7 +122,6 @@ struct hfsc_class struct gnet_stats_basic bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; - spinlock_t *stats_lock; unsigned int level; /* class level in hierarchy */ struct tcf_proto *filter_list; /* filter list */ unsigned int filter_cnt; /* filter count */ @@ -1056,7 +1055,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (tca[TCA_RATE-1]) gen_replace_estimator(&cl->bstats, &cl->rate_est, - cl->stats_lock, tca[TCA_RATE-1]); + &sch->dev->queue_lock, + tca[TCA_RATE-1]); return 0; } @@ -1096,7 +1096,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); if (cl->qdisc == NULL) cl->qdisc = &noop_qdisc; - cl->stats_lock = &sch->dev->queue_lock; INIT_LIST_HEAD(&cl->children); cl->vt_tree = RB_ROOT; cl->cf_tree = RB_ROOT; @@ -1112,7 +1111,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (tca[TCA_RATE-1]) gen_new_estimator(&cl->bstats, &cl->rate_est, - cl->stats_lock, tca[TCA_RATE-1]); + &sch->dev->queue_lock, tca[TCA_RATE-1]); *arg = (unsigned long)cl; return 0; } @@ -1440,8 +1439,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) return -EINVAL; qopt = RTA_DATA(opt); - sch->stats_lock = &sch->dev->queue_lock; - q->defcls = qopt->defcls; for (i = 0; i < HFSC_HSIZE; i++) INIT_LIST_HEAD(&q->clhash[i]); @@ -1456,7 +1453,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) sch->handle); if (q->root.qdisc == NULL) q->root.qdisc = &noop_qdisc; - q->root.stats_lock = &sch->dev->queue_lock; INIT_LIST_HEAD(&q->root.children); q->root.vt_tree = RB_ROOT; q->root.cf_tree = RB_ROOT; -- cgit v1.2.3 From 89da1ecf5483e6aa29b456a15ad6d05a6797c5a5 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 2 Jul 2007 22:54:18 -0700 Subject: [IrDA]: Netlink layer. First IrDA configuration netlink layer implementation. Currently, we only support the set/get mode commands. Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- include/linux/irda.h | 27 ++++++++ include/net/irda/irda.h | 3 + include/net/irda/irlap.h | 2 + net/irda/Makefile | 2 +- net/irda/irmod.c | 48 +++++++++++-- net/irda/irnetlink.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 net/irda/irnetlink.c (limited to 'include/net') diff --git a/include/linux/irda.h b/include/linux/irda.h index 945ba3110874..35911bd4dbe8 100644 --- a/include/linux/irda.h +++ b/include/linux/irda.h @@ -216,6 +216,33 @@ struct if_irda_req { #define ifr_dtr ifr_ifru.ifru_line.dtr #define ifr_rts ifr_ifru.ifru_line.rts + +/* IrDA netlink definitions */ +#define IRDA_NL_NAME "irda" +#define IRDA_NL_VERSION 1 + +enum irda_nl_commands { + IRDA_NL_CMD_UNSPEC, + IRDA_NL_CMD_SET_MODE, + IRDA_NL_CMD_GET_MODE, + + __IRDA_NL_CMD_AFTER_LAST +}; +#define IRDA_NL_CMD_MAX (__IRDA_NL_CMD_AFTER_LAST - 1) + +enum nl80211_attrs { + IRDA_NL_ATTR_UNSPEC, + IRDA_NL_ATTR_IFNAME, + IRDA_NL_ATTR_MODE, + + __IRDA_NL_ATTR_AFTER_LAST +}; +#define IRDA_NL_ATTR_MAX (__IRDA_NL_ATTR_AFTER_LAST - 1) + +/* IrDA modes */ +#define IRDA_MODE_PRIMARY 0x1 +#define IRDA_MODE_SECONDARY 0x2 + #endif /* KERNEL_IRDA_H */ diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index 36bee441aa56..08387553b57e 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -125,6 +125,9 @@ extern void irda_sysctl_unregister(void); extern int irsock_init(void); extern void irsock_cleanup(void); +extern int irda_nl_register(void); +extern void irda_nl_unregister(void); + extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev); diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index a3d370efb903..9d0c78ea92f5 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -208,6 +208,8 @@ struct irlap_cb { int xbofs_delay; /* Nr of XBOF's used to MTT */ int bofs_count; /* Negotiated extra BOFs */ int next_bofs; /* Negotiated extra BOFs after next frame */ + + int mode; /* IrLAP mode (primary, secondary or monitor) */ }; /* diff --git a/net/irda/Makefile b/net/irda/Makefile index d1366c2a39cb..187f6c563a4b 100644 --- a/net/irda/Makefile +++ b/net/irda/Makefile @@ -10,6 +10,6 @@ obj-$(CONFIG_IRCOMM) += ircomm/ irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \ - discovery.o parameters.o irmod.o + discovery.o parameters.o irnetlink.o irmod.o irda-$(CONFIG_PROC_FS) += irproc.o irda-$(CONFIG_SYSCTL) += irsysctl.o diff --git a/net/irda/irmod.c b/net/irda/irmod.c index c7fad2c5b9f3..1900937b3328 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -88,16 +88,23 @@ EXPORT_SYMBOL(irda_notify_init); */ static int __init irda_init(void) { + int ret = 0; + IRDA_DEBUG(0, "%s()\n", __FUNCTION__); /* Lower layer of the stack */ irlmp_init(); irlap_init(); + /* Driver/dongle support */ + irda_device_init(); + /* Higher layers of the stack */ iriap_init(); irttp_init(); - irsock_init(); + ret = irsock_init(); + if (ret < 0) + goto out_err_1; /* Add IrDA packet type (Start receiving packets) */ dev_add_pack(&irda_packet_type); @@ -107,13 +114,44 @@ static int __init irda_init(void) irda_proc_register(); #endif #ifdef CONFIG_SYSCTL - irda_sysctl_register(); + ret = irda_sysctl_register(); + if (ret < 0) + goto out_err_2; #endif - /* Driver/dongle support */ - irda_device_init(); + ret = irda_nl_register(); + if (ret < 0) + goto out_err_3; return 0; + + out_err_3: +#ifdef CONFIG_SYSCTL + irda_sysctl_unregister(); +#endif + out_err_2: +#ifdef CONFIG_PROC_FS + irda_proc_unregister(); +#endif + + /* Remove IrDA packet type (stop receiving packets) */ + dev_remove_pack(&irda_packet_type); + + /* Remove higher layers */ + irsock_cleanup(); + out_err_1: + irttp_cleanup(); + iriap_cleanup(); + + /* Remove lower layers */ + irda_device_cleanup(); + irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */ + + /* Remove middle layer */ + irlmp_cleanup(); + + + return ret; } /* @@ -125,6 +163,8 @@ static int __init irda_init(void) static void __exit irda_cleanup(void) { /* Remove External APIs */ + irda_nl_unregister(); + #ifdef CONFIG_SYSCTL irda_sysctl_unregister(); #endif diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c new file mode 100644 index 000000000000..db716580e1ae --- /dev/null +++ b/net/irda/irnetlink.c @@ -0,0 +1,170 @@ +/* + * IrDA netlink layer, for stack configuration. + * + * Copyright (c) 2007 Samuel Ortiz + * + * Partly based on the 802.11 nelink implementation + * (see net/wireless/nl80211.c) which is: + * Copyright 2006 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include + + + +static struct genl_family irda_nl_family = { + .id = GENL_ID_GENERATE, + .name = IRDA_NL_NAME, + .hdrsize = 0, + .version = IRDA_NL_VERSION, + .maxattr = IRDA_NL_CMD_MAX, +}; + +static struct net_device * ifname_to_netdev(struct genl_info *info) +{ + char * ifname; + + if (!info->attrs[IRDA_NL_ATTR_IFNAME]) + return NULL; + + ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]); + + IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname); + + return dev_get_by_name(ifname); +} + +static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device * dev; + struct irlap_cb * irlap; + u32 mode; + + if (!info->attrs[IRDA_NL_ATTR_MODE]) + return -EINVAL; + + mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]); + + IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode); + + dev = ifname_to_netdev(info); + if (!dev) + return -ENODEV; + + irlap = (struct irlap_cb *)dev->atalk_ptr; + if (!irlap) { + dev_put(dev); + return -ENODEV; + } + + irlap->mode = mode; + + dev_put(dev); + + return 0; +} + +static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device * dev; + struct irlap_cb * irlap; + struct sk_buff *msg; + void *hdr; + int ret = -ENOBUFS; + + dev = ifname_to_netdev(info); + if (!dev) + return -ENODEV; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) { + dev_put(dev); + return -ENOMEM; + } + + irlap = (struct irlap_cb *)dev->atalk_ptr; + if (!irlap) { + ret = -ENODEV; + goto err_out; + } + + hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, + &irda_nl_family, 0, IRDA_NL_CMD_GET_MODE); + if (IS_ERR(hdr)) { + ret = PTR_ERR(hdr); + goto err_out; + } + + if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME, + dev->name)); + goto err_out; + + if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode)) + goto err_out; + + genlmsg_end(msg, hdr); + + return genlmsg_unicast(msg, info->snd_pid); + + err_out: + nlmsg_free(msg); + dev_put(dev); + + return ret; +} + +static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = { + [IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, + .len = IFNAMSIZ-1 }, + [IRDA_NL_ATTR_MODE] = { .type = NLA_U32 }, +}; + +static struct genl_ops irda_nl_ops[] = { + { + .cmd = IRDA_NL_CMD_SET_MODE, + .doit = irda_nl_set_mode, + .policy = irda_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = IRDA_NL_CMD_GET_MODE, + .doit = irda_nl_get_mode, + .policy = irda_nl_policy, + /* can be retrieved by unprivileged users */ + }, + +}; + +int irda_nl_register(void) +{ + int err, i; + + err = genl_register_family(&irda_nl_family); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) { + err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]); + if (err) + goto err_out; + } + return 0; + err_out: + genl_unregister_family(&irda_nl_family); + return err; +} + +void irda_nl_unregister(void) +{ + genl_unregister_family(&irda_nl_family); +} -- cgit v1.2.3 From 067b207b281db5e3f03f8d244286c20f61aa2343 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Thu, 5 Jul 2007 17:08:05 -0700 Subject: [UDP]: Cleanup UDP encapsulation code This cleanup fell out after adding L2TP support where a new encap_rcv funcptr was added to struct udp_sock. Have XFRM use the new encap_rcv funcptr, which allows us to move the XFRM encap code from udp.c into xfrm4_input.c. Make xfrm4_rcv_encap() static since it is no longer called externally. Signed-off-by: James Chapman Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/xfrm.h | 5 +- net/ipv4/udp.c | 156 ++++++++----------------------------------------- net/ipv4/xfrm4_input.c | 114 +++++++++++++++++++++++++++++++++--- 3 files changed, 133 insertions(+), 142 deletions(-) (limited to 'include/net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d3a898b18fb4..ae959e950174 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1003,7 +1003,7 @@ extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, u8 **prevhdr); #ifdef CONFIG_XFRM -extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); +extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen); extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); #else @@ -1012,12 +1012,13 @@ static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optv return -ENOPROTOOPT; } -static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) +static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) { /* should not happen */ kfree_skb(skb); return 0; } + static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family) { return -EINVAL; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b9276f8bdac5..4ec4a25a8d0c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -920,108 +920,6 @@ int udp_disconnect(struct sock *sk, int flags) return 0; } -/* return: - * 1 if the UDP system should process it - * 0 if we should drop this packet - * -1 if it should get processed by xfrm4_rcv_encap - * -2 if it should get processed by l2tp - */ -static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) -{ - struct udp_sock *up = udp_sk(sk); - struct udphdr *uh; - struct iphdr *iph; - int iphlen, len; - - __u8 *udpdata; - __be32 *udpdata32; - __u16 encap_type = up->encap_type; - - /* if we're overly short, let UDP handle it */ - len = skb->len - sizeof(struct udphdr); - if (len <= 0) - return 1; - - /* if this is not encapsulated socket, then just return now */ - if (!encap_type) - return 1; - - /* If this is a paged skb, make sure we pull up - * whatever data we need to look at. */ - if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) - return 1; - - /* Now we can get the pointers */ - uh = udp_hdr(skb); - udpdata = (__u8 *)uh + sizeof(struct udphdr); - udpdata32 = (__be32 *)udpdata; - - switch (encap_type) { - default: - case UDP_ENCAP_ESPINUDP: - /* Check if this is a keepalive packet. If so, eat it. */ - if (len == 1 && udpdata[0] == 0xff) { - return 0; - } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { - /* ESP Packet without Non-ESP header */ - len = sizeof(struct udphdr); - } else - /* Must be an IKE packet.. pass it through */ - return 1; - break; - case UDP_ENCAP_ESPINUDP_NON_IKE: - /* Check if this is a keepalive packet. If so, eat it. */ - if (len == 1 && udpdata[0] == 0xff) { - return 0; - } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && - udpdata32[0] == 0 && udpdata32[1] == 0) { - - /* ESP Packet with Non-IKE marker */ - len = sizeof(struct udphdr) + 2 * sizeof(u32); - } else - /* Must be an IKE packet.. pass it through */ - return 1; - break; - case UDP_ENCAP_L2TPINUDP: - /* Let caller know to send this to l2tp */ - return -2; - } - -#ifndef CONFIG_XFRM - return 1; -#else - /* At this point we are sure that this is an ESPinUDP packet, - * so we need to remove 'len' bytes from the packet (the UDP - * header and optional ESP marker bytes) and then modify the - * protocol to ESP, and then call into the transform receiver. - */ - if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - return 0; - - /* Now we can update and verify the packet length... */ - iph = ip_hdr(skb); - iphlen = iph->ihl << 2; - iph->tot_len = htons(ntohs(iph->tot_len) - len); - if (skb->len < iphlen + len) { - /* packet is too small!?! */ - return 0; - } - - /* pull the data buffer up to the ESP header and set the - * transport header to point to ESP. Keep UDP on the stack - * for later. - */ - __skb_pull(skb, len); - skb_reset_transport_header(skb); - - /* modify the protocol (it's ESP!) */ - iph->protocol = IPPROTO_ESP; - - /* and let the caller know to send this into the ESP processor... */ - return -1; -#endif -} - /* returns: * -1: error * 0: success @@ -1044,44 +942,36 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) if (up->encap_type) { /* - * This is an encapsulation socket, so let's see if this is - * an encapsulated packet. - * If it's a keepalive packet, then just eat it. - * If it's an encapsulateed packet, then pass it to the - * IPsec xfrm input and return the response - * appropriately. Otherwise, just fall through and - * pass this up the UDP socket. + * This is an encapsulation socket so pass the skb to + * the socket's udp_encap_rcv() hook. Otherwise, just + * fall through and pass this up the UDP socket. + * up->encap_rcv() returns the following value: + * =0 if skb was successfully passed to the encap + * handler or was discarded by it. + * >0 if skb should be passed on to UDP. + * <0 if skb should be resubmitted as proto -N */ - int ret; + unsigned int len; - ret = udp_encap_rcv(sk, skb); - if (ret == 0) { - /* Eat the packet .. */ - kfree_skb(skb); - return 0; - } - if (ret == -1) { - /* process the ESP packet */ - ret = xfrm4_rcv_encap(skb, up->encap_type); - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); - return -ret; - } - if (ret == -2) { - /* process the L2TP packet */ - if (up->encap_rcv != NULL) { - ret = (*up->encap_rcv)(sk, skb); - if (ret <= 0) { - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); - return ret; - } - - /* FALLTHROUGH -- pass up as UDP packet */ + /* if we're overly short, let UDP handle it */ + len = skb->len - sizeof(struct udphdr); + if (len <= 0) + goto udp; + + if (up->encap_rcv != NULL) { + int ret; + + ret = (*up->encap_rcv)(sk, skb); + if (ret <= 0) { + UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); + return -ret; } } /* FALLTHROUGH -- it's a UDP Packet */ } +udp: /* * UDP-Lite specific tests, ignored on UDP sockets */ @@ -1367,6 +1257,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, case 0: case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP_NON_IKE: + up->encap_rcv = xfrm4_udp_encap_rcv; + /* FALLTHROUGH */ case UDP_ENCAP_L2TPINUDP: up->encap_type = val; break; diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index fa1902dc81b8..2fa108245413 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -16,13 +16,6 @@ #include #include -int xfrm4_rcv(struct sk_buff *skb) -{ - return xfrm4_rcv_encap(skb, 0); -} - -EXPORT_SYMBOL(xfrm4_rcv); - static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) { switch (nexthdr) { @@ -53,7 +46,7 @@ drop: } #endif -int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) +static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) { __be32 spi, seq; struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; @@ -167,3 +160,108 @@ drop: kfree_skb(skb); return 0; } + +/* If it's a keepalive packet, then just eat it. + * If it's an encapsulated packet, then pass it to the + * IPsec xfrm input. + * Returns 0 if skb passed to xfrm or was dropped. + * Returns >0 if skb should be passed to UDP. + * Returns <0 if skb should be resubmitted (-ret is protocol) + */ +int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) +{ + struct udp_sock *up = udp_sk(sk); + struct udphdr *uh; + struct iphdr *iph; + int iphlen, len; + int ret; + + __u8 *udpdata; + __be32 *udpdata32; + __u16 encap_type = up->encap_type; + + /* if this is not encapsulated socket, then just return now */ + if (!encap_type) + return 1; + + /* If this is a paged skb, make sure we pull up + * whatever data we need to look at. */ + len = skb->len - sizeof(struct udphdr); + if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) + return 1; + + /* Now we can get the pointers */ + uh = udp_hdr(skb); + udpdata = (__u8 *)uh + sizeof(struct udphdr); + udpdata32 = (__be32 *)udpdata; + + switch (encap_type) { + default: + case UDP_ENCAP_ESPINUDP: + /* Check if this is a keepalive packet. If so, eat it. */ + if (len == 1 && udpdata[0] == 0xff) { + goto drop; + } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { + /* ESP Packet without Non-ESP header */ + len = sizeof(struct udphdr); + } else + /* Must be an IKE packet.. pass it through */ + return 1; + break; + case UDP_ENCAP_ESPINUDP_NON_IKE: + /* Check if this is a keepalive packet. If so, eat it. */ + if (len == 1 && udpdata[0] == 0xff) { + goto drop; + } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && + udpdata32[0] == 0 && udpdata32[1] == 0) { + + /* ESP Packet with Non-IKE marker */ + len = sizeof(struct udphdr) + 2 * sizeof(u32); + } else + /* Must be an IKE packet.. pass it through */ + return 1; + break; + } + + /* At this point we are sure that this is an ESPinUDP packet, + * so we need to remove 'len' bytes from the packet (the UDP + * header and optional ESP marker bytes) and then modify the + * protocol to ESP, and then call into the transform receiver. + */ + if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; + + /* Now we can update and verify the packet length... */ + iph = ip_hdr(skb); + iphlen = iph->ihl << 2; + iph->tot_len = htons(ntohs(iph->tot_len) - len); + if (skb->len < iphlen + len) { + /* packet is too small!?! */ + goto drop; + } + + /* pull the data buffer up to the ESP header and set the + * transport header to point to ESP. Keep UDP on the stack + * for later. + */ + __skb_pull(skb, len); + skb_reset_transport_header(skb); + + /* modify the protocol (it's ESP!) */ + iph->protocol = IPPROTO_ESP; + + /* process ESP */ + ret = xfrm4_rcv_encap(skb, encap_type); + return ret; + +drop: + kfree_skb(skb); + return 0; +} + +int xfrm4_rcv(struct sk_buff *skb) +{ + return xfrm4_rcv_encap(skb, 0); +} + +EXPORT_SYMBOL(xfrm4_rcv); -- cgit v1.2.3 From 4ba887790ce2015e8c464809c0be902fb813ad15 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:22:33 -0700 Subject: [NETFILTER]: nf_nat: move NAT declarations from nf_conntrack_ipv4.h to nf_nat.h Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 23 +---------------------- include/net/netfilter/nf_conntrack.h | 1 + include/net/netfilter/nf_nat.h | 18 ++++++++++++++++++ include/net/netfilter/nf_nat_core.h | 1 + 4 files changed, 21 insertions(+), 22 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 1401ccc051c4..3ed4e14970c5 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -9,29 +9,8 @@ #ifndef _NF_CONNTRACK_IPV4_H #define _NF_CONNTRACK_IPV4_H -#ifdef CONFIG_NF_NAT_NEEDED -#include -#include - -/* per conntrack: nat application helper private data */ -union nf_conntrack_nat_help { - /* insert nat helper private data here */ - struct nf_nat_pptp nat_pptp_info; -}; - -struct nf_conn_nat { - struct nf_nat_info info; - union nf_conntrack_nat_help help; -#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ - defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) - int masq_index; -#endif -}; -#endif /* CONFIG_NF_NAT_NEEDED */ - /* Returns new sk_buff, or NULL */ -struct sk_buff * -nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); +struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 4732432f8eb0..12a0e793cc0b 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -280,6 +280,7 @@ nf_conntrack_unregister_cache(u_int32_t features); * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help */ #ifdef CONFIG_NF_NAT_NEEDED +#include static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) { unsigned int offset = sizeof(struct nf_conn); diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index bc57dd7b9b5c..47d3dc107a6a 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -51,6 +51,7 @@ struct nf_nat_multi_range_compat #ifdef __KERNEL__ #include +#include /* The structure embedded in the conntrack structure. */ struct nf_nat_info @@ -59,6 +60,23 @@ struct nf_nat_info struct nf_nat_seq seq[IP_CT_DIR_MAX]; }; +/* per conntrack: nat application helper private data */ +union nf_conntrack_nat_help +{ + /* insert nat helper private data here */ + struct nf_nat_pptp nat_pptp_info; +}; + +struct nf_conn_nat +{ + struct nf_nat_info info; + union nf_conntrack_nat_help help; +#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ + defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) + int masq_index; +#endif +}; + struct nf_conn; /* Set up the info structure to map into this range. */ diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index 9778ffa93440..c3cd127ba4bb 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -2,6 +2,7 @@ #define _NF_NAT_CORE_H #include #include +#include /* This header used to share core functionality between the standalone NAT module, and the compatibility layer's use of NAT for masquerading. */ -- cgit v1.2.3 From ecfab2c9fe5597221c2b30dec48634a2361a0d08 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:23:21 -0700 Subject: [NETFILTER]: nf_conntrack: introduce extension infrastructure Old space allocator of conntrack had problems about extensibility. - It required slab cache per combination of extensions. - It expected what extensions would be assigned, but it was impossible to expect that completely, then we allocated bigger memory object than really required. - It needed to search helper twice due to lock issue. Now basic informations of a connection are stored in 'struct nf_conn'. And a storage for extension (helper, NAT) is allocated by kmalloc. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 3 + include/net/netfilter/nf_conntrack_extend.h | 80 ++++++++++++ net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_core.c | 4 + net/netfilter/nf_conntrack_extend.c | 195 ++++++++++++++++++++++++++++ 5 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 include/net/netfilter/nf_conntrack_extend.h create mode 100644 net/netfilter/nf_conntrack_extend.c (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 12a0e793cc0b..c31382d3ef11 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -131,6 +131,9 @@ struct nf_conn /* Storage reserved for other modules: */ union nf_conntrack_proto proto; + /* Extensions */ + struct nf_ct_ext *ext; + /* features dynamically at the end: helper, nat (both optional) */ char data[0]; }; diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h new file mode 100644 index 000000000000..8a988d136465 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -0,0 +1,80 @@ +#ifndef _NF_CONNTRACK_EXTEND_H +#define _NF_CONNTRACK_EXTEND_H + +#include + +enum nf_ct_ext_id +{ + NF_CT_EXT_NUM, +}; + +/* Extensions: optional stuff which isn't permanently in struct. */ +struct nf_ct_ext { + u8 offset[NF_CT_EXT_NUM]; + u8 len; + u8 real_len; + char data[0]; +}; + +static inline int nf_ct_ext_exist(const struct nf_conn *ct, u8 id) +{ + return (ct->ext && ct->ext->offset[id]); +} + +static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id) +{ + if (!nf_ct_ext_exist(ct, id)) + return NULL; + + return (void *)ct->ext + ct->ext->offset[id]; +} +#define nf_ct_ext_find(ext, id) \ + ((id##_TYPE *)__nf_ct_ext_find((ext), (id))) + +/* Destroy all relationships */ +extern void __nf_ct_ext_destroy(struct nf_conn *ct); +static inline void nf_ct_ext_destroy(struct nf_conn *ct) +{ + if (ct->ext) + __nf_ct_ext_destroy(ct); +} + +/* Free operation. If you want to free a object referred from private area, + * please implement __nf_ct_ext_free() and call it. + */ +static inline void nf_ct_ext_free(struct nf_conn *ct) +{ + if (ct->ext) + kfree(ct->ext); +} + +/* Add this type, returns pointer to data or NULL. */ +void * +__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp); +#define nf_ct_ext_add(ct, id, gfp) \ + ((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp))) + +#define NF_CT_EXT_F_PREALLOC 0x0001 + +struct nf_ct_ext_type +{ + /* Destroys relationships (can be NULL). */ + void (*destroy)(struct nf_conn *ct); + /* Called when realloacted (can be NULL). + Contents has already been moved. */ + void (*move)(struct nf_conn *ct, void *old); + + enum nf_ct_ext_id id; + + unsigned int flags; + + /* Length and min alignment. */ + u8 len; + u8 align; + /* initial size of nf_ct_ext. */ + u8 alloc_size; +}; + +int nf_ct_extend_register(struct nf_ct_ext_type *type); +void nf_ct_extend_unregister(struct nf_ct_ext_type *type); +#endif /* _NF_CONNTRACK_EXTEND_H */ diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 3b792687f001..58b4245a1723 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,6 +1,6 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o -nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o +nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o obj-$(CONFIG_NETFILTER) = netfilter.o diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7a15e30356f2..b56f954895bb 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -36,6 +36,7 @@ #include #include #include +#include #define NF_CONNTRACK_VERSION "0.5.0" @@ -317,6 +318,8 @@ destroy_conntrack(struct nf_conntrack *nfct) if (l4proto && l4proto->destroy) l4proto->destroy(ct); + nf_ct_ext_destroy(ct); + destroyed = rcu_dereference(nf_conntrack_destroyed); if (destroyed) destroyed(ct); @@ -650,6 +653,7 @@ void nf_conntrack_free(struct nf_conn *conntrack) { u_int32_t features = conntrack->features; NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM); + nf_ct_ext_free(conntrack); DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features, conntrack); kmem_cache_free(nf_ct_cache[features].cachep, conntrack); diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c new file mode 100644 index 000000000000..a1a65a1313b3 --- /dev/null +++ b/net/netfilter/nf_conntrack_extend.c @@ -0,0 +1,195 @@ +/* Structure dynamic extension infrastructure + * Copyright (C) 2004 Rusty Russell IBM Corporation + * Copyright (C) 2007 Netfilter Core Team + * Copyright (C) 2007 USAGI/WIDE Project + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include + +static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM]; +static DEFINE_MUTEX(nf_ct_ext_type_mutex); + +/* Horrible trick to figure out smallest amount worth kmallocing. */ +#define CACHE(x) (x) + 0 * +enum { + NF_CT_EXT_MIN_SIZE = +#include + 1 }; +#undef CACHE + +void __nf_ct_ext_destroy(struct nf_conn *ct) +{ + unsigned int i; + struct nf_ct_ext_type *t; + + for (i = 0; i < NF_CT_EXT_NUM; i++) { + if (!nf_ct_ext_exist(ct, i)) + continue; + + rcu_read_lock(); + t = rcu_dereference(nf_ct_ext_types[i]); + + /* Here the nf_ct_ext_type might have been unregisterd. + * I.e., it has responsible to cleanup private + * area in all conntracks when it is unregisterd. + */ + if (t && t->destroy) + t->destroy(ct); + rcu_read_unlock(); + } +} +EXPORT_SYMBOL(__nf_ct_ext_destroy); + +static void * +nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) +{ + unsigned int off, len, real_len; + struct nf_ct_ext_type *t; + + rcu_read_lock(); + t = rcu_dereference(nf_ct_ext_types[id]); + BUG_ON(t == NULL); + off = ALIGN(sizeof(struct nf_ct_ext), t->align); + len = off + t->len; + real_len = t->alloc_size; + rcu_read_unlock(); + + *ext = kzalloc(real_len, gfp); + if (!*ext) + return NULL; + + (*ext)->offset[id] = off; + (*ext)->len = len; + (*ext)->real_len = real_len; + + return (void *)(*ext) + off; +} + +void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) +{ + struct nf_ct_ext *new; + int i, newlen, newoff; + struct nf_ct_ext_type *t; + + if (!ct->ext) + return nf_ct_ext_create(&ct->ext, id, gfp); + + if (nf_ct_ext_exist(ct, id)) + return NULL; + + rcu_read_lock(); + t = rcu_dereference(nf_ct_ext_types[id]); + BUG_ON(t == NULL); + + newoff = ALIGN(ct->ext->len, t->align); + newlen = newoff + t->len; + rcu_read_unlock(); + + if (newlen >= ct->ext->real_len) { + new = kmalloc(newlen, gfp); + if (!new) + return NULL; + + memcpy(new, ct->ext, ct->ext->len); + + for (i = 0; i < NF_CT_EXT_NUM; i++) { + if (!nf_ct_ext_exist(ct, i)) + continue; + + rcu_read_lock(); + t = rcu_dereference(nf_ct_ext_types[i]); + if (t && t->move) + t->move(ct, ct->ext + ct->ext->offset[id]); + rcu_read_unlock(); + } + kfree(ct->ext); + new->real_len = newlen; + ct->ext = new; + } + + ct->ext->offset[id] = newoff; + ct->ext->len = newlen; + memset((void *)ct->ext + newoff, 0, newlen - newoff); + return (void *)ct->ext + newoff; +} +EXPORT_SYMBOL(__nf_ct_ext_add); + +static void update_alloc_size(struct nf_ct_ext_type *type) +{ + int i, j; + struct nf_ct_ext_type *t1, *t2; + enum nf_ct_ext_id min = 0, max = NF_CT_EXT_NUM - 1; + + /* unnecessary to update all types */ + if ((type->flags & NF_CT_EXT_F_PREALLOC) == 0) { + min = type->id; + max = type->id; + } + + /* This assumes that extended areas in conntrack for the types + whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */ + for (i = min; i <= max; i++) { + t1 = nf_ct_ext_types[i]; + if (!t1) + continue; + + t1->alloc_size = sizeof(struct nf_ct_ext) + + ALIGN(sizeof(struct nf_ct_ext), t1->align) + + t1->len; + for (j = 0; j < NF_CT_EXT_NUM; j++) { + t2 = nf_ct_ext_types[j]; + if (t2 == NULL || t2 == t1 || + (t2->flags & NF_CT_EXT_F_PREALLOC) == 0) + continue; + + t1->alloc_size = ALIGN(t1->alloc_size, t2->align) + + t2->len; + } + if (t1->alloc_size < NF_CT_EXT_MIN_SIZE) + t1->alloc_size = NF_CT_EXT_MIN_SIZE; + } +} + +/* This MUST be called in process context. */ +int nf_ct_extend_register(struct nf_ct_ext_type *type) +{ + int ret = 0; + + mutex_lock(&nf_ct_ext_type_mutex); + if (nf_ct_ext_types[type->id]) { + ret = -EBUSY; + goto out; + } + + /* This ensures that nf_ct_ext_create() can allocate enough area + before updating alloc_size */ + type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) + + type->len; + rcu_assign_pointer(nf_ct_ext_types[type->id], type); + update_alloc_size(type); +out: + mutex_unlock(&nf_ct_ext_type_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(nf_ct_extend_register); + +/* This MUST be called in process context. */ +void nf_ct_extend_unregister(struct nf_ct_ext_type *type) +{ + mutex_lock(&nf_ct_ext_type_mutex); + rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); + update_alloc_size(type); + mutex_unlock(&nf_ct_ext_type_mutex); + synchronize_rcu(); +} +EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); -- cgit v1.2.3 From ceceae1b1555a9afcb8dacf90df5fa1f20fd5466 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:23:42 -0700 Subject: [NETFILTER]: nf_conntrack: use extension infrastructure for helper Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 26 ---------- include/net/netfilter/nf_conntrack_core.h | 3 ++ include/net/netfilter/nf_conntrack_extend.h | 3 ++ include/net/netfilter/nf_conntrack_helper.h | 5 ++ net/ipv4/netfilter/nf_nat_standalone.c | 10 ---- net/netfilter/nf_conntrack_core.c | 80 ++++++++++++++++++----------- net/netfilter/nf_conntrack_helper.c | 27 ++++++---- net/netfilter/nf_conntrack_netlink.c | 37 +++++++------ 8 files changed, 99 insertions(+), 92 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index c31382d3ef11..f1e0fee9aa9c 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -294,32 +294,6 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) offset = ALIGN(offset, __alignof__(struct nf_conn_nat)); return (struct nf_conn_nat *) ((void *)ct + offset); } - -static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) -{ - unsigned int offset = sizeof(struct nf_conn); - - if (!(ct->features & NF_CT_F_HELP)) - return NULL; - if (ct->features & NF_CT_F_NAT) { - offset = ALIGN(offset, __alignof__(struct nf_conn_nat)); - offset += sizeof(struct nf_conn_nat); - } - - offset = ALIGN(offset, __alignof__(struct nf_conn_help)); - return (struct nf_conn_help *) ((void *)ct + offset); -} -#else /* No NAT */ -static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) -{ - unsigned int offset = sizeof(struct nf_conn); - - if (!(ct->features & NF_CT_F_HELP)) - return NULL; - - offset = ALIGN(offset, __alignof__(struct nf_conn_help)); - return (struct nf_conn_help *) ((void *)ct + offset); -} #endif /* CONFIG_NF_NAT_NEEDED */ #endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_H */ diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 9fb906688ffa..3bf7d05ea64d 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -30,6 +30,9 @@ extern void nf_conntrack_cleanup(void); extern int nf_conntrack_proto_init(void); extern void nf_conntrack_proto_fini(void); +extern int nf_conntrack_helper_init(void); +extern void nf_conntrack_helper_fini(void); + struct nf_conntrack_l3proto; extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf); /* Like above, but you already have conntrack read lock. */ diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 8a988d136465..05357dc5d2d2 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -5,9 +5,12 @@ enum nf_ct_ext_id { + NF_CT_EXT_HELPER, NF_CT_EXT_NUM, }; +#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help + /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { u8 offset[NF_CT_EXT_NUM]; diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 8c72ac9f0ab8..b43a75ba44ac 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -10,6 +10,7 @@ #ifndef _NF_CONNTRACK_HELPER_H #define _NF_CONNTRACK_HELPER_H #include +#include struct module; @@ -52,4 +53,8 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); +static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) +{ + return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); +} #endif /*_NF_CONNTRACK_HELPER_H*/ diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 55dac36dbc85..0b2f0c33f7cd 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -338,14 +338,6 @@ static int __init nf_nat_standalone_init(void) return ret; } - size = ALIGN(size, __alignof__(struct nf_conn_help)) + - sizeof(struct nf_conn_help); - ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP, - "nf_nat:help", size); - if (ret < 0) { - printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n"); - goto cleanup_register_cache; - } #ifdef CONFIG_XFRM BUG_ON(ip_nat_decode_session != NULL); ip_nat_decode_session = nat_decode_session; @@ -370,8 +362,6 @@ static int __init nf_nat_standalone_init(void) ip_nat_decode_session = NULL; synchronize_net(); #endif - nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP); - cleanup_register_cache: nf_conntrack_unregister_cache(NF_CT_F_NAT); return ret; } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b56f954895bb..914506e6c787 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -566,7 +566,6 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, u_int32_t features) { struct nf_conn *conntrack = NULL; - struct nf_conntrack_helper *helper; if (unlikely(!nf_conntrack_hash_rnd_initted)) { get_random_bytes(&nf_conntrack_hash_rnd, 4); @@ -593,14 +592,6 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, /* find features needed by this conntrack. */ features |= l3proto->get_features(orig); - /* FIXME: protect helper list per RCU */ - read_lock_bh(&nf_conntrack_lock); - helper = __nf_ct_helper_find(repl); - /* NAT might want to assign a helper later */ - if (helper || features & NF_CT_F_NAT) - features |= NF_CT_F_HELP; - read_unlock_bh(&nf_conntrack_lock); - DEBUGP("nf_conntrack_alloc: features=0x%x\n", features); read_lock_bh(&nf_ct_cache_lock); @@ -681,12 +672,6 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, return NULL; } - read_lock_bh(&nf_conntrack_lock); - exp = __nf_conntrack_expect_find(tuple); - if (exp && exp->helper) - features = NF_CT_F_HELP; - read_unlock_bh(&nf_conntrack_lock); - conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features); if (conntrack == NULL || IS_ERR(conntrack)) { DEBUGP("Can't allocate conntrack.\n"); @@ -701,16 +686,21 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, write_lock_bh(&nf_conntrack_lock); exp = find_expectation(tuple); - - help = nfct_help(conntrack); if (exp) { DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", conntrack, exp); /* Welcome, Mr. Bond. We've been expecting you... */ __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = exp->master; - if (exp->helper) - rcu_assign_pointer(help->helper, exp->helper); + if (exp->helper) { + help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, + GFP_ATOMIC); + if (help) + rcu_assign_pointer(help->helper, exp->helper); + else + DEBUGP("failed to add helper extension area"); + } + #ifdef CONFIG_NF_CONNTRACK_MARK conntrack->mark = exp->master->mark; #endif @@ -720,10 +710,18 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, nf_conntrack_get(&conntrack->master->ct_general); NF_CT_STAT_INC(expect_new); } else { - if (help) { - /* not in hash table yet, so not strictly necessary */ - rcu_assign_pointer(help->helper, - __nf_ct_helper_find(&repl_tuple)); + struct nf_conntrack_helper *helper; + + helper = __nf_ct_helper_find(&repl_tuple); + if (helper) { + help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, + GFP_ATOMIC); + if (help) + /* not in hash table yet, so not strictly + necessary */ + rcu_assign_pointer(help->helper, helper); + else + DEBUGP("failed to add helper extension area"); } NF_CT_STAT_INC(new); } @@ -892,6 +890,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, const struct nf_conntrack_tuple *newreply) { struct nf_conn_help *help = nfct_help(ct); + struct nf_conntrack_helper *helper; write_lock_bh(&nf_conntrack_lock); /* Should be unconfirmed, so not in hash table yet */ @@ -901,14 +900,28 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, NF_CT_DUMP_TUPLE(newreply); ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; - if (!ct->master && help && help->expecting == 0) { - struct nf_conntrack_helper *helper; - helper = __nf_ct_helper_find(newreply); - if (helper) - memset(&help->help, 0, sizeof(help->help)); - /* not in hash table yet, so not strictly necessary */ - rcu_assign_pointer(help->helper, helper); + if (ct->master || (help && help->expecting != 0)) + goto out; + + helper = __nf_ct_helper_find(newreply); + if (helper == NULL) { + if (help) + rcu_assign_pointer(help->helper, NULL); + goto out; } + + if (help == NULL) { + help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_ATOMIC); + if (help == NULL) { + DEBUGP("failed to add helper extension area"); + goto out; + } + } else { + memset(&help->help, 0, sizeof(help->help)); + } + + rcu_assign_pointer(help->helper, helper); +out: write_unlock_bh(&nf_conntrack_lock); } EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); @@ -1150,6 +1163,7 @@ void nf_conntrack_cleanup(void) nf_conntrack_htable_size); nf_conntrack_proto_fini(); + nf_conntrack_helper_fini(); } static struct list_head *alloc_hashtable(int size, int *vmalloced) @@ -1272,6 +1286,10 @@ int __init nf_conntrack_init(void) if (ret < 0) goto out_free_expect_slab; + ret = nf_conntrack_helper_init(); + if (ret < 0) + goto out_fini_proto; + /* For use by REJECT target */ rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach); rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); @@ -1284,6 +1302,8 @@ int __init nf_conntrack_init(void) return ret; +out_fini_proto: + nf_conntrack_proto_fini(); out_free_expect_slab: kmem_cache_destroy(nf_conntrack_expect_cachep); err_free_conntrack_slab: diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index f868b7fbd9b4..6d32399d64e1 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -26,6 +26,7 @@ #include #include #include +#include static __read_mostly LIST_HEAD(helpers); @@ -100,18 +101,8 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { - int size, ret; - BUG_ON(me->timeout == 0); - size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) + - sizeof(struct nf_conn_help); - ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", - size); - if (ret < 0) { - printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n"); - return ret; - } write_lock_bh(&nf_conntrack_lock); list_add(&me->list, &helpers); write_unlock_bh(&nf_conntrack_lock); @@ -153,3 +144,19 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) synchronize_net(); } EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); + +struct nf_ct_ext_type helper_extend = { + .len = sizeof(struct nf_conn_help), + .align = __alignof__(struct nf_conn_help), + .id = NF_CT_EXT_HELPER, +}; + +int nf_conntrack_helper_init() +{ + return nf_ct_extend_register(&helper_extend); +} + +void nf_conntrack_helper_fini() +{ + nf_ct_extend_unregister(&helper_extend); +} diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d0fe3d769828..3d56f36074f7 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -856,23 +856,23 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) return 0; } - if (!help) { - /* FIXME: we need to reallocate and rehash */ - return -EBUSY; - } - helper = __nf_conntrack_helper_find_byname(helpname); if (helper == NULL) return -EINVAL; - if (help->helper == helper) - return 0; - - if (help->helper) - return -EBUSY; + if (help) { + if (help->helper == helper) + return 0; + if (help->helper) + return -EBUSY; + /* need to zero data of old helper */ + memset(&help->help, 0, sizeof(help->help)); + } else { + help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); + if (help == NULL) + return -ENOMEM; + } - /* need to zero data of old helper */ - memset(&help->help, 0, sizeof(help->help)); rcu_assign_pointer(help->helper, helper); return 0; @@ -957,7 +957,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], struct nf_conn *ct; int err = -EINVAL; struct nf_conn_help *help; - struct nf_conntrack_helper *helper = NULL; + struct nf_conntrack_helper *helper; ct = nf_conntrack_alloc(otuple, rtuple); if (ct == NULL || IS_ERR(ct)) @@ -987,9 +987,14 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); #endif - help = nfct_help(ct); - if (help) { - helper = nf_ct_helper_find_get(rtuple); + helper = nf_ct_helper_find_get(rtuple); + if (helper) { + help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); + if (help == NULL) { + nf_ct_helper_put(helper); + err = -ENOMEM; + goto err; + } /* not in hash table yet so not strictly necessary */ rcu_assign_pointer(help->helper, helper); } -- cgit v1.2.3 From e54cbc1f91dea4f98b6209e693d3b5eae46321bd Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:24:04 -0700 Subject: [NETFILTER]: nf_nat: add reference to conntrack from entry of bysource list I will split 'struct nf_nat_info' out from conntrack. So I cannot use 'offsetof' to get the pointer to conntrack from it. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_nat.h | 5 +++-- net/ipv4/netfilter/nf_nat_core.c | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 47d3dc107a6a..575dc8ac48dc 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -53,11 +53,14 @@ struct nf_nat_multi_range_compat #include #include +struct nf_conn; + /* The structure embedded in the conntrack structure. */ struct nf_nat_info { struct list_head bysource; struct nf_nat_seq seq[IP_CT_DIR_MAX]; + struct nf_conn *ct; }; /* per conntrack: nat application helper private data */ @@ -77,8 +80,6 @@ struct nf_conn_nat #endif }; -struct nf_conn; - /* Set up the info structure to map into this range. */ extern unsigned int nf_nat_setup_info(struct nf_conn *ct, const struct nf_nat_range *range, diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index ea02f00d2dac..ac7e8abbbdeb 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -97,6 +97,7 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *conn) nat = nfct_nat(conn); write_lock_bh(&nf_nat_lock); list_del(&nat->info.bysource); + nat->info.ct = NULL; write_unlock_bh(&nf_nat_lock); } @@ -169,7 +170,7 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, read_lock_bh(&nf_nat_lock); list_for_each_entry(nat, &bysource[h], info.bysource) { - ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data)); + ct = nat->info.ct; if (same_src(ct, tuple)) { /* Copy source part from reply tuple. */ nf_ct_invert_tuplepr(result, @@ -337,6 +338,7 @@ nf_nat_setup_info(struct nf_conn *ct, srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); write_lock_bh(&nf_nat_lock); + info->ct = ct; list_add(&info->bysource, &bysource[srchash]); write_unlock_bh(&nf_nat_lock); } -- cgit v1.2.3 From 2d59e5ca8c7113ad91452f0f9259a4b55ee90323 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:24:28 -0700 Subject: [NETFILTER]: nf_nat: use extension infrastructure Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 17 -------- include/net/netfilter/nf_conntrack_extend.h | 2 + include/net/netfilter/nf_nat.h | 6 +++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 3 -- net/ipv4/netfilter/nf_nat_core.c | 60 ++++++++++++++++++++++++-- net/ipv4/netfilter/nf_nat_standalone.c | 21 ++++----- 6 files changed, 73 insertions(+), 36 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index f1e0fee9aa9c..b2083d386f33 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -278,22 +278,5 @@ nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size); extern void nf_conntrack_unregister_cache(u_int32_t features); -/* valid combinations: - * basic: nf_conn, nf_conn .. nf_conn_help - * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help - */ -#ifdef CONFIG_NF_NAT_NEEDED -#include -static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) -{ - unsigned int offset = sizeof(struct nf_conn); - - if (!(ct->features & NF_CT_F_NAT)) - return NULL; - - offset = ALIGN(offset, __alignof__(struct nf_conn_nat)); - return (struct nf_conn_nat *) ((void *)ct + offset); -} -#endif /* CONFIG_NF_NAT_NEEDED */ #endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_H */ diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 05357dc5d2d2..73b5711faf32 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -6,10 +6,12 @@ enum nf_ct_ext_id { NF_CT_EXT_HELPER, + NF_CT_EXT_NAT, NF_CT_EXT_NUM, }; #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help +#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 575dc8ac48dc..0425e28c6a78 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -52,6 +52,7 @@ struct nf_nat_multi_range_compat #ifdef __KERNEL__ #include #include +#include struct nf_conn; @@ -89,6 +90,11 @@ extern unsigned int nf_nat_setup_info(struct nf_conn *ct, extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack); +static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) +{ + return nf_ct_ext_find(ct, NF_CT_EXT_NAT); +} + extern int nf_nat_module_is_loaded; #else /* !__KERNEL__: iptables wants this to compile. */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 6dc72a815f77..96f641d07a40 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -108,9 +108,6 @@ EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) { - if (nf_nat_module_is_loaded) - return NF_CT_F_NAT; - return NF_CT_F_BASIC; } diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index ac7e8abbbdeb..4ce82d7014ff 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -297,11 +297,21 @@ nf_nat_setup_info(struct nf_conn *ct, unsigned int hooknum) { struct nf_conntrack_tuple curr_tuple, new_tuple; - struct nf_conn_nat *nat = nfct_nat(ct); - struct nf_nat_info *info = &nat->info; + struct nf_conn_nat *nat; + struct nf_nat_info *info; int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); + /* nat helper or nfctnetlink also setup binding */ + nat = nfct_nat(ct); + if (!nat) { + nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); + if (nat == NULL) { + DEBUGP("failed to add NAT extension\n"); + return NF_ACCEPT; + } + } + NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN || @@ -338,6 +348,8 @@ nf_nat_setup_info(struct nf_conn *ct, srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); write_lock_bh(&nf_nat_lock); + /* nf_conntrack_alter_reply might re-allocate exntension aera */ + info = &nfct_nat(ct)->info; info->ct = ct; list_add(&info->bysource, &bysource[srchash]); write_unlock_bh(&nf_nat_lock); @@ -592,17 +604,52 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); #endif +static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) +{ + struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); + struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old; + struct nf_conn *ct = old_nat->info.ct; + unsigned int srchash; + + if (!(ct->status & IPS_NAT_DONE_MASK)) + return; + + srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + + write_lock_bh(&nf_nat_lock); + list_replace(&old_nat->info.bysource, &new_nat->info.bysource); + new_nat->info.ct = ct; + write_unlock_bh(&nf_nat_lock); +} + +struct nf_ct_ext_type nat_extend = { + .len = sizeof(struct nf_conn_nat), + .align = __alignof__(struct nf_conn_nat), + .move = nf_nat_move_storage, + .id = NF_CT_EXT_NAT, + .flags = NF_CT_EXT_F_PREALLOC, +}; + static int __init nf_nat_init(void) { size_t i; + int ret; + + ret = nf_ct_extend_register(&nat_extend); + if (ret < 0) { + printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); + return ret; + } /* Leave them the same for the moment. */ nf_nat_htable_size = nf_conntrack_htable_size; /* One vmalloc for both hash tables */ bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); - if (!bysource) - return -ENOMEM; + if (!bysource) { + ret = -ENOMEM; + goto cleanup_extend; + } /* Sew in builtin protocols. */ write_lock_bh(&nf_nat_lock); @@ -626,6 +673,10 @@ static int __init nf_nat_init(void) l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); return 0; + + cleanup_extend: + nf_ct_extend_unregister(&nat_extend); + return ret; } /* Clear NAT section of all conntracks, in case we're loaded again. */ @@ -647,6 +698,7 @@ static void __exit nf_nat_cleanup(void) synchronize_rcu(); vfree(bysource); nf_ct_l3proto_put(l3proto); + nf_ct_extend_unregister(&nat_extend); } MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 0b2f0c33f7cd..51a2708f7bf0 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -113,8 +114,13 @@ nf_nat_fn(unsigned int hooknum, return NF_ACCEPT; nat = nfct_nat(ct); - if (!nat) - return NF_ACCEPT; + if (!nat) { + nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); + if (nat == NULL) { + DEBUGP("failed to add NAT extension\n"); + return NF_ACCEPT; + } + } switch (ctinfo) { case IP_CT_RELATED: @@ -326,18 +332,10 @@ static struct nf_hook_ops nf_nat_ops[] = { static int __init nf_nat_standalone_init(void) { - int size, ret = 0; + int ret = 0; need_conntrack(); - size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) + - sizeof(struct nf_conn_nat); - ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size); - if (ret < 0) { - printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n"); - return ret; - } - #ifdef CONFIG_XFRM BUG_ON(ip_nat_decode_session != NULL); ip_nat_decode_session = nat_decode_session; @@ -362,7 +360,6 @@ static int __init nf_nat_standalone_init(void) ip_nat_decode_session = NULL; synchronize_net(); #endif - nf_conntrack_unregister_cache(NF_CT_F_NAT); return ret; } -- cgit v1.2.3 From ff09b7493c8f433d3ffd6a31ad58d190f82ef0c5 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:25:28 -0700 Subject: [NETFILTER]: nf_nat: remove unused nf_nat_module_is_loaded Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_nat.h | 2 -- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 3 --- net/ipv4/netfilter/nf_nat_standalone.c | 2 -- 3 files changed, 7 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 0425e28c6a78..0541eed5008f 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -95,8 +95,6 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) return nf_ct_ext_find(ct, NF_CT_EXT_NAT); } -extern int nf_nat_module_is_loaded; - #else /* !__KERNEL__: iptables wants this to compile. */ #define nf_nat_multi_range nf_nat_multi_range_compat #endif /*__KERNEL__*/ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 96f641d07a40..7411dd16d779 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -103,9 +103,6 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, return NF_ACCEPT; } -int nf_nat_module_is_loaded = 0; -EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); - static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) { return NF_CT_F_BASIC; diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 51a2708f7bf0..30eeaa4c645c 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -350,7 +350,6 @@ static int __init nf_nat_standalone_init(void) printk("nf_nat_init: can't register hooks.\n"); goto cleanup_rule_init; } - nf_nat_module_is_loaded = 1; return ret; cleanup_rule_init: @@ -367,7 +366,6 @@ static void __exit nf_nat_standalone_fini(void) { nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); nf_nat_rule_cleanup(); - nf_nat_module_is_loaded = 0; #ifdef CONFIG_XFRM ip_nat_decode_session = NULL; synchronize_net(); -- cgit v1.2.3 From dacd2a1a5cf621288833aa3c6e815b86a1536538 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:25:51 -0700 Subject: [NETFILTER]: nf_conntrack: remove old memory allocator of conntrack Now memory space for help and NAT are allocated by extension infrastructure. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 14 -- include/net/netfilter/nf_conntrack_l3proto.h | 2 - net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 - net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 6 - net/netfilter/nf_conntrack_core.c | 222 ++----------------------- net/netfilter/nf_conntrack_l3proto_generic.c | 7 - 6 files changed, 15 insertions(+), 242 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index b2083d386f33..71386e5c4bb7 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -117,9 +117,6 @@ struct nf_conn /* Unique ID that identifies this conntrack*/ unsigned int id; - /* features - nat, helper, ... used by allocating system */ - u_int32_t features; - #if defined(CONFIG_NF_CONNTRACK_MARK) u_int32_t mark; #endif @@ -133,9 +130,6 @@ struct nf_conn /* Extensions */ struct nf_ct_ext *ext; - - /* features dynamically at the end: helper, nat (both optional) */ - char data[0]; }; static inline struct nf_conn * @@ -265,14 +259,6 @@ do { \ local_bh_enable(); \ } while (0) -/* no helper, no nat */ -#define NF_CT_F_BASIC 0 -/* for helper */ -#define NF_CT_F_HELP 1 -/* for nat. */ -#define NF_CT_F_NAT 2 -#define NF_CT_F_NUM 4 - extern int nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size); extern void diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 96a58d8e1d3f..890752d7f673 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -64,8 +64,6 @@ struct nf_conntrack_l3proto int (*prepare)(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, u_int8_t *protonum); - u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple); - int (*tuple_to_nfattr)(struct sk_buff *skb, const struct nf_conntrack_tuple *t); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 7411dd16d779..129a8cccf4a1 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -103,11 +103,6 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, return NF_ACCEPT; } -static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) -{ - return NF_CT_F_BASIC; -} - static unsigned int ipv4_confirm(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, @@ -419,7 +414,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .print_tuple = ipv4_print_tuple, .print_conntrack = ipv4_print_conntrack, .prepare = ipv4_prepare, - .get_features = ipv4_get_features, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv4_tuple_to_nfattr, .nfattr_to_tuple = ipv4_nfattr_to_tuple, diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 1b1797f1f33d..747b01e53132 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -147,11 +147,6 @@ ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, return NF_ACCEPT; } -static u_int32_t ipv6_get_features(const struct nf_conntrack_tuple *tuple) -{ - return NF_CT_F_BASIC; -} - static unsigned int ipv6_confirm(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, @@ -397,7 +392,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .ctl_table_path = nf_net_netfilter_sysctl_path, .ctl_table = nf_ct_ipv6_sysctl_table, #endif - .get_features = ipv6_get_features, .me = THIS_MODULE, }; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 914506e6c787..a71366652938 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -71,39 +71,12 @@ EXPORT_SYMBOL_GPL(nf_conntrack_untracked); unsigned int nf_ct_log_invalid __read_mostly; LIST_HEAD(unconfirmed); static int nf_conntrack_vmalloc __read_mostly; - +static struct kmem_cache *nf_conntrack_cachep __read_mostly; static unsigned int nf_conntrack_next_id; DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat); -/* - * This scheme offers various size of "struct nf_conn" dependent on - * features(helper, nat, ...) - */ - -#define NF_CT_FEATURES_NAMELEN 256 -static struct { - /* name of slab cache. printed in /proc/slabinfo */ - char *name; - - /* size of slab cache */ - size_t size; - - /* slab cache pointer */ - struct kmem_cache *cachep; - - /* allocated slab cache + modules which uses this slab cache */ - int use; - -} nf_ct_cache[NF_CT_F_NUM]; - -/* protect members of nf_ct_cache except of "use" */ -DEFINE_RWLOCK(nf_ct_cache_lock); - -/* This avoids calling kmem_cache_create() with same name simultaneously */ -static DEFINE_MUTEX(nf_ct_cache_mutex); - static int nf_conntrack_hash_rnd_initted; static unsigned int nf_conntrack_hash_rnd; @@ -126,122 +99,6 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) nf_conntrack_hash_rnd); } -int nf_conntrack_register_cache(u_int32_t features, const char *name, - size_t size) -{ - int ret = 0; - char *cache_name; - struct kmem_cache *cachep; - - DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n", - features, name, size); - - if (features < NF_CT_F_BASIC || features >= NF_CT_F_NUM) { - DEBUGP("nf_conntrack_register_cache: invalid features.: 0x%x\n", - features); - return -EINVAL; - } - - mutex_lock(&nf_ct_cache_mutex); - - write_lock_bh(&nf_ct_cache_lock); - /* e.g: multiple helpers are loaded */ - if (nf_ct_cache[features].use > 0) { - DEBUGP("nf_conntrack_register_cache: already resisterd.\n"); - if ((!strncmp(nf_ct_cache[features].name, name, - NF_CT_FEATURES_NAMELEN)) - && nf_ct_cache[features].size == size) { - DEBUGP("nf_conntrack_register_cache: reusing.\n"); - nf_ct_cache[features].use++; - ret = 0; - } else - ret = -EBUSY; - - write_unlock_bh(&nf_ct_cache_lock); - mutex_unlock(&nf_ct_cache_mutex); - return ret; - } - write_unlock_bh(&nf_ct_cache_lock); - - /* - * The memory space for name of slab cache must be alive until - * cache is destroyed. - */ - cache_name = kmalloc(sizeof(char)*NF_CT_FEATURES_NAMELEN, GFP_ATOMIC); - if (cache_name == NULL) { - DEBUGP("nf_conntrack_register_cache: can't alloc cache_name\n"); - ret = -ENOMEM; - goto out_up_mutex; - } - - if (strlcpy(cache_name, name, NF_CT_FEATURES_NAMELEN) - >= NF_CT_FEATURES_NAMELEN) { - printk("nf_conntrack_register_cache: name too long\n"); - ret = -EINVAL; - goto out_free_name; - } - - cachep = kmem_cache_create(cache_name, size, 0, 0, - NULL, NULL); - if (!cachep) { - printk("nf_conntrack_register_cache: Can't create slab cache " - "for the features = 0x%x\n", features); - ret = -ENOMEM; - goto out_free_name; - } - - write_lock_bh(&nf_ct_cache_lock); - nf_ct_cache[features].use = 1; - nf_ct_cache[features].size = size; - nf_ct_cache[features].cachep = cachep; - nf_ct_cache[features].name = cache_name; - write_unlock_bh(&nf_ct_cache_lock); - - goto out_up_mutex; - -out_free_name: - kfree(cache_name); -out_up_mutex: - mutex_unlock(&nf_ct_cache_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(nf_conntrack_register_cache); - -/* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */ -void nf_conntrack_unregister_cache(u_int32_t features) -{ - struct kmem_cache *cachep; - char *name; - - /* - * This assures that kmem_cache_create() isn't called before destroying - * slab cache. - */ - DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features); - mutex_lock(&nf_ct_cache_mutex); - - write_lock_bh(&nf_ct_cache_lock); - if (--nf_ct_cache[features].use > 0) { - write_unlock_bh(&nf_ct_cache_lock); - mutex_unlock(&nf_ct_cache_mutex); - return; - } - cachep = nf_ct_cache[features].cachep; - name = nf_ct_cache[features].name; - nf_ct_cache[features].cachep = NULL; - nf_ct_cache[features].name = NULL; - nf_ct_cache[features].size = 0; - write_unlock_bh(&nf_ct_cache_lock); - - synchronize_net(); - - kmem_cache_destroy(cachep); - kfree(name); - - mutex_unlock(&nf_ct_cache_mutex); -} -EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache); - int nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, @@ -559,11 +416,8 @@ static int early_drop(struct list_head *chain) return dropped; } -static struct nf_conn * -__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, - const struct nf_conntrack_tuple *repl, - const struct nf_conntrack_l3proto *l3proto, - u_int32_t features) +struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, + const struct nf_conntrack_tuple *repl) { struct nf_conn *conntrack = NULL; @@ -589,65 +443,28 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, } } - /* find features needed by this conntrack. */ - features |= l3proto->get_features(orig); - - DEBUGP("nf_conntrack_alloc: features=0x%x\n", features); - - read_lock_bh(&nf_ct_cache_lock); - - if (unlikely(!nf_ct_cache[features].use)) { - DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n", - features); - goto out; - } - - conntrack = kmem_cache_alloc(nf_ct_cache[features].cachep, GFP_ATOMIC); + conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC); if (conntrack == NULL) { - DEBUGP("nf_conntrack_alloc: Can't alloc conntrack from cache\n"); - goto out; + DEBUGP("nf_conntrack_alloc: Can't alloc conntrack.\n"); + atomic_dec(&nf_conntrack_count); + return ERR_PTR(-ENOMEM); } - memset(conntrack, 0, nf_ct_cache[features].size); - conntrack->features = features; atomic_set(&conntrack->ct_general.use, 1); conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; /* Don't set timer yet: wait for confirmation */ setup_timer(&conntrack->timeout, death_by_timeout, (unsigned long)conntrack); - read_unlock_bh(&nf_ct_cache_lock); - return conntrack; -out: - read_unlock_bh(&nf_ct_cache_lock); - atomic_dec(&nf_conntrack_count); return conntrack; } - -struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, - const struct nf_conntrack_tuple *repl) -{ - struct nf_conntrack_l3proto *l3proto; - struct nf_conn *ct; - - rcu_read_lock(); - l3proto = __nf_ct_l3proto_find(orig->src.l3num); - ct = __nf_conntrack_alloc(orig, repl, l3proto, 0); - rcu_read_unlock(); - - return ct; -} EXPORT_SYMBOL_GPL(nf_conntrack_alloc); void nf_conntrack_free(struct nf_conn *conntrack) { - u_int32_t features = conntrack->features; - NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM); nf_ct_ext_free(conntrack); - DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features, - conntrack); - kmem_cache_free(nf_ct_cache[features].cachep, conntrack); + kmem_cache_free(nf_conntrack_cachep, conntrack); atomic_dec(&nf_conntrack_count); } EXPORT_SYMBOL_GPL(nf_conntrack_free); @@ -665,14 +482,13 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, struct nf_conn_help *help; struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_expect *exp; - u_int32_t features = 0; if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { DEBUGP("Can't invert tuple.\n"); return NULL; } - conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features); + conntrack = nf_conntrack_alloc(tuple, &repl_tuple); if (conntrack == NULL || IS_ERR(conntrack)) { DEBUGP("Can't allocate conntrack.\n"); return (struct nf_conntrack_tuple_hash *)conntrack; @@ -1128,8 +944,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_flush); supposed to kill the mall. */ void nf_conntrack_cleanup(void) { - int i; - rcu_assign_pointer(ip_ct_attach, NULL); /* This makes sure all current packets have passed through @@ -1150,14 +964,7 @@ void nf_conntrack_cleanup(void) rcu_assign_pointer(nf_ct_destroy, NULL); - for (i = 0; i < NF_CT_F_NUM; i++) { - if (nf_ct_cache[i].use == 0) - continue; - - NF_CT_ASSERT(nf_ct_cache[i].use == 1); - nf_ct_cache[i].use = 1; - nf_conntrack_unregister_cache(i); - } + kmem_cache_destroy(nf_conntrack_cachep); kmem_cache_destroy(nf_conntrack_expect_cachep); free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, nf_conntrack_htable_size); @@ -1267,9 +1074,10 @@ int __init nf_conntrack_init(void) goto err_out; } - ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic", - sizeof(struct nf_conn)); - if (ret < 0) { + nf_conntrack_cachep = kmem_cache_create("nf_conntrack", + sizeof(struct nf_conn), + 0, 0, NULL, NULL); + if (!nf_conntrack_cachep) { printk(KERN_ERR "Unable to create nf_conn slab cache\n"); goto err_free_hash; } @@ -1307,7 +1115,7 @@ out_fini_proto: out_free_expect_slab: kmem_cache_destroy(nf_conntrack_expect_cachep); err_free_conntrack_slab: - nf_conntrack_unregister_cache(NF_CT_F_BASIC); + kmem_cache_destroy(nf_conntrack_cachep); err_free_hash: free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, nf_conntrack_htable_size); diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index cbd96f3c1b89..2fd0f11b8fb2 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -76,12 +76,6 @@ generic_prepare(struct sk_buff **pskb, unsigned int hooknum, } -static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple) - -{ - return NF_CT_F_BASIC; -} - struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { .l3proto = PF_UNSPEC, .name = "unknown", @@ -90,6 +84,5 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { .print_tuple = generic_print_tuple, .print_conntrack = generic_print_conntrack, .prepare = generic_prepare, - .get_features = generic_get_features, }; EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); -- cgit v1.2.3 From d8a0509a696de60296a66ba4fe4f9eaade497103 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:26:16 -0700 Subject: [NETFILTER]: nf_nat: kill global 'destroy' operation This kills the global 'destroy' operation which was used by NAT. Instead it uses the extension infrastructure so that multiple extensions can register own operations. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 3 --- net/ipv4/netfilter/nf_nat_core.c | 46 +++++++++++++++++------------------- net/netfilter/nf_conntrack_core.c | 8 ------- 3 files changed, 22 insertions(+), 35 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 71386e5c4bb7..ef4a403878a3 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -213,9 +213,6 @@ extern void nf_conntrack_tcp_update(struct sk_buff *skb, struct nf_conn *conntrack, int dir); -/* Call me when a conntrack is destroyed. */ -extern void (*nf_conntrack_destroyed)(struct nf_conn *conntrack); - /* Fake conntrack entry for untracked connections */ extern struct nf_conn nf_conntrack_untracked; diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 4ce82d7014ff..e370d1568001 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -87,20 +87,6 @@ hash_by_src(const struct nf_conntrack_tuple *tuple) tuple->dst.protonum, 0) % nf_nat_htable_size; } -/* Noone using conntrack by the time this called. */ -static void nf_nat_cleanup_conntrack(struct nf_conn *conn) -{ - struct nf_conn_nat *nat; - if (!(conn->status & IPS_NAT_DONE_MASK)) - return; - - nat = nfct_nat(conn); - write_lock_bh(&nf_nat_lock); - list_del(&nat->info.bysource); - nat->info.ct = NULL; - write_unlock_bh(&nf_nat_lock); -} - /* Is this tuple already taken? (not by us) */ int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, @@ -604,6 +590,22 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); #endif +/* Noone using conntrack by the time this called. */ +static void nf_nat_cleanup_conntrack(struct nf_conn *ct) +{ + struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); + + if (nat == NULL || nat->info.ct == NULL) + return; + + NF_CT_ASSERT(nat->info.ct->status & IPS_NAT_DONE_MASK); + + write_lock_bh(&nf_nat_lock); + list_del(&nat->info.bysource); + nat->info.ct = NULL; + write_unlock_bh(&nf_nat_lock); +} + static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) { struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); @@ -623,11 +625,12 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) } struct nf_ct_ext_type nat_extend = { - .len = sizeof(struct nf_conn_nat), - .align = __alignof__(struct nf_conn_nat), - .move = nf_nat_move_storage, - .id = NF_CT_EXT_NAT, - .flags = NF_CT_EXT_F_PREALLOC, + .len = sizeof(struct nf_conn_nat), + .align = __alignof__(struct nf_conn_nat), + .destroy = nf_nat_cleanup_conntrack, + .move = nf_nat_move_storage, + .id = NF_CT_EXT_NAT, + .flags = NF_CT_EXT_F_PREALLOC, }; static int __init nf_nat_init(void) @@ -664,10 +667,6 @@ static int __init nf_nat_init(void) INIT_LIST_HEAD(&bysource[i]); } - /* FIXME: Man, this is a hack. */ - NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL); - rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack); - /* Initialize fake conntrack so that NAT will skip it */ nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; @@ -694,7 +693,6 @@ static int clean_nat(struct nf_conn *i, void *data) static void __exit nf_nat_cleanup(void) { nf_ct_iterate_cleanup(&clean_nat, NULL); - rcu_assign_pointer(nf_conntrack_destroyed, NULL); synchronize_rcu(); vfree(bysource); nf_ct_l3proto_put(l3proto); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a71366652938..035eb9f4a61e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -53,9 +53,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_lock); atomic_t nf_conntrack_count = ATOMIC_INIT(0); EXPORT_SYMBOL_GPL(nf_conntrack_count); -void (*nf_conntrack_destroyed)(struct nf_conn *conntrack); -EXPORT_SYMBOL_GPL(nf_conntrack_destroyed); - unsigned int nf_conntrack_htable_size __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); @@ -157,7 +154,6 @@ destroy_conntrack(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conntrack_l4proto *l4proto; - typeof(nf_conntrack_destroyed) destroyed; DEBUGP("destroy_conntrack(%p)\n", ct); NF_CT_ASSERT(atomic_read(&nfct->use) == 0); @@ -177,10 +173,6 @@ destroy_conntrack(struct nf_conntrack *nfct) nf_ct_ext_destroy(ct); - destroyed = rcu_dereference(nf_conntrack_destroyed); - if (destroyed) - destroyed(ct); - rcu_read_unlock(); write_lock_bh(&nf_conntrack_lock); -- cgit v1.2.3 From b6b84d4a94e95727a4c65841eea23ac60c6aa329 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 7 Jul 2007 22:26:35 -0700 Subject: [NETFILTER]: nf_nat: merge nf_conn and nf_nat_info Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_nat.h | 17 ++++++----------- net/ipv4/netfilter/nf_nat_core.c | 25 ++++++++++++------------- net/ipv4/netfilter/nf_nat_helper.c | 11 +++++------ 3 files changed, 23 insertions(+), 30 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 0541eed5008f..d0e5e436dc1b 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -54,16 +54,6 @@ struct nf_nat_multi_range_compat #include #include -struct nf_conn; - -/* The structure embedded in the conntrack structure. */ -struct nf_nat_info -{ - struct list_head bysource; - struct nf_nat_seq seq[IP_CT_DIR_MAX]; - struct nf_conn *ct; -}; - /* per conntrack: nat application helper private data */ union nf_conntrack_nat_help { @@ -71,9 +61,14 @@ union nf_conntrack_nat_help struct nf_nat_pptp nat_pptp_info; }; +struct nf_conn; + +/* The structure embedded in the conntrack structure. */ struct nf_conn_nat { - struct nf_nat_info info; + struct list_head bysource; + struct nf_nat_seq seq[IP_CT_DIR_MAX]; + struct nf_conn *ct; union nf_conntrack_nat_help help; #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index e370d1568001..7e31777082de 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -155,8 +155,8 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, struct nf_conn *ct; read_lock_bh(&nf_nat_lock); - list_for_each_entry(nat, &bysource[h], info.bysource) { - ct = nat->info.ct; + list_for_each_entry(nat, &bysource[h], bysource) { + ct = nat->ct; if (same_src(ct, tuple)) { /* Copy source part from reply tuple. */ nf_ct_invert_tuplepr(result, @@ -284,7 +284,6 @@ nf_nat_setup_info(struct nf_conn *ct, { struct nf_conntrack_tuple curr_tuple, new_tuple; struct nf_conn_nat *nat; - struct nf_nat_info *info; int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); @@ -335,9 +334,9 @@ nf_nat_setup_info(struct nf_conn *ct, srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); write_lock_bh(&nf_nat_lock); /* nf_conntrack_alter_reply might re-allocate exntension aera */ - info = &nfct_nat(ct)->info; - info->ct = ct; - list_add(&info->bysource, &bysource[srchash]); + nat = nfct_nat(ct); + nat->ct = ct; + list_add(&nat->bysource, &bysource[srchash]); write_unlock_bh(&nf_nat_lock); } @@ -595,14 +594,14 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) { struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); - if (nat == NULL || nat->info.ct == NULL) + if (nat == NULL || nat->ct == NULL) return; - NF_CT_ASSERT(nat->info.ct->status & IPS_NAT_DONE_MASK); + NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK); write_lock_bh(&nf_nat_lock); - list_del(&nat->info.bysource); - nat->info.ct = NULL; + list_del(&nat->bysource); + nat->ct = NULL; write_unlock_bh(&nf_nat_lock); } @@ -610,7 +609,7 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) { struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old; - struct nf_conn *ct = old_nat->info.ct; + struct nf_conn *ct = old_nat->ct; unsigned int srchash; if (!(ct->status & IPS_NAT_DONE_MASK)) @@ -619,8 +618,8 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); write_lock_bh(&nf_nat_lock); - list_replace(&old_nat->info.bysource, &new_nat->info.bysource); - new_nat->info.ct = ct; + list_replace(&old_nat->bysource, &new_nat->bysource); + new_nat->ct = ct; write_unlock_bh(&nf_nat_lock); } diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index ef0a99e09fd1..f3383fc14e1c 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -52,8 +52,8 @@ adjust_tcp_sequence(u32 seq, dir = CTINFO2DIR(ctinfo); - this_way = &nat->info.seq[dir]; - other_way = &nat->info.seq[!dir]; + this_way = &nat->seq[dir]; + other_way = &nat->seq[!dir]; DEBUGP("nf_nat_resize_packet: Seq_offset before: "); DUMP_OFFSET(this_way); @@ -372,8 +372,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, op[1] >= 2+TCPOLEN_SACK_PERBLOCK && ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) sack_adjust(*pskb, tcph, optoff+2, - optoff+op[1], - &nat->info.seq[!dir]); + optoff+op[1], &nat->seq[!dir]); optoff += op[1]; } } @@ -394,8 +393,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb, dir = CTINFO2DIR(ctinfo); - this_way = &nat->info.seq[dir]; - other_way = &nat->info.seq[!dir]; + this_way = &nat->seq[dir]; + other_way = &nat->seq[!dir]; if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) return 0; -- cgit v1.2.3 From f205c5e0c28aa7e0fb6eaaa66e97928f9d9e6994 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:28:14 -0700 Subject: [NETFILTER]: nf_conntrack: use hlists for conntrack hash Convert conntrack hash to hlists to reduce its size and cache footprint. Since the default hashsize to max. entries ratio sucks (1:16), this patch doesn't reduce the amount of memory used for the hash by default, but instead uses a better ratio of 1:8, which results in the same max. entries value. One thing worth noting is early_drop. It really should use LRU, so it now has to iterate over the entire chain to find the last unconfirmed entry. Since chains shouldn't be very long and the entire operation is very rare this shouldn't be a problem. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_core.h | 4 +- include/net/netfilter/nf_conntrack_tuple.h | 3 +- .../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 17 ++-- net/netfilter/nf_conntrack_core.c | 100 ++++++++++++--------- net/netfilter/nf_conntrack_helper.c | 5 +- net/netfilter/nf_conntrack_netlink.c | 6 +- net/netfilter/nf_conntrack_standalone.c | 17 ++-- 7 files changed, 83 insertions(+), 69 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 3bf7d05ea64d..6351948654b3 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -84,9 +84,9 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, struct nf_conntrack_l4proto *proto); -extern struct list_head *nf_conntrack_hash; +extern struct hlist_head *nf_conntrack_hash; extern struct list_head nf_conntrack_expect_list; extern rwlock_t nf_conntrack_lock ; -extern struct list_head unconfirmed; +extern struct hlist_head unconfirmed; #endif /* _NF_CONNTRACK_CORE_H */ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 5d72b16e876f..d02ce876b4ca 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -125,8 +125,7 @@ DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ /* Connections have two entries in the hash table: one for each way */ struct nf_conntrack_tuple_hash { - struct list_head list; - + struct hlist_node hnode; struct nf_conntrack_tuple tuple; }; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 89f933e81035..888f27fd884f 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -41,35 +41,36 @@ struct ct_iter_state { unsigned int bucket; }; -static struct list_head *ct_get_first(struct seq_file *seq) +static struct hlist_node *ct_get_first(struct seq_file *seq) { struct ct_iter_state *st = seq->private; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { - if (!list_empty(&nf_conntrack_hash[st->bucket])) - return nf_conntrack_hash[st->bucket].next; + if (!hlist_empty(&nf_conntrack_hash[st->bucket])) + return nf_conntrack_hash[st->bucket].first; } return NULL; } -static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head) +static struct hlist_node *ct_get_next(struct seq_file *seq, + struct hlist_node *head) { struct ct_iter_state *st = seq->private; head = head->next; - while (head == &nf_conntrack_hash[st->bucket]) { + while (head == NULL) { if (++st->bucket >= nf_conntrack_htable_size) return NULL; - head = nf_conntrack_hash[st->bucket].next; + head = nf_conntrack_hash[st->bucket].first; } return head; } -static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) { - struct list_head *head = ct_get_first(seq); + struct hlist_node *head = ct_get_first(seq); if (head) while (pos && (head = ct_get_next(seq, head))) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 54acac5c6ea7..992d0ef31fa3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -59,14 +59,14 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); int nf_conntrack_max __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_max); -struct list_head *nf_conntrack_hash __read_mostly; +struct hlist_head *nf_conntrack_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_hash); struct nf_conn nf_conntrack_untracked __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_untracked); unsigned int nf_ct_log_invalid __read_mostly; -LIST_HEAD(unconfirmed); +HLIST_HEAD(unconfirmed); static int nf_conntrack_vmalloc __read_mostly; static struct kmem_cache *nf_conntrack_cachep __read_mostly; static unsigned int nf_conntrack_next_id; @@ -142,8 +142,8 @@ static void clean_from_lists(struct nf_conn *ct) { DEBUGP("clean_from_lists(%p)\n", ct); - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); + hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); + hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); /* Destroy all pending expectations */ nf_ct_remove_expectations(ct); @@ -184,8 +184,8 @@ destroy_conntrack(struct nf_conntrack *nfct) /* We overload first tuple to link into unconfirmed list. */ if (!nf_ct_is_confirmed(ct)) { - BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list)); - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); + hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); } NF_CT_STAT_INC(delete); @@ -226,9 +226,10 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack) { struct nf_conntrack_tuple_hash *h; + struct hlist_node *n; unsigned int hash = hash_conntrack(tuple); - list_for_each_entry(h, &nf_conntrack_hash[hash], list) { + hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) { if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && nf_ct_tuple_equal(tuple, &h->tuple)) { NF_CT_STAT_INC(found); @@ -263,10 +264,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, unsigned int repl_hash) { ct->id = ++nf_conntrack_next_id; - list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list, - &nf_conntrack_hash[hash]); - list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list, - &nf_conntrack_hash[repl_hash]); + hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, + &nf_conntrack_hash[hash]); + hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, + &nf_conntrack_hash[repl_hash]); } void nf_conntrack_hash_insert(struct nf_conn *ct) @@ -290,6 +291,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; struct nf_conn_help *help; + struct hlist_node *n; enum ip_conntrack_info ctinfo; ct = nf_ct_get(*pskb, &ctinfo); @@ -319,17 +321,17 @@ __nf_conntrack_confirm(struct sk_buff **pskb) /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're not in the hash. If there is, we lost race. */ - list_for_each_entry(h, &nf_conntrack_hash[hash], list) + hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, &h->tuple)) goto out; - list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list) + hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, &h->tuple)) goto out; /* Remove from unconfirmed list */ - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); __nf_conntrack_hash_insert(ct, hash, repl_hash); /* Timer relative to confirmation time, not original @@ -378,22 +380,22 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); /* There's a small race here where we may free a just-assured connection. Too bad: we're in trouble anyway. */ -static int early_drop(struct list_head *chain) +static int early_drop(struct hlist_head *chain) { - /* Traverse backwards: gives us oldest, which is roughly LRU */ + /* Use oldest entry, which is roughly LRU */ struct nf_conntrack_tuple_hash *h; struct nf_conn *ct = NULL, *tmp; + struct hlist_node *n; int dropped = 0; read_lock_bh(&nf_conntrack_lock); - list_for_each_entry_reverse(h, chain, list) { + hlist_for_each_entry(h, n, chain, hnode) { tmp = nf_ct_tuplehash_to_ctrack(h); - if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) { + if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) ct = tmp; - atomic_inc(&ct->ct_general.use); - break; - } } + if (ct) + atomic_inc(&ct->ct_general.use); read_unlock_bh(&nf_conntrack_lock); if (!ct) @@ -535,7 +537,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, } /* Overload tuple linked list to put us in unconfirmed list. */ - list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); + hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode, + &unconfirmed); write_unlock_bh(&nf_conntrack_lock); @@ -873,16 +876,17 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), { struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; + struct hlist_node *n; write_lock_bh(&nf_conntrack_lock); for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { - list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) { + hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) goto found; } } - list_for_each_entry(h, &unconfirmed, list) { + hlist_for_each_entry(h, n, &unconfirmed, hnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) set_bit(IPS_DYING_BIT, &ct->status); @@ -917,13 +921,14 @@ static int kill_all(struct nf_conn *i, void *data) return 1; } -static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size) +static void free_conntrack_hash(struct hlist_head *hash, int vmalloced, + int size) { if (vmalloced) vfree(hash); else free_pages((unsigned long)hash, - get_order(sizeof(struct list_head) * size)); + get_order(sizeof(struct hlist_head) * size)); } void nf_conntrack_flush(void) @@ -965,26 +970,26 @@ void nf_conntrack_cleanup(void) nf_conntrack_helper_fini(); } -static struct list_head *alloc_hashtable(int *sizep, int *vmalloced) +static struct hlist_head *alloc_hashtable(int *sizep, int *vmalloced) { - struct list_head *hash; + struct hlist_head *hash; unsigned int size, i; *vmalloced = 0; - size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct list_head)); + size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); hash = (void*)__get_free_pages(GFP_KERNEL, - get_order(sizeof(struct list_head) + get_order(sizeof(struct hlist_head) * size)); if (!hash) { *vmalloced = 1; printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); - hash = vmalloc(sizeof(struct list_head) * size); + hash = vmalloc(sizeof(struct hlist_head) * size); } if (hash) for (i = 0; i < size; i++) - INIT_LIST_HEAD(&hash[i]); + INIT_HLIST_HEAD(&hash[i]); return hash; } @@ -994,7 +999,7 @@ int set_hashsize(const char *val, struct kernel_param *kp) int i, bucket, hashsize, vmalloced; int old_vmalloced, old_size; int rnd; - struct list_head *hash, *old_hash; + struct hlist_head *hash, *old_hash; struct nf_conntrack_tuple_hash *h; /* On boot, we can set this without any fancy locking. */ @@ -1015,12 +1020,12 @@ int set_hashsize(const char *val, struct kernel_param *kp) write_lock_bh(&nf_conntrack_lock); for (i = 0; i < nf_conntrack_htable_size; i++) { - while (!list_empty(&nf_conntrack_hash[i])) { - h = list_entry(nf_conntrack_hash[i].next, - struct nf_conntrack_tuple_hash, list); - list_del(&h->list); + while (!hlist_empty(&nf_conntrack_hash[i])) { + h = hlist_entry(nf_conntrack_hash[i].first, + struct nf_conntrack_tuple_hash, hnode); + hlist_del(&h->hnode); bucket = __hash_conntrack(&h->tuple, hashsize, rnd); - list_add_tail(&h->list, &hash[bucket]); + hlist_add_head(&h->hnode, &hash[bucket]); } } old_size = nf_conntrack_htable_size; @@ -1042,18 +1047,25 @@ module_param_call(hashsize, set_hashsize, param_get_uint, int __init nf_conntrack_init(void) { + int max_factor = 8; int ret; /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB - * machine has 256 buckets. >= 1GB machines have 8192 buckets. */ + * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ if (!nf_conntrack_htable_size) { nf_conntrack_htable_size = (((num_physpages << PAGE_SHIFT) / 16384) - / sizeof(struct list_head)); + / sizeof(struct hlist_head)); if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE)) - nf_conntrack_htable_size = 8192; - if (nf_conntrack_htable_size < 16) - nf_conntrack_htable_size = 16; + nf_conntrack_htable_size = 16384; + if (nf_conntrack_htable_size < 32) + nf_conntrack_htable_size = 32; + + /* Use a max. factor of four by default to get the same max as + * with the old struct list_heads. When a table size is given + * we use the old value of 8 to avoid reducing the max. + * entries. */ + max_factor = 4; } nf_conntrack_hash = alloc_hashtable(&nf_conntrack_htable_size, &nf_conntrack_vmalloc); @@ -1062,7 +1074,7 @@ int __init nf_conntrack_init(void) goto err_out; } - nf_conntrack_max = 8 * nf_conntrack_htable_size; + nf_conntrack_max = max_factor * nf_conntrack_htable_size; printk("nf_conntrack version %s (%u buckets, %d max)\n", NF_CONNTRACK_VERSION, nf_conntrack_htable_size, diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index dc352f509477..3fc6e9f0de1a 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -116,6 +116,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) unsigned int i; struct nf_conntrack_tuple_hash *h; struct nf_conntrack_expect *exp, *tmp; + struct hlist_node *n; /* Need write lock here, to delete helper. */ write_lock_bh(&nf_conntrack_lock); @@ -132,10 +133,10 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) } /* Get rid of expecteds, set helpers to NULL. */ - list_for_each_entry(h, &unconfirmed, list) + hlist_for_each_entry(h, n, &unconfirmed, hnode) unhelp(h, me); for (i = 0; i < nf_conntrack_htable_size; i++) { - list_for_each_entry(h, &nf_conntrack_hash[i], list) + hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode) unhelp(h, me); } write_unlock_bh(&nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 3d56f36074f7..0627559ca470 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -428,7 +428,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { struct nf_conn *ct, *last; struct nf_conntrack_tuple_hash *h; - struct list_head *i; + struct hlist_node *n; struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; @@ -436,8 +436,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: - list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { - h = (struct nf_conntrack_tuple_hash *) i; + hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]], + hnode) { if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 45baeb0e30f9..fe536b20408b 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -60,35 +60,36 @@ struct ct_iter_state { unsigned int bucket; }; -static struct list_head *ct_get_first(struct seq_file *seq) +static struct hlist_node *ct_get_first(struct seq_file *seq) { struct ct_iter_state *st = seq->private; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { - if (!list_empty(&nf_conntrack_hash[st->bucket])) - return nf_conntrack_hash[st->bucket].next; + if (!hlist_empty(&nf_conntrack_hash[st->bucket])) + return nf_conntrack_hash[st->bucket].first; } return NULL; } -static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head) +static struct hlist_node *ct_get_next(struct seq_file *seq, + struct hlist_node *head) { struct ct_iter_state *st = seq->private; head = head->next; - while (head == &nf_conntrack_hash[st->bucket]) { + while (head == NULL) { if (++st->bucket >= nf_conntrack_htable_size) return NULL; - head = nf_conntrack_hash[st->bucket].next; + head = nf_conntrack_hash[st->bucket].first; } return head; } -static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) { - struct list_head *head = ct_get_first(seq); + struct hlist_node *head = ct_get_first(seq); if (head) while (pos && (head = ct_get_next(seq, head))) -- cgit v1.2.3 From 330f7db5e578e1e298ba3a41748e5ea333a64a2b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:28:42 -0700 Subject: [NETFILTER]: nf_conntrack: remove 'ignore_conntrack' argument from nf_conntrack_find_get All callers pass NULL, this also doesn't seem very useful for modules. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_core.h | 3 +-- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 4 ++-- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 7 +++---- net/netfilter/nf_conntrack_netlink.c | 6 +++--- net/netfilter/nf_conntrack_pptp.c | 2 +- 7 files changed, 12 insertions(+), 14 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 6351948654b3..2fa3a1bbc7f2 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -58,8 +58,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, /* Find a connection corresponding to a tuple. */ extern struct nf_conntrack_tuple_hash * -nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack); +nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple); extern int __nf_conntrack_confirm(struct sk_buff **pskb); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 129a8cccf4a1..a103f597d446 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -334,7 +334,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) return -EINVAL; } - h = nf_conntrack_find_get(&tuple, NULL); + h = nf_conntrack_find_get(&tuple); if (h) { struct sockaddr_in sin; struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index f4fc657c1983..91fb277045ef 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -187,13 +187,13 @@ icmp_error_message(struct sk_buff *skb, *ctinfo = IP_CT_RELATED; - h = nf_conntrack_find_get(&innertuple, NULL); + h = nf_conntrack_find_get(&innertuple); if (!h) { /* Locally generated ICMPs will match inverted if they haven't been SNAT'ed yet */ /* FIXME: NAT code has to handle half-done double NAT --RR */ if (hooknum == NF_IP_LOCAL_OUT) - h = nf_conntrack_find_get(&origtuple, NULL); + h = nf_conntrack_find_get(&origtuple); if (!h) { DEBUGP("icmp_error_message: no match\n"); diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 8814b95b2326..a514661d25dd 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -193,7 +193,7 @@ icmpv6_error_message(struct sk_buff *skb, *ctinfo = IP_CT_RELATED; - h = nf_conntrack_find_get(&intuple, NULL); + h = nf_conntrack_find_get(&intuple); if (!h) { DEBUGP("icmpv6_error: no match\n"); return -NF_ACCEPT; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 992d0ef31fa3..8ed761cc0819 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -244,13 +244,12 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find); /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * -nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple, - const struct nf_conn *ignored_conntrack) +nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; read_lock_bh(&nf_conntrack_lock); - h = __nf_conntrack_find(tuple, ignored_conntrack); + h = __nf_conntrack_find(tuple, NULL); if (h) atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); read_unlock_bh(&nf_conntrack_lock); @@ -574,7 +573,7 @@ resolve_normal_ct(struct sk_buff *skb, } /* look for tuple match */ - h = nf_conntrack_find_get(&tuple, NULL); + h = nf_conntrack_find_get(&tuple); if (!h) { h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff); if (!h) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 0627559ca470..d310ec866194 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -689,7 +689,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(&tuple, NULL); + h = nf_conntrack_find_get(&tuple); if (!h) return -ENOENT; @@ -744,7 +744,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(&tuple, NULL); + h = nf_conntrack_find_get(&tuple); if (!h) return -ENOENT; @@ -1426,7 +1426,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) return err; /* Look for master conntrack of this expectation */ - h = nf_conntrack_find_get(&master_tuple, NULL); + h = nf_conntrack_find_get(&master_tuple); if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 115bcb5d5a7c..da36c48177e9 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -146,7 +146,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) DEBUGP("trying to timeout ct or exp for tuple "); NF_CT_DUMP_TUPLE(t); - h = nf_conntrack_find_get(t, NULL); + h = nf_conntrack_find_get(t); if (h) { sibling = nf_ct_tuplehash_to_ctrack(h); DEBUGP("setting timeout of conntrack %p to 0\n", sibling); -- cgit v1.2.3 From ac565e5fc104fe1842a87f2206fcfb7b6dda903d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:30:08 -0700 Subject: [NETFILTER]: nf_conntrack: export hash allocation/destruction functions Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 4 ++++ net/netfilter/nf_conntrack_core.c | 23 ++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index ef4a403878a3..8f2cbb965f3d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -172,6 +172,10 @@ static inline void nf_ct_put(struct nf_conn *ct) extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); extern void nf_ct_l3proto_module_put(unsigned short l3proto); +extern struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced); +extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, + int size); + extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 8ed761cc0819..f4c3039728dc 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -920,8 +920,7 @@ static int kill_all(struct nf_conn *i, void *data) return 1; } -static void free_conntrack_hash(struct hlist_head *hash, int vmalloced, - int size) +void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size) { if (vmalloced) vfree(hash); @@ -929,6 +928,7 @@ static void free_conntrack_hash(struct hlist_head *hash, int vmalloced, free_pages((unsigned long)hash, get_order(sizeof(struct hlist_head) * size)); } +EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); void nf_conntrack_flush(void) { @@ -962,14 +962,14 @@ void nf_conntrack_cleanup(void) kmem_cache_destroy(nf_conntrack_cachep); kmem_cache_destroy(nf_conntrack_expect_cachep); - free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, - nf_conntrack_htable_size); + nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, + nf_conntrack_htable_size); nf_conntrack_proto_fini(); nf_conntrack_helper_fini(); } -static struct hlist_head *alloc_hashtable(int *sizep, int *vmalloced) +struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) { struct hlist_head *hash; unsigned int size, i; @@ -992,6 +992,7 @@ static struct hlist_head *alloc_hashtable(int *sizep, int *vmalloced) return hash; } +EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable); int set_hashsize(const char *val, struct kernel_param *kp) { @@ -1009,7 +1010,7 @@ int set_hashsize(const char *val, struct kernel_param *kp) if (!hashsize) return -EINVAL; - hash = alloc_hashtable(&hashsize, &vmalloced); + hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced); if (!hash) return -ENOMEM; @@ -1037,7 +1038,7 @@ int set_hashsize(const char *val, struct kernel_param *kp) nf_conntrack_hash_rnd = rnd; write_unlock_bh(&nf_conntrack_lock); - free_conntrack_hash(old_hash, old_vmalloced, old_size); + nf_ct_free_hashtable(old_hash, old_vmalloced, old_size); return 0; } @@ -1066,8 +1067,8 @@ int __init nf_conntrack_init(void) * entries. */ max_factor = 4; } - nf_conntrack_hash = alloc_hashtable(&nf_conntrack_htable_size, - &nf_conntrack_vmalloc); + nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, + &nf_conntrack_vmalloc); if (!nf_conntrack_hash) { printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); goto err_out; @@ -1122,8 +1123,8 @@ out_free_expect_slab: err_free_conntrack_slab: kmem_cache_destroy(nf_conntrack_cachep); err_free_hash: - free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, - nf_conntrack_htable_size); + nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, + nf_conntrack_htable_size); err_out: return -ENOMEM; } -- cgit v1.2.3 From 53aba5979e1d964c0234816eda2316f1c2e7946d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:30:27 -0700 Subject: [NETFILTER]: nf_nat: use hlists for bysource hash Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_nat.h | 2 +- net/ipv4/netfilter/nf_nat_core.c | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index d0e5e436dc1b..6ae52f7c9f55 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -66,7 +66,7 @@ struct nf_conn; /* The structure embedded in the conntrack structure. */ struct nf_conn_nat { - struct list_head bysource; + struct hlist_node bysource; struct nf_nat_seq seq[IP_CT_DIR_MAX]; struct nf_conn *ct; union nf_conntrack_nat_help help; diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 04691edf50c2..f242ac61b3eb 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -44,8 +43,9 @@ static struct nf_conntrack_l3proto *l3proto = NULL; /* Calculated at init based on memory size */ static unsigned int nf_nat_htable_size; +static int nf_nat_vmalloced; -static struct list_head *bysource; +static struct hlist_head *bysource; #define MAX_IP_NAT_PROTO 256 static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]; @@ -153,9 +153,10 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, unsigned int h = hash_by_src(tuple); struct nf_conn_nat *nat; struct nf_conn *ct; + struct hlist_node *n; read_lock_bh(&nf_nat_lock); - list_for_each_entry(nat, &bysource[h], bysource) { + hlist_for_each_entry(nat, n, &bysource[h], bysource) { ct = nat->ct; if (same_src(ct, tuple)) { /* Copy source part from reply tuple. */ @@ -336,7 +337,7 @@ nf_nat_setup_info(struct nf_conn *ct, /* nf_conntrack_alter_reply might re-allocate exntension aera */ nat = nfct_nat(ct); nat->ct = ct; - list_add(&nat->bysource, &bysource[srchash]); + hlist_add_head(&nat->bysource, &bysource[srchash]); write_unlock_bh(&nf_nat_lock); } @@ -600,7 +601,7 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK); write_lock_bh(&nf_nat_lock); - list_del(&nat->bysource); + hlist_del(&nat->bysource); nat->ct = NULL; write_unlock_bh(&nf_nat_lock); } @@ -618,7 +619,7 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); write_lock_bh(&nf_nat_lock); - list_replace(&old_nat->bysource, &new_nat->bysource); + hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); new_nat->ct = ct; write_unlock_bh(&nf_nat_lock); } @@ -646,8 +647,8 @@ static int __init nf_nat_init(void) /* Leave them the same for the moment. */ nf_nat_htable_size = nf_conntrack_htable_size; - /* One vmalloc for both hash tables */ - bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); + bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, + &nf_nat_vmalloced); if (!bysource) { ret = -ENOMEM; goto cleanup_extend; @@ -663,7 +664,7 @@ static int __init nf_nat_init(void) write_unlock_bh(&nf_nat_lock); for (i = 0; i < nf_nat_htable_size; i++) { - INIT_LIST_HEAD(&bysource[i]); + INIT_HLIST_HEAD(&bysource[i]); } /* Initialize fake conntrack so that NAT will skip it */ @@ -693,7 +694,7 @@ static void __exit nf_nat_cleanup(void) { nf_ct_iterate_cleanup(&clean_nat, NULL); synchronize_rcu(); - vfree(bysource); + nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size); nf_ct_l3proto_put(l3proto); nf_ct_extend_unregister(&nat_extend); } -- cgit v1.2.3 From 6823645d608541c2c69e8a99454936e058c294e0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:30:49 -0700 Subject: [NETFILTER]: nf_conntrack_expect: function naming unification Currently there is a wild mix of nf_conntrack_expect_, nf_ct_exp_, expect_, exp_, ... Consistently use nf_ct_ as prefix for exported functions. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_core.h | 2 +- include/net/netfilter/nf_conntrack_ecache.h | 17 ++- include/net/netfilter/nf_conntrack_expect.h | 28 ++--- .../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 6 +- net/ipv4/netfilter/nf_nat_amanda.c | 4 +- net/ipv4/netfilter/nf_nat_ftp.c | 4 +- net/ipv4/netfilter/nf_nat_h323.c | 26 ++--- net/ipv4/netfilter/nf_nat_irc.c | 4 +- net/ipv4/netfilter/nf_nat_pptp.c | 6 +- net/ipv4/netfilter/nf_nat_sip.c | 4 +- net/ipv4/netfilter/nf_nat_tftp.c | 2 +- net/netfilter/nf_conntrack_amanda.c | 11 +- net/netfilter/nf_conntrack_core.c | 12 +- net/netfilter/nf_conntrack_ecache.c | 16 +-- net/netfilter/nf_conntrack_expect.c | 93 +++++++-------- net/netfilter/nf_conntrack_ftp.c | 6 +- net/netfilter/nf_conntrack_h323_main.c | 127 ++++++++++----------- net/netfilter/nf_conntrack_helper.c | 4 +- net/netfilter/nf_conntrack_irc.c | 12 +- net/netfilter/nf_conntrack_netbios_ns.c | 6 +- net/netfilter/nf_conntrack_netlink.c | 40 +++---- net/netfilter/nf_conntrack_pptp.c | 44 +++---- net/netfilter/nf_conntrack_sane.c | 12 +- net/netfilter/nf_conntrack_sip.c | 12 +- net/netfilter/nf_conntrack_tftp.c | 12 +- 25 files changed, 251 insertions(+), 259 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 2fa3a1bbc7f2..a18f79c80db8 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -84,7 +84,7 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l4proto *proto); extern struct hlist_head *nf_conntrack_hash; -extern struct list_head nf_conntrack_expect_list; +extern struct list_head nf_ct_expect_list; extern rwlock_t nf_conntrack_lock ; extern struct hlist_head unconfirmed; diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 811c9073c532..f0b9078235c9 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -49,15 +49,15 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event, atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); } -extern struct atomic_notifier_head nf_conntrack_expect_chain; -extern int nf_conntrack_expect_register_notifier(struct notifier_block *nb); -extern int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb); +extern struct atomic_notifier_head nf_ct_expect_chain; +extern int nf_ct_expect_register_notifier(struct notifier_block *nb); +extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); static inline void -nf_conntrack_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) +nf_ct_expect_event(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp) { - atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp); + atomic_notifier_call_chain(&nf_ct_expect_chain, event, exp); } #else /* CONFIG_NF_CONNTRACK_EVENTS */ @@ -67,9 +67,8 @@ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, static inline void nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} -static inline void -nf_conntrack_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) {} +static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp) {} static inline void nf_ct_event_cache_flush(void) {} #endif /* CONFIG_NF_CONNTRACK_EVENTS */ diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 173c7c1eff23..c0b1d1fb23e1 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -6,8 +6,8 @@ #define _NF_CONNTRACK_EXPECT_H #include -extern struct list_head nf_conntrack_expect_list; -extern struct kmem_cache *nf_conntrack_expect_cachep; +extern struct list_head nf_ct_expect_list; +extern struct kmem_cache *nf_ct_expect_cachep; extern const struct file_operations exp_file_ops; struct nf_conntrack_expect @@ -54,27 +54,27 @@ struct nf_conntrack_expect struct nf_conntrack_expect * -__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); +__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * -nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple); +nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * -find_expectation(const struct nf_conntrack_tuple *tuple); +nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple); void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); void nf_ct_remove_expectations(struct nf_conn *ct); -void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp); +void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); /* Allocate space for an expectation: this is mandatory before calling - nf_conntrack_expect_related. You will have to call put afterwards. */ -struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me); -void nf_conntrack_expect_init(struct nf_conntrack_expect *, int, - union nf_conntrack_address *, - union nf_conntrack_address *, - u_int8_t, __be16 *, __be16 *); -void nf_conntrack_expect_put(struct nf_conntrack_expect *exp); -int nf_conntrack_expect_related(struct nf_conntrack_expect *expect); + nf_ct_expect_related. You will have to call put afterwards. */ +struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me); +void nf_ct_expect_init(struct nf_conntrack_expect *, int, + union nf_conntrack_address *, + union nf_conntrack_address *, + u_int8_t, __be16 *, __be16 *); +void nf_ct_expect_put(struct nf_conntrack_expect *exp); +int nf_ct_expect_related(struct nf_conntrack_expect *expect); #endif /*_NF_CONNTRACK_EXPECT_H*/ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 888f27fd884f..12d6a6327b63 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -209,7 +209,7 @@ static const struct file_operations ct_file_ops = { /* expects */ static void *exp_seq_start(struct seq_file *s, loff_t *pos) { - struct list_head *e = &nf_conntrack_expect_list; + struct list_head *e = &nf_ct_expect_list; loff_t i; /* strange seq_file api calls stop even if we fail, @@ -221,7 +221,7 @@ static void *exp_seq_start(struct seq_file *s, loff_t *pos) for (i = 0; i <= *pos; i++) { e = e->next; - if (e == &nf_conntrack_expect_list) + if (e == &nf_ct_expect_list) return NULL; } return e; @@ -234,7 +234,7 @@ static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) ++*pos; e = e->next; - if (e == &nf_conntrack_expect_list) + if (e == &nf_ct_expect_list) return NULL; return e; diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index 0f17098917bc..bd93a1d71052 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c @@ -45,7 +45,7 @@ static unsigned int help(struct sk_buff **pskb, /* Try to get same port: if not, try to change it. */ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { exp->tuple.dst.u.tcp.port = htons(port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -57,7 +57,7 @@ static unsigned int help(struct sk_buff **pskb, matchoff, matchlen, buffer, strlen(buffer)); if (ret != NF_ACCEPT) - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return ret; } diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index e6bc8e5a72f1..cae4b460aee1 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c @@ -131,7 +131,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, /* Try to get same port: if not, try to change it. */ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { exp->tuple.dst.u.tcp.port = htons(port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -139,7 +139,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, return NF_DROP; if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return NF_DROP; } return NF_ACCEPT; diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index c5d2a2d690b8..3d760dd657c7 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -237,12 +237,12 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); nated_port != 0; nated_port += 2) { rtp_exp->tuple.dst.u.udp.port = htons(nated_port); - if (nf_conntrack_expect_related(rtp_exp) == 0) { + if (nf_ct_expect_related(rtp_exp) == 0) { rtcp_exp->tuple.dst.u.udp.port = htons(nated_port + 1); - if (nf_conntrack_expect_related(rtcp_exp) == 0) + if (nf_ct_expect_related(rtcp_exp) == 0) break; - nf_conntrack_unexpect_related(rtp_exp); + nf_ct_unexpect_related(rtp_exp); } } @@ -261,8 +261,8 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, info->rtp_port[i][dir] = rtp_port; info->rtp_port[i][!dir] = htons(nated_port); } else { - nf_conntrack_unexpect_related(rtp_exp); - nf_conntrack_unexpect_related(rtcp_exp); + nf_ct_unexpect_related(rtp_exp); + nf_ct_unexpect_related(rtcp_exp); return -1; } @@ -299,7 +299,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, /* Try to get same port: if not, try to change it. */ for (; nated_port != 0; nated_port++) { exp->tuple.dst.u.tcp.port = htons(nated_port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -313,7 +313,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, if (set_h245_addr(pskb, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, htons(nated_port)) < 0) { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return -1; } @@ -347,7 +347,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, /* Try to get same port: if not, try to change it. */ for (; nated_port != 0; nated_port++) { exp->tuple.dst.u.tcp.port = htons(nated_port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -365,7 +365,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, info->sig_port[dir] = port; info->sig_port[!dir] = htons(nated_port); } else { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return -1; } @@ -433,7 +433,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, /* Try to get same port: if not, try to change it. */ for (; nated_port != 0; nated_port++) { exp->tuple.dst.u.tcp.port = htons(nated_port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -460,7 +460,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, info->sig_port[!dir]); } } else { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return -1; } @@ -517,7 +517,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, /* Try to get same port: if not, try to change it. */ for (nated_port = ntohs(port); nated_port != 0; nated_port++) { exp->tuple.dst.u.tcp.port = htons(nated_port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -531,7 +531,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, if (!set_h225_addr(pskb, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, htons(nated_port)) == 0) { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return -1; } diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index 9b8c0daea744..db7fbf66fec0 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c @@ -55,7 +55,7 @@ static unsigned int help(struct sk_buff **pskb, /* Try to get same port: if not, try to change it. */ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { exp->tuple.dst.u.tcp.port = htons(port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -71,7 +71,7 @@ static unsigned int help(struct sk_buff **pskb, matchoff, matchlen, buffer, strlen(buffer)); if (ret != NF_ACCEPT) - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return ret; } diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index a66888749ceb..deb80ae2831e 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -81,10 +81,10 @@ static void pptp_nat_expected(struct nf_conn *ct, DEBUGP("trying to unexpect other dir: "); NF_CT_DUMP_TUPLE(&t); - other_exp = nf_conntrack_expect_find_get(&t); + other_exp = nf_ct_expect_find_get(&t); if (other_exp) { - nf_conntrack_unexpect_related(other_exp); - nf_conntrack_expect_put(other_exp); + nf_ct_unexpect_related(other_exp); + nf_ct_expect_put(other_exp); DEBUGP("success\n"); } else { DEBUGP("not found!\n"); diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index a32d746c4592..940cdfc429de 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -278,7 +278,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, /* Try to get same port: if not, try to change it. */ for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) { exp->tuple.dst.u.udp.port = htons(port); - if (nf_conntrack_expect_related(exp) == 0) + if (nf_ct_expect_related(exp) == 0) break; } @@ -286,7 +286,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, return NF_DROP; if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); return NF_DROP; } return NF_ACCEPT; diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 2566b79de224..04dfeaefec02 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c @@ -30,7 +30,7 @@ static unsigned int help(struct sk_buff **pskb, = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; exp->dir = IP_CT_DIR_REPLY; exp->expectfn = nf_nat_follow_master; - if (nf_conntrack_expect_related(exp) != 0) + if (nf_ct_expect_related(exp) != 0) return NF_DROP; return NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 0568f2e86b59..d21359e6c14c 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -142,23 +142,22 @@ static int amanda_help(struct sk_buff **pskb, if (port == 0 || len > 5) break; - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - nf_conntrack_expect_init(exp, family, - &tuple->src.u3, &tuple->dst.u3, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, + IPPROTO_TCP, NULL, &port); nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); if (nf_nat_amanda && ct->status & IPS_NAT_MASK) ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, len, exp); - else if (nf_conntrack_expect_related(exp) != 0) + else if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } out: diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f4c3039728dc..793f12ff168b 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -494,7 +494,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, } write_lock_bh(&nf_conntrack_lock); - exp = find_expectation(tuple); + exp = nf_ct_find_expectation(tuple); if (exp) { DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", conntrack, exp); @@ -544,7 +544,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, if (exp) { if (exp->expectfn) exp->expectfn(conntrack, exp); - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL]; @@ -961,7 +961,7 @@ void nf_conntrack_cleanup(void) rcu_assign_pointer(nf_ct_destroy, NULL); kmem_cache_destroy(nf_conntrack_cachep); - kmem_cache_destroy(nf_conntrack_expect_cachep); + kmem_cache_destroy(nf_ct_expect_cachep); nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, nf_conntrack_htable_size); @@ -1088,10 +1088,10 @@ int __init nf_conntrack_init(void) goto err_free_hash; } - nf_conntrack_expect_cachep = kmem_cache_create("nf_conntrack_expect", + nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", sizeof(struct nf_conntrack_expect), 0, 0, NULL, NULL); - if (!nf_conntrack_expect_cachep) { + if (!nf_ct_expect_cachep) { printk(KERN_ERR "Unable to create nf_expect slab cache\n"); goto err_free_conntrack_slab; } @@ -1119,7 +1119,7 @@ int __init nf_conntrack_init(void) out_fini_proto: nf_conntrack_proto_fini(); out_free_expect_slab: - kmem_cache_destroy(nf_conntrack_expect_cachep); + kmem_cache_destroy(nf_ct_expect_cachep); err_free_conntrack_slab: kmem_cache_destroy(nf_conntrack_cachep); err_free_hash: diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 6bd421df2dbc..83c41ac3505b 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -26,8 +26,8 @@ ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); EXPORT_SYMBOL_GPL(nf_conntrack_chain); -ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); -EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain); +ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain); +EXPORT_SYMBOL_GPL(nf_ct_expect_chain); DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); @@ -103,14 +103,14 @@ int nf_conntrack_unregister_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); -int nf_conntrack_expect_register_notifier(struct notifier_block *nb) +int nf_ct_expect_register_notifier(struct notifier_block *nb) { - return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); + return atomic_notifier_chain_register(&nf_ct_expect_chain, nb); } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_register_notifier); +EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); -int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) +int nf_ct_expect_unregister_notifier(struct notifier_block *nb) { - return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, nb); + return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb); } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_unregister_notifier); +EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 504fb6c083f9..4130ea662c48 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -26,11 +26,11 @@ #include #include -LIST_HEAD(nf_conntrack_expect_list); -EXPORT_SYMBOL_GPL(nf_conntrack_expect_list); +LIST_HEAD(nf_ct_expect_list); +EXPORT_SYMBOL_GPL(nf_ct_expect_list); -struct kmem_cache *nf_conntrack_expect_cachep __read_mostly; -static unsigned int nf_conntrack_expect_next_id; +struct kmem_cache *nf_ct_expect_cachep __read_mostly; +static unsigned int nf_ct_expect_next_id; /* nf_conntrack_expect helper functions */ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) @@ -43,57 +43,57 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) list_del(&exp->list); NF_CT_STAT_INC(expect_delete); master_help->expecting--; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); -static void expectation_timed_out(unsigned long ul_expect) +static void nf_ct_expectation_timed_out(unsigned long ul_expect) { struct nf_conntrack_expect *exp = (void *)ul_expect; write_lock_bh(&nf_conntrack_lock); nf_ct_unlink_expect(exp); write_unlock_bh(&nf_conntrack_lock); - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } struct nf_conntrack_expect * -__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) +__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; - list_for_each_entry(i, &nf_conntrack_expect_list, list) { + list_for_each_entry(i, &nf_ct_expect_list, list) { if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; } return NULL; } -EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find); +EXPORT_SYMBOL_GPL(__nf_ct_expect_find); /* Just find a expectation corresponding to a tuple. */ struct nf_conntrack_expect * -nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple) +nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; read_lock_bh(&nf_conntrack_lock); - i = __nf_conntrack_expect_find(tuple); + i = __nf_ct_expect_find(tuple); if (i) atomic_inc(&i->use); read_unlock_bh(&nf_conntrack_lock); return i; } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get); +EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); /* If an expectation for this connection is found, it gets delete from * global list then returned. */ struct nf_conntrack_expect * -find_expectation(const struct nf_conntrack_tuple *tuple) +nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *exp; - exp = __nf_conntrack_expect_find(tuple); + exp = __nf_ct_expect_find(tuple); if (!exp) return NULL; @@ -126,10 +126,10 @@ void nf_ct_remove_expectations(struct nf_conn *ct) if (!help || help->expecting == 0) return; - list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { + list_for_each_entry_safe(i, tmp, &nf_ct_expect_list, list) { if (i->master == ct && del_timer(&i->timeout)) { nf_ct_unlink_expect(i); - nf_conntrack_expect_put(i); + nf_ct_expect_put(i); } } } @@ -172,32 +172,32 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, } /* Generally a bad idea to call this: could have matched already. */ -void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp) +void nf_ct_unexpect_related(struct nf_conntrack_expect *exp) { struct nf_conntrack_expect *i; write_lock_bh(&nf_conntrack_lock); /* choose the oldest expectation to evict */ - list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { + list_for_each_entry_reverse(i, &nf_ct_expect_list, list) { if (expect_matches(i, exp) && del_timer(&i->timeout)) { nf_ct_unlink_expect(i); write_unlock_bh(&nf_conntrack_lock); - nf_conntrack_expect_put(i); + nf_ct_expect_put(i); return; } } write_unlock_bh(&nf_conntrack_lock); } -EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related); +EXPORT_SYMBOL_GPL(nf_ct_unexpect_related); /* We don't increase the master conntrack refcount for non-fulfilled * conntracks. During the conntrack destruction, the expectations are * always killed before the conntrack itself */ -struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me) +struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me) { struct nf_conntrack_expect *new; - new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC); + new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC); if (!new) return NULL; @@ -205,12 +205,12 @@ struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me) atomic_set(&new->use, 1); return new; } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc); +EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); -void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, - union nf_conntrack_address *saddr, - union nf_conntrack_address *daddr, - u_int8_t proto, __be16 *src, __be16 *dst) +void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, + union nf_conntrack_address *saddr, + union nf_conntrack_address *daddr, + u_int8_t proto, __be16 *src, __be16 *dst) { int len; @@ -273,28 +273,29 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, exp->mask.dst.u.all = 0; } } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_init); +EXPORT_SYMBOL_GPL(nf_ct_expect_init); -void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) +void nf_ct_expect_put(struct nf_conntrack_expect *exp) { if (atomic_dec_and_test(&exp->use)) - kmem_cache_free(nf_conntrack_expect_cachep, exp); + kmem_cache_free(nf_ct_expect_cachep, exp); } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_put); +EXPORT_SYMBOL_GPL(nf_ct_expect_put); -static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) +static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) { struct nf_conn_help *master_help = nfct_help(exp->master); atomic_inc(&exp->use); master_help->expecting++; - list_add(&exp->list, &nf_conntrack_expect_list); + list_add(&exp->list, &nf_ct_expect_list); - setup_timer(&exp->timeout, expectation_timed_out, (unsigned long)exp); + setup_timer(&exp->timeout, nf_ct_expectation_timed_out, + (unsigned long)exp); exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; add_timer(&exp->timeout); - exp->id = ++nf_conntrack_expect_next_id; + exp->id = ++nf_ct_expect_next_id; atomic_inc(&exp->use); NF_CT_STAT_INC(expect_create); } @@ -304,11 +305,11 @@ static void evict_oldest_expect(struct nf_conn *master) { struct nf_conntrack_expect *i; - list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { + list_for_each_entry_reverse(i, &nf_ct_expect_list, list) { if (i->master == master) { if (del_timer(&i->timeout)) { nf_ct_unlink_expect(i); - nf_conntrack_expect_put(i); + nf_ct_expect_put(i); } break; } @@ -327,7 +328,7 @@ static inline int refresh_timer(struct nf_conntrack_expect *i) return 1; } -int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) +int nf_ct_expect_related(struct nf_conntrack_expect *expect) { struct nf_conntrack_expect *i; struct nf_conn *master = expect->master; @@ -341,7 +342,7 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) ret = -ESHUTDOWN; goto out; } - list_for_each_entry(i, &nf_conntrack_expect_list, list) { + list_for_each_entry(i, &nf_ct_expect_list, list) { if (expect_matches(i, expect)) { /* Refresh timer: if it's dying, ignore.. */ if (refresh_timer(i)) { @@ -358,19 +359,19 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) master_help->expecting >= master_help->helper->max_expected) evict_oldest_expect(master); - nf_conntrack_expect_insert(expect); - nf_conntrack_expect_event(IPEXP_NEW, expect); + nf_ct_expect_insert(expect); + nf_ct_expect_event(IPEXP_NEW, expect); ret = 0; out: write_unlock_bh(&nf_conntrack_lock); return ret; } -EXPORT_SYMBOL_GPL(nf_conntrack_expect_related); +EXPORT_SYMBOL_GPL(nf_ct_expect_related); #ifdef CONFIG_PROC_FS static void *exp_seq_start(struct seq_file *s, loff_t *pos) { - struct list_head *e = &nf_conntrack_expect_list; + struct list_head *e = &nf_ct_expect_list; loff_t i; /* strange seq_file api calls stop even if we fail, @@ -382,7 +383,7 @@ static void *exp_seq_start(struct seq_file *s, loff_t *pos) for (i = 0; i <= *pos; i++) { e = e->next; - if (e == &nf_conntrack_expect_list) + if (e == &nf_ct_expect_list) return NULL; } return e; @@ -395,7 +396,7 @@ static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) ++*pos; e = e->next; - if (e == &nf_conntrack_expect_list) + if (e == &nf_ct_expect_list) return NULL; return e; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 82db2aa53bfc..5efe65d4b3c0 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -445,7 +445,7 @@ static int help(struct sk_buff **pskb, (int)matchlen, fb_ptr + matchoff, matchlen, ntohl(th->seq) + matchoff); - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; @@ -523,14 +523,14 @@ static int help(struct sk_buff **pskb, matchoff, matchlen, exp); else { /* Can't expect this? Best to drop packet now. */ - if (nf_conntrack_expect_related(exp) != 0) + if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; else ret = NF_ACCEPT; } out_put_expect: - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); out_update_nl: /* Now if this ends in \n, update ftp info. Seq may have been diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a1b95acad297..61ae90fb328a 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -282,22 +282,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, rtcp_port = htons(ntohs(port) + 1); /* Create expect for RTP */ - if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, - &ct->tuplehash[!dir].tuple.dst.u3, - IPPROTO_UDP, NULL, &rtp_port); + nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + IPPROTO_UDP, NULL, &rtp_port); /* Create expect for RTCP */ - if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) { - nf_conntrack_expect_put(rtp_exp); + if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) { + nf_ct_expect_put(rtp_exp); return -1; } - nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, - &ct->tuplehash[!dir].tuple.dst.u3, - IPPROTO_UDP, NULL, &rtcp_port); + nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + IPPROTO_UDP, NULL, &rtcp_port); if (memcmp(&ct->tuplehash[dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, @@ -308,22 +308,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, taddr, port, rtp_port, rtp_exp, rtcp_exp); } else { /* Conntrack only */ - if (nf_conntrack_expect_related(rtp_exp) == 0) { - if (nf_conntrack_expect_related(rtcp_exp) == 0) { + if (nf_ct_expect_related(rtp_exp) == 0) { + if (nf_ct_expect_related(rtcp_exp) == 0) { DEBUGP("nf_ct_h323: expect RTP "); NF_CT_DUMP_TUPLE(&rtp_exp->tuple); DEBUGP("nf_ct_h323: expect RTCP "); NF_CT_DUMP_TUPLE(&rtcp_exp->tuple); } else { - nf_conntrack_unexpect_related(rtp_exp); + nf_ct_unexpect_related(rtp_exp); ret = -1; } } else ret = -1; } - nf_conntrack_expect_put(rtp_exp); - nf_conntrack_expect_put(rtcp_exp); + nf_ct_expect_put(rtp_exp); + nf_ct_expect_put(rtcp_exp); return ret; } @@ -349,12 +349,12 @@ static int expect_t120(struct sk_buff **pskb, return 0; /* Create expect for T.120 connections */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, - &ct->tuplehash[!dir].tuple.dst.u3, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + IPPROTO_TCP, NULL, &port); exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */ if (memcmp(&ct->tuplehash[dir].tuple.src.u3, @@ -366,14 +366,14 @@ static int expect_t120(struct sk_buff **pskb, ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, port, exp); } else { /* Conntrack only */ - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_h323: expect T.120 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; } - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -684,12 +684,12 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, return 0; /* Create expect for h245 connection */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, - &ct->tuplehash[!dir].tuple.dst.u3, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + IPPROTO_TCP, NULL, &port); exp->helper = &nf_conntrack_helper_h245; if (memcmp(&ct->tuplehash[dir].tuple.src.u3, @@ -701,14 +701,14 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, port, exp); } else { /* Conntrack only */ - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_q931: expect H.245 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; } - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -796,11 +796,11 @@ static int expect_callforwarding(struct sk_buff **pskb, } /* Create expect for the second call leg */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, &addr, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, &addr, + IPPROTO_TCP, NULL, &port); exp->helper = nf_conntrack_helper_q931; if (memcmp(&ct->tuplehash[dir].tuple.src.u3, @@ -812,14 +812,14 @@ static int expect_callforwarding(struct sk_buff **pskb, ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, taddr, port, exp); } else { /* Conntrack only */ - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_q931: expect Call Forwarding "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; } - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -1225,7 +1225,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, tuple.dst.u.tcp.port = port; tuple.dst.protonum = IPPROTO_TCP; - exp = __nf_conntrack_expect_find(&tuple); + exp = __nf_ct_expect_find(&tuple); if (exp && exp->master == ct) return exp; return NULL; @@ -1271,14 +1271,13 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, return 0; /* Create expect for Q.931 */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - gkrouted_only ? /* only accept calls from GK? */ - &ct->tuplehash[!dir].tuple.src.u3 : - NULL, - &ct->tuplehash[!dir].tuple.dst.u3, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + gkrouted_only ? /* only accept calls from GK? */ + &ct->tuplehash[!dir].tuple.src.u3 : NULL, + &ct->tuplehash[!dir].tuple.dst.u3, + IPPROTO_TCP, NULL, &port); exp->helper = nf_conntrack_helper_q931; exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ @@ -1286,7 +1285,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); } else { /* Conntrack only */ - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); @@ -1296,7 +1295,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, ret = -1; } - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -1343,20 +1342,20 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, return 0; /* Need new expect */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, &addr, - IPPROTO_UDP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, &addr, + IPPROTO_UDP, NULL, &port); exp->helper = nf_conntrack_helper_ras; - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_ras: expect RAS "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -1548,21 +1547,21 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, } /* Need new expect */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, &addr, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, &addr, + IPPROTO_TCP, NULL, &port); exp->flags = NF_CT_EXPECT_PERMANENT; exp->helper = nf_conntrack_helper_q931; - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } @@ -1601,21 +1600,21 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, return 0; /* Need new expect for call signal */ - if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) + if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; - nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, - &ct->tuplehash[!dir].tuple.src.u3, &addr, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, + &ct->tuplehash[!dir].tuple.src.u3, &addr, + IPPROTO_TCP, NULL, &port); exp->flags = NF_CT_EXPECT_PERMANENT; exp->helper = nf_conntrack_helper_q931; - if (nf_conntrack_expect_related(exp) == 0) { + if (nf_ct_expect_related(exp) == 0) { DEBUGP("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); /* Ignore rasAddress */ diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 3fc6e9f0de1a..89a5f7333d38 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -123,12 +123,12 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) list_del(&me->list); /* Get rid of expectations */ - list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { + list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { struct nf_conn_help *help = nfct_help(exp->master); if ((help->helper == me || exp->helper == me) && del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } } diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 43ccd0e2e8ae..79da93e4396b 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -184,16 +184,16 @@ static int help(struct sk_buff **pskb, unsigned int protoff, continue; } - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[!dir].tuple; port = htons(dcc_port); - nf_conntrack_expect_init(exp, tuple->src.l3num, - NULL, &tuple->dst.u3, - IPPROTO_TCP, NULL, &port); + nf_ct_expect_init(exp, tuple->src.l3num, + NULL, &tuple->dst.u3, + IPPROTO_TCP, NULL, &port); nf_nat_irc = rcu_dereference(nf_nat_irc_hook); if (nf_nat_irc && ct->status & IPS_NAT_MASK) @@ -201,9 +201,9 @@ static int help(struct sk_buff **pskb, unsigned int protoff, addr_beg_p - ib_ptr, addr_end_p - addr_beg_p, exp); - else if (nf_conntrack_expect_related(exp) != 0) + else if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); goto out; } } diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 1093478cc007..ea585c789a83 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -74,7 +74,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, if (mask == 0) goto out; - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) goto out; @@ -91,8 +91,8 @@ static int help(struct sk_buff **pskb, unsigned int protoff, exp->flags = NF_CT_EXPECT_PERMANENT; exp->helper = NULL; - nf_conntrack_expect_related(exp); - nf_conntrack_expect_put(exp); + nf_ct_expect_related(exp); + nf_ct_expect_put(exp); nf_ct_refresh(ct, *pskb, timeout * HZ); out: diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d310ec866194..954cc58b9d04 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1239,7 +1239,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) u_int8_t l3proto = nfmsg->nfgen_family; read_lock_bh(&nf_conntrack_lock); - list_for_each_prev(i, &nf_conntrack_expect_list) { + list_for_each_prev(i, &nf_ct_expect_list) { exp = (struct nf_conntrack_expect *) i; if (l3proto && exp->tuple.src.l3num != l3proto) continue; @@ -1291,14 +1291,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = nf_conntrack_expect_find_get(&tuple); + exp = nf_ct_expect_find_get(&tuple); if (!exp) return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); if (exp->id != ntohl(id)) { - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return -ENOENT; } } @@ -1314,14 +1314,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err <= 0) goto free; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); free: kfree_skb(skb2); out: - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return err; } @@ -1346,23 +1346,23 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = nf_conntrack_expect_find_get(&tuple); + exp = nf_ct_expect_find_get(&tuple); if (!exp) return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); if (exp->id != ntohl(id)) { - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return -ENOENT; } } /* after list removal, usage count == 1 */ - nf_conntrack_unexpect_related(exp); + nf_ct_unexpect_related(exp); /* have to put what we 'get' above. * after this line usage count == 0 */ - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } else if (cda[CTA_EXPECT_HELP_NAME-1]) { char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); @@ -1373,24 +1373,22 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, write_unlock_bh(&nf_conntrack_lock); return -EINVAL; } - list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, - list) { + list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { struct nf_conn_help *m_help = nfct_help(exp->master); if (m_help->helper == h && del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } } write_unlock_bh(&nf_conntrack_lock); } else { /* This basically means we have to flush everything*/ write_lock_bh(&nf_conntrack_lock); - list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, - list) { + list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { if (del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); } } write_unlock_bh(&nf_conntrack_lock); @@ -1438,7 +1436,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) goto out; } - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (!exp) { err = -ENOMEM; goto out; @@ -1451,8 +1449,8 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple)); - err = nf_conntrack_expect_related(exp); - nf_conntrack_expect_put(exp); + err = nf_ct_expect_related(exp); + nf_ct_expect_put(exp); out: nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); @@ -1482,7 +1480,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, return err; write_lock_bh(&nf_conntrack_lock); - exp = __nf_conntrack_expect_find(&tuple); + exp = __nf_ct_expect_find(&tuple); if (!exp) { write_unlock_bh(&nf_conntrack_lock); @@ -1572,7 +1570,7 @@ static int __init ctnetlink_init(void) goto err_unreg_exp_subsys; } - ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp); + ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); if (ret < 0) { printk("ctnetlink_init: cannot expect register notifier.\n"); goto err_unreg_notifier; @@ -1598,7 +1596,7 @@ static void __exit ctnetlink_exit(void) printk("ctnetlink: unregistering from nfnetlink.\n"); #ifdef CONFIG_NF_CONNTRACK_EVENTS - nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); + nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); nf_conntrack_unregister_notifier(&ctnl_notifier); #endif diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index da36c48177e9..916e106d36bc 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -124,12 +124,12 @@ static void pptp_expectfn(struct nf_conn *ct, DEBUGP("trying to unexpect other dir: "); NF_CT_DUMP_TUPLE(&inv_t); - exp_other = nf_conntrack_expect_find_get(&inv_t); + exp_other = nf_ct_expect_find_get(&inv_t); if (exp_other) { /* delete other expectation. */ DEBUGP("found\n"); - nf_conntrack_unexpect_related(exp_other); - nf_conntrack_expect_put(exp_other); + nf_ct_unexpect_related(exp_other); + nf_ct_expect_put(exp_other); } else { DEBUGP("not found\n"); } @@ -157,11 +157,11 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) nf_ct_put(sibling); return 1; } else { - exp = nf_conntrack_expect_find_get(t); + exp = nf_ct_expect_find_get(t); if (exp) { DEBUGP("unexpect_related of expect %p\n", exp); - nf_conntrack_unexpect_related(exp); - nf_conntrack_expect_put(exp); + nf_ct_unexpect_related(exp); + nf_ct_expect_put(exp); return 1; } } @@ -201,36 +201,36 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) int ret = 1; typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre; - exp_orig = nf_conntrack_expect_alloc(ct); + exp_orig = nf_ct_expect_alloc(ct); if (exp_orig == NULL) goto out; - exp_reply = nf_conntrack_expect_alloc(ct); + exp_reply = nf_ct_expect_alloc(ct); if (exp_reply == NULL) goto out_put_orig; /* original direction, PNS->PAC */ dir = IP_CT_DIR_ORIGINAL; - nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num, - &ct->tuplehash[dir].tuple.src.u3, - &ct->tuplehash[dir].tuple.dst.u3, - IPPROTO_GRE, &peer_callid, &callid); + nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num, + &ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[dir].tuple.dst.u3, + IPPROTO_GRE, &peer_callid, &callid); exp_orig->expectfn = pptp_expectfn; /* reply direction, PAC->PNS */ dir = IP_CT_DIR_REPLY; - nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num, - &ct->tuplehash[dir].tuple.src.u3, - &ct->tuplehash[dir].tuple.dst.u3, - IPPROTO_GRE, &callid, &peer_callid); + nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num, + &ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[dir].tuple.dst.u3, + IPPROTO_GRE, &callid, &peer_callid); exp_reply->expectfn = pptp_expectfn; nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre); if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK) nf_nat_pptp_exp_gre(exp_orig, exp_reply); - if (nf_conntrack_expect_related(exp_orig) != 0) + if (nf_ct_expect_related(exp_orig) != 0) goto out_put_both; - if (nf_conntrack_expect_related(exp_reply) != 0) + if (nf_ct_expect_related(exp_reply) != 0) goto out_unexpect_orig; /* Add GRE keymap entries */ @@ -243,16 +243,16 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) ret = 0; out_put_both: - nf_conntrack_expect_put(exp_reply); + nf_ct_expect_put(exp_reply); out_put_orig: - nf_conntrack_expect_put(exp_orig); + nf_ct_expect_put(exp_orig); out: return ret; out_unexpect_both: - nf_conntrack_unexpect_related(exp_reply); + nf_ct_unexpect_related(exp_reply); out_unexpect_orig: - nf_conntrack_unexpect_related(exp_orig); + nf_ct_unexpect_related(exp_orig); goto out_put_both; } diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index eb2d1dc46d45..28ed303c565b 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -141,27 +141,25 @@ static int help(struct sk_buff **pskb, if (reply->zero != 0) goto out; - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - nf_conntrack_expect_init(exp, family, - &tuple->src.u3, &tuple->dst.u3, - IPPROTO_TCP, - NULL, &reply->port); + nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, + IPPROTO_TCP, NULL, &reply->port); DEBUGP("nf_ct_sane: expect: "); NF_CT_DUMP_TUPLE(&exp->tuple); NF_CT_DUMP_TUPLE(&exp->mask); /* Can't expect this? Best to drop packet now. */ - if (nf_conntrack_expect_related(exp) != 0) + if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); out: spin_unlock_bh(&nf_sane_lock); diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1b5c6c1055f7..1f17f8040cd2 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -378,23 +378,23 @@ static int set_expected_rtp(struct sk_buff **pskb, int ret; typeof(nf_nat_sdp_hook) nf_nat_sdp; - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) return NF_DROP; - nf_conntrack_expect_init(exp, family, - &ct->tuplehash[!dir].tuple.src.u3, addr, - IPPROTO_UDP, NULL, &port); + nf_ct_expect_init(exp, family, + &ct->tuplehash[!dir].tuple.src.u3, addr, + IPPROTO_UDP, NULL, &port); nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); if (nf_nat_sdp && ct->status & IPS_NAT_MASK) ret = nf_nat_sdp(pskb, ctinfo, exp, dptr); else { - if (nf_conntrack_expect_related(exp) != 0) + if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; else ret = NF_ACCEPT; } - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); return ret; } diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 37c4542e3112..53d57b4c0de7 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -66,14 +66,12 @@ static int tftp_help(struct sk_buff **pskb, NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); - exp = nf_conntrack_expect_alloc(ct); + exp = nf_ct_expect_alloc(ct); if (exp == NULL) return NF_DROP; tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; - nf_conntrack_expect_init(exp, family, - &tuple->src.u3, &tuple->dst.u3, - IPPROTO_UDP, - NULL, &tuple->dst.u.udp.port); + nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, + IPPROTO_UDP, NULL, &tuple->dst.u.udp.port); DEBUGP("expect: "); NF_CT_DUMP_TUPLE(&exp->tuple); @@ -82,9 +80,9 @@ static int tftp_help(struct sk_buff **pskb, nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); if (nf_nat_tftp && ct->status & IPS_NAT_MASK) ret = nf_nat_tftp(pskb, ctinfo, exp); - else if (nf_conntrack_expect_related(exp) != 0) + else if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; - nf_conntrack_expect_put(exp); + nf_ct_expect_put(exp); break; case TFTP_OPCODE_DATA: case TFTP_OPCODE_ACK: -- cgit v1.2.3 From d4156e8cd93f5772483928aaf4960120caebd789 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:31:32 -0700 Subject: [NETFILTER]: nf_conntrack: reduce masks to a subset of tuples Since conntrack currently allows to use masks for every bit of both helper and expectation tuples, we can't hash them and have to keep them on two global lists that are searched for every new connection. This patch removes the never used ability to use masks for the destination part of the expectation tuple and completely removes masks from helpers since the only reasonable choice is a full match on l3num, protonum and src.u.all. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_expect.h | 3 +- include/net/netfilter/nf_conntrack_helper.h | 5 +-- include/net/netfilter/nf_conntrack_tuple.h | 65 +++++++++++++++++++---------- net/ipv4/netfilter/nf_nat_snmp_basic.c | 6 --- net/netfilter/nf_conntrack_amanda.c | 6 --- net/netfilter/nf_conntrack_expect.c | 44 ++++--------------- net/netfilter/nf_conntrack_ftp.c | 3 -- net/netfilter/nf_conntrack_h323_main.c | 14 ------- net/netfilter/nf_conntrack_helper.c | 3 +- net/netfilter/nf_conntrack_irc.c | 3 -- net/netfilter/nf_conntrack_netbios_ns.c | 6 --- net/netfilter/nf_conntrack_netlink.c | 18 +++++--- net/netfilter/nf_conntrack_pptp.c | 3 -- net/netfilter/nf_conntrack_sane.c | 2 - net/netfilter/nf_conntrack_sip.c | 3 -- net/netfilter/nf_conntrack_tftp.c | 3 -- 16 files changed, 71 insertions(+), 116 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index c0b1d1fb23e1..13643f7f7422 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -16,7 +16,8 @@ struct nf_conntrack_expect struct list_head list; /* We expect this tuple, with the following mask */ - struct nf_conntrack_tuple tuple, mask; + struct nf_conntrack_tuple tuple; + struct nf_conntrack_tuple_mask mask; /* Function to call after setup and insertion */ void (*expectfn)(struct nf_conn *new, diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index b43a75ba44ac..d62e6f093af4 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -24,10 +24,9 @@ struct nf_conntrack_helper * expected connections */ unsigned int timeout; /* timeout for expecteds */ - /* Mask of things we will help (compared against server response) */ + /* Tuple of things we will help (compared against server response) */ struct nf_conntrack_tuple tuple; - struct nf_conntrack_tuple mask; - + /* Function to call when data passes; return verdict, or -1 to invalidate. */ int (*help)(struct sk_buff **pskb, diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index d02ce876b4ca..99934ab538e6 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -100,6 +100,14 @@ struct nf_conntrack_tuple } dst; }; +struct nf_conntrack_tuple_mask +{ + struct { + union nf_conntrack_address u3; + union nf_conntrack_man_proto u; + } src; +}; + /* This is optimized opposed to a memset of the whole structure. Everything we * really care about is the source/destination unions */ #define NF_CT_TUPLE_U_BLANK(tuple) \ @@ -161,31 +169,44 @@ static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1, return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2); } +static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1, + const struct nf_conntrack_tuple_mask *m2) +{ + return (m1->src.u3.all[0] == m2->src.u3.all[0] && + m1->src.u3.all[1] == m2->src.u3.all[1] && + m1->src.u3.all[2] == m2->src.u3.all[2] && + m1->src.u3.all[3] == m2->src.u3.all[3] && + m1->src.u.all == m2->src.u.all); +} + +static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1, + const struct nf_conntrack_tuple *t2, + const struct nf_conntrack_tuple_mask *mask) +{ + int count; + + for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) { + if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) & + mask->src.u3.all[count]) + return 0; + } + + if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all) + return 0; + + if (t1->src.l3num != t2->src.l3num || + t1->dst.protonum != t2->dst.protonum) + return 0; + + return 1; +} + static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t, const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_tuple *mask) + const struct nf_conntrack_tuple_mask *mask) { - int count = 0; - - for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ - if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) & - mask->src.u3.all[count]) - return 0; - } - - for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ - if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) & - mask->dst.u3.all[count]) - return 0; - } - - if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all || - (t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all || - (t->src.l3num ^ tuple->src.l3num) & mask->src.l3num || - (t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum) - return 0; - - return 1; + return nf_ct_tuple_src_mask_cmp(t, tuple, mask) && + nf_ct_tuple_dst_equal(t, tuple); } #endif /* _NF_CONNTRACK_TUPLE_H */ diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 6e88505d6162..6bfcd3a90f08 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1276,9 +1276,6 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.udp.port = __constant_htons(SNMP_PORT), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, }; static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { @@ -1290,9 +1287,6 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, }; /***************************************************************************** diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index d21359e6c14c..e42ab230ad88 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -174,9 +174,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.udp.port = __constant_htons(10080), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, }, { .name = "amanda", @@ -187,9 +184,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { .tuple.src.l3num = AF_INET6, .tuple.src.u.udp.port = __constant_htons(10080), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, }, }; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 4130ea662c48..83b5ad85e0ee 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -141,25 +141,16 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, { /* Part covered by intersection of masks must be unequal, otherwise they clash */ - struct nf_conntrack_tuple intersect_mask; + struct nf_conntrack_tuple_mask intersect_mask; int count; - intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num; intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all; - intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all; - intersect_mask.dst.protonum = a->mask.dst.protonum - & b->mask.dst.protonum; for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ intersect_mask.src.u3.all[count] = a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; } - for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ - intersect_mask.dst.u3.all[count] = - a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count]; - } - return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask); } @@ -168,7 +159,7 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, { return a->master == b->master && nf_ct_tuple_equal(&a->tuple, &b->tuple) - && nf_ct_tuple_equal(&a->mask, &b->mask); + && nf_ct_tuple_mask_equal(&a->mask, &b->mask); } /* Generally a bad idea to call this: could have matched already. */ @@ -224,8 +215,6 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, exp->helper = NULL; exp->tuple.src.l3num = family; exp->tuple.dst.protonum = proto; - exp->mask.src.l3num = 0xFFFF; - exp->mask.dst.protonum = 0xFF; if (saddr) { memcpy(&exp->tuple.src.u3, saddr, len); @@ -242,21 +231,6 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3)); } - if (daddr) { - memcpy(&exp->tuple.dst.u3, daddr, len); - if (sizeof(exp->tuple.dst.u3) > len) - /* address needs to be cleared for nf_ct_tuple_equal */ - memset((void *)&exp->tuple.dst.u3 + len, 0x00, - sizeof(exp->tuple.dst.u3) - len); - memset(&exp->mask.dst.u3, 0xFF, len); - if (sizeof(exp->mask.dst.u3) > len) - memset((void *)&exp->mask.dst.u3 + len, 0x00, - sizeof(exp->mask.dst.u3) - len); - } else { - memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3)); - memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3)); - } - if (src) { exp->tuple.src.u.all = (__force u16)*src; exp->mask.src.u.all = 0xFFFF; @@ -265,13 +239,13 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, exp->mask.src.u.all = 0; } - if (dst) { - exp->tuple.dst.u.all = (__force u16)*dst; - exp->mask.dst.u.all = 0xFFFF; - } else { - exp->tuple.dst.u.all = 0; - exp->mask.dst.u.all = 0; - } + memcpy(&exp->tuple.dst.u3, daddr, len); + if (sizeof(exp->tuple.dst.u3) > len) + /* address needs to be cleared for nf_ct_tuple_equal */ + memset((void *)&exp->tuple.dst.u3 + len, 0x00, + sizeof(exp->tuple.dst.u3) - len); + + exp->tuple.dst.u.all = (__force u16)*dst; } EXPORT_SYMBOL_GPL(nf_ct_expect_init); diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 9ad15191bb44..198330b8ada4 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -560,9 +560,6 @@ static int __init nf_conntrack_ftp_init(void) for (j = 0; j < 2; j++) { ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; - ftp[i][j].mask.src.l3num = 0xFFFF; - ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF); - ftp[i][j].mask.dst.protonum = 0xFF; ftp[i][j].max_expected = 1; ftp[i][j].timeout = 5 * 60; /* 5 Minutes */ ftp[i][j].me = THIS_MODULE; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 61ae90fb328a..8c57b8119bfb 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -626,8 +626,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */, .timeout = 240, .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .help = h245_help }; @@ -1173,9 +1171,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), .tuple.dst.protonum = IPPROTO_TCP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.tcp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .help = q931_help }, { @@ -1187,9 +1182,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { .tuple.src.l3num = AF_INET6, .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), .tuple.dst.protonum = IPPROTO_TCP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.tcp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .help = q931_help }, }; @@ -1751,9 +1743,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.udp.port = __constant_htons(RAS_PORT), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .help = ras_help, }, { @@ -1764,9 +1753,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { .tuple.src.l3num = AF_INET6, .tuple.src.u.udp.port = __constant_htons(RAS_PORT), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .help = ras_help, }, }; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 89a5f7333d38..fdabf823f8cd 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -34,9 +34,10 @@ struct nf_conntrack_helper * __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_helper *h; + struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; list_for_each_entry(h, &helpers, list) { - if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) + if (nf_ct_tuple_src_mask_cmp(tuple, &h->tuple, &mask)) return h; } return NULL; diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 79da93e4396b..8c7340794bf6 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -239,9 +239,6 @@ static int __init nf_conntrack_irc_init(void) irc[i].tuple.src.l3num = AF_INET; irc[i].tuple.src.u.tcp.port = htons(ports[i]); irc[i].tuple.dst.protonum = IPPROTO_TCP; - irc[i].mask.src.l3num = 0xFFFF; - irc[i].mask.src.u.tcp.port = htons(0xFFFF); - irc[i].mask.dst.protonum = 0xFF; irc[i].max_expected = max_dcc_channels; irc[i].timeout = dcc_timeout; irc[i].me = THIS_MODULE; diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index ea585c789a83..1d59fabeb5f7 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -83,9 +83,6 @@ static int help(struct sk_buff **pskb, unsigned int protoff, exp->mask.src.u3.ip = mask; exp->mask.src.u.udp.port = htons(0xFFFF); - exp->mask.dst.u3.ip = htonl(0xFFFFFFFF); - exp->mask.dst.u.udp.port = htons(0xFFFF); - exp->mask.dst.protonum = 0xFF; exp->expectfn = NULL; exp->flags = NF_CT_EXPECT_PERMANENT; @@ -104,9 +101,6 @@ static struct nf_conntrack_helper helper __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.udp.port = __constant_htons(NMBD_PORT), .tuple.dst.protonum = IPPROTO_UDP, - .mask.src.l3num = 0xFFFF, - .mask.src.u.udp.port = __constant_htons(0xFFFF), - .mask.dst.protonum = 0xFF, .max_expected = 1, .me = THIS_MODULE, .help = help, diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 954cc58b9d04..206491488f4e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1094,22 +1094,29 @@ nfattr_failure: static inline int ctnetlink_exp_dump_mask(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_tuple *mask) + const struct nf_conntrack_tuple_mask *mask) { int ret; struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; - struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); + struct nf_conntrack_tuple m; + struct nfattr *nest_parms; + + memset(&m, 0xFF, sizeof(m)); + m.src.u.all = mask->src.u.all; + memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3)); + + nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); - ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto); + ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto); nf_ct_l3proto_put(l3proto); if (unlikely(ret < 0)) goto nfattr_failure; l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); - ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto); + ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); nf_ct_l4proto_put(l4proto); if (unlikely(ret < 0)) goto nfattr_failure; @@ -1447,7 +1454,8 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) exp->master = ct; exp->helper = NULL; memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); - memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple)); + memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); + exp->mask.src.u.all = mask.src.u.all; err = nf_ct_expect_related(exp); nf_ct_expect_put(exp); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 916e106d36bc..63dac5eb959f 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -585,9 +585,6 @@ static struct nf_conntrack_helper pptp __read_mostly = { .tuple.src.l3num = AF_INET, .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT), .tuple.dst.protonum = IPPROTO_TCP, - .mask.src.l3num = 0xffff, - .mask.src.u.tcp.port = __constant_htons(0xffff), - .mask.dst.protonum = 0xff, .help = conntrack_pptp_help, .destroy = pptp_destroy_siblings, }; diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 28ed303c565b..edd10df8aa08 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -206,8 +206,6 @@ static int __init nf_conntrack_sane_init(void) for (j = 0; j < 2; j++) { sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); sane[i][j].tuple.dst.protonum = IPPROTO_TCP; - sane[i][j].mask.src.u.tcp.port = 0xFFFF; - sane[i][j].mask.dst.protonum = 0xFF; sane[i][j].max_expected = 1; sane[i][j].timeout = 5 * 60; /* 5 Minutes */ sane[i][j].me = THIS_MODULE; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1f17f8040cd2..5b78f0e1f63b 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -506,9 +506,6 @@ static int __init nf_conntrack_sip_init(void) for (j = 0; j < 2; j++) { sip[i][j].tuple.dst.protonum = IPPROTO_UDP; sip[i][j].tuple.src.u.udp.port = htons(ports[i]); - sip[i][j].mask.src.l3num = 0xFFFF; - sip[i][j].mask.src.u.udp.port = htons(0xFFFF); - sip[i][j].mask.dst.protonum = 0xFF; sip[i][j].max_expected = 2; sip[i][j].timeout = 3 * 60; /* 3 minutes */ sip[i][j].me = THIS_MODULE; diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 53d57b4c0de7..db0387cf9bac 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -126,9 +126,6 @@ static int __init nf_conntrack_tftp_init(void) for (j = 0; j < 2; j++) { tftp[i][j].tuple.dst.protonum = IPPROTO_UDP; tftp[i][j].tuple.src.u.udp.port = htons(ports[i]); - tftp[i][j].mask.src.l3num = 0xFFFF; - tftp[i][j].mask.dst.protonum = 0xFF; - tftp[i][j].mask.src.u.udp.port = htons(0xFFFF); tftp[i][j].max_expected = 1; tftp[i][j].timeout = 5 * 60; /* 5 minutes */ tftp[i][j].me = THIS_MODULE; -- cgit v1.2.3 From e9c1b084e17ca225b6be731b819308ee0f9e04b8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:32:53 -0700 Subject: [NETFILTER]: nf_conntrack: move expectaton related init code to nf_conntrack_expect.c Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_expect.h | 4 +-- net/netfilter/nf_conntrack_core.c | 20 +++++------- net/netfilter/nf_conntrack_expect.c | 48 ++++++++++++++++++++++++++++- net/netfilter/nf_conntrack_standalone.c | 11 ++----- 4 files changed, 59 insertions(+), 24 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 13643f7f7422..cf6a619664e8 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -7,8 +7,6 @@ #include extern struct list_head nf_ct_expect_list; -extern struct kmem_cache *nf_ct_expect_cachep; -extern const struct file_operations exp_file_ops; struct nf_conntrack_expect { @@ -53,6 +51,8 @@ struct nf_conntrack_expect #define NF_CT_EXPECT_PERMANENT 0x1 +int nf_conntrack_expect_init(void); +void nf_conntrack_expect_fini(void); struct nf_conntrack_expect * __nf_ct_expect_find(const struct nf_conntrack_tuple *tuple); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 793f12ff168b..ed44a09ae739 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -961,12 +961,12 @@ void nf_conntrack_cleanup(void) rcu_assign_pointer(nf_ct_destroy, NULL); kmem_cache_destroy(nf_conntrack_cachep); - kmem_cache_destroy(nf_ct_expect_cachep); nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, nf_conntrack_htable_size); nf_conntrack_proto_fini(); nf_conntrack_helper_fini(); + nf_conntrack_expect_fini(); } struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) @@ -1088,21 +1088,17 @@ int __init nf_conntrack_init(void) goto err_free_hash; } - nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", - sizeof(struct nf_conntrack_expect), - 0, 0, NULL, NULL); - if (!nf_ct_expect_cachep) { - printk(KERN_ERR "Unable to create nf_expect slab cache\n"); + ret = nf_conntrack_proto_init(); + if (ret < 0) goto err_free_conntrack_slab; - } - ret = nf_conntrack_proto_init(); + ret = nf_conntrack_expect_init(); if (ret < 0) - goto out_free_expect_slab; + goto out_fini_proto; ret = nf_conntrack_helper_init(); if (ret < 0) - goto out_fini_proto; + goto out_fini_expect; /* For use by REJECT target */ rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach); @@ -1116,10 +1112,10 @@ int __init nf_conntrack_init(void) return ret; +out_fini_expect: + nf_conntrack_expect_fini(); out_fini_proto: nf_conntrack_proto_fini(); -out_free_expect_slab: - kmem_cache_destroy(nf_ct_expect_cachep); err_free_conntrack_slab: kmem_cache_destroy(nf_conntrack_cachep); err_free_hash: diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 5c8cb0f243a2..ad197bccc7ca 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -29,7 +29,7 @@ LIST_HEAD(nf_ct_expect_list); EXPORT_SYMBOL_GPL(nf_ct_expect_list); -struct kmem_cache *nf_ct_expect_cachep __read_mostly; +static struct kmem_cache *nf_ct_expect_cachep __read_mostly; static unsigned int nf_ct_expect_next_id; /* nf_conntrack_expect helper functions */ @@ -413,3 +413,49 @@ const struct file_operations exp_file_ops = { .release = seq_release }; #endif /* CONFIG_PROC_FS */ + +static int __init exp_proc_init(void) +{ +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc; + + proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops); + if (!proc) + return -ENOMEM; +#endif /* CONFIG_PROC_FS */ + return 0; +} + +static void exp_proc_remove(void) +{ +#ifdef CONFIG_PROC_FS + proc_net_remove("nf_conntrack_expect"); +#endif /* CONFIG_PROC_FS */ +} + +int __init nf_conntrack_expect_init(void) +{ + int err; + + nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", + sizeof(struct nf_conntrack_expect), + 0, 0, NULL, NULL); + if (!nf_ct_expect_cachep) + return -ENOMEM; + + err = exp_proc_init(); + if (err < 0) + goto err1; + + return 0; + +err1: + kmem_cache_destroy(nf_ct_expect_cachep); + return err; +} + +void nf_conntrack_expect_fini(void) +{ + exp_proc_remove(); + kmem_cache_destroy(nf_ct_expect_cachep); +} diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index fe536b20408b..098e7993932a 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -411,7 +411,7 @@ EXPORT_SYMBOL_GPL(nf_ct_log_invalid); static int __init nf_conntrack_standalone_init(void) { #ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc, *proc_exp, *proc_stat; + struct proc_dir_entry *proc, *proc_stat; #endif int ret = 0; @@ -423,13 +423,9 @@ static int __init nf_conntrack_standalone_init(void) proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); if (!proc) goto cleanup_init; - proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, - &exp_file_ops); - if (!proc_exp) goto cleanup_proc; - proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); if (!proc_stat) - goto cleanup_proc_exp; + goto cleanup_proc; proc_stat->proc_fops = &ct_cpu_seq_fops; proc_stat->owner = THIS_MODULE; @@ -449,8 +445,6 @@ static int __init nf_conntrack_standalone_init(void) #endif #ifdef CONFIG_PROC_FS remove_proc_entry("nf_conntrack", proc_net_stat); - cleanup_proc_exp: - proc_net_remove("nf_conntrack_expect"); cleanup_proc: proc_net_remove("nf_conntrack"); cleanup_init: @@ -466,7 +460,6 @@ static void __exit nf_conntrack_standalone_fini(void) #endif #ifdef CONFIG_PROC_FS remove_proc_entry("nf_conntrack", proc_net_stat); - proc_net_remove("nf_conntrack_expect"); proc_net_remove("nf_conntrack"); #endif /* CNFIG_PROC_FS */ nf_conntrack_cleanup(); -- cgit v1.2.3 From a71c085562bcc99e8b711cab4222bff1f6e955da Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:33:47 -0700 Subject: [NETFILTER]: nf_conntrack: use hashtable for expectations Currently all expectations are kept on a global list that - needs to be searched for every new conncetion - needs to be walked for evicting expectations when a master connection has reached its limit - needs to be walked on connection destruction for connections that have open expectations This is obviously not good, especially when considering helpers like H.323 that register *lots* of expectations and can set up permanent expectations, but it also allows for an easy DoS against firewalls using connection tracking helpers. Use a hashtable for expectations to avoid incurring the search overhead for every new connection. The default hash size is 1/256 of the conntrack hash table size, this can be overriden using a module parameter. This patch only introduces the hash table for expectation lookups and keeps other users to reduce the noise, the following patches will get rid of it completely. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_core.h | 1 - include/net/netfilter/nf_conntrack_expect.h | 5 ++ net/netfilter/nf_conntrack_expect.c | 72 ++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 7 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index a18f79c80db8..4056f5f08da1 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -84,7 +84,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l4proto *proto); extern struct hlist_head *nf_conntrack_hash; -extern struct list_head nf_ct_expect_list; extern rwlock_t nf_conntrack_lock ; extern struct hlist_head unconfirmed; diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index cf6a619664e8..424d4bdb9848 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -7,12 +7,17 @@ #include extern struct list_head nf_ct_expect_list; +extern struct hlist_head *nf_ct_expect_hash; +extern unsigned int nf_ct_expect_hsize; struct nf_conntrack_expect { /* Internal linked list (global expectation list) */ struct list_head list; + /* Hash member */ + struct hlist_node hnode; + /* We expect this tuple, with the following mask */ struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple_mask mask; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index ad197bccc7ca..0696f87aaef1 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,17 @@ LIST_HEAD(nf_ct_expect_list); EXPORT_SYMBOL_GPL(nf_ct_expect_list); +struct hlist_head *nf_ct_expect_hash __read_mostly; +EXPORT_SYMBOL_GPL(nf_ct_expect_hash); + +unsigned int nf_ct_expect_hsize __read_mostly; +EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); + +static unsigned int nf_ct_expect_hash_rnd __read_mostly; +static unsigned int nf_ct_expect_count; +static int nf_ct_expect_hash_rnd_initted __read_mostly; +static int nf_ct_expect_vmalloc; + static struct kmem_cache *nf_ct_expect_cachep __read_mostly; static unsigned int nf_ct_expect_next_id; @@ -41,6 +53,9 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) NF_CT_ASSERT(!timer_pending(&exp->timeout)); list_del(&exp->list); + hlist_del(&exp->hnode); + nf_ct_expect_count--; + NF_CT_STAT_INC(expect_delete); master_help->expecting--; nf_ct_expect_put(exp); @@ -57,12 +72,31 @@ static void nf_ct_expectation_timed_out(unsigned long ul_expect) nf_ct_expect_put(exp); } +static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple) +{ + if (unlikely(!nf_ct_expect_hash_rnd_initted)) { + get_random_bytes(&nf_ct_expect_hash_rnd, 4); + nf_ct_expect_hash_rnd_initted = 1; + } + + return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), + (((tuple->dst.protonum ^ tuple->src.l3num) << 16) | + tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) % + nf_ct_expect_hsize; +} + struct nf_conntrack_expect * __nf_ct_expect_find(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; + struct hlist_node *n; + unsigned int h; + + if (!nf_ct_expect_count) + return NULL; - list_for_each_entry(i, &nf_ct_expect_list, list) { + h = nf_ct_expect_dst_hash(tuple); + hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) { if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; } @@ -252,10 +286,14 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_put); static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) { struct nf_conn_help *master_help = nfct_help(exp->master); + unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); atomic_inc(&exp->use); master_help->expecting++; + list_add(&exp->list, &nf_ct_expect_list); + hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]); + nf_ct_expect_count++; setup_timer(&exp->timeout, nf_ct_expectation_timed_out, (unsigned long)exp); @@ -300,6 +338,8 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) struct nf_conntrack_expect *i; struct nf_conn *master = expect->master; struct nf_conn_help *master_help = nfct_help(master); + struct hlist_node *n; + unsigned int h; int ret; NF_CT_ASSERT(master_help); @@ -309,7 +349,8 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) ret = -ESHUTDOWN; goto out; } - list_for_each_entry(i, &nf_ct_expect_list, list) { + h = nf_ct_expect_dst_hash(&expect->tuple); + hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) { if (expect_matches(i, expect)) { /* Refresh timer: if it's dying, ignore.. */ if (refresh_timer(i)) { @@ -433,24 +474,41 @@ static void exp_proc_remove(void) #endif /* CONFIG_PROC_FS */ } +module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600); + int __init nf_conntrack_expect_init(void) { - int err; + int err = -ENOMEM; + + if (!nf_ct_expect_hsize) { + nf_ct_expect_hsize = nf_conntrack_htable_size / 256; + if (!nf_ct_expect_hsize) + nf_ct_expect_hsize = 1; + } + + nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, + &nf_ct_expect_vmalloc); + if (nf_ct_expect_hash == NULL) + goto err1; nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", sizeof(struct nf_conntrack_expect), 0, 0, NULL, NULL); if (!nf_ct_expect_cachep) - return -ENOMEM; + goto err2; err = exp_proc_init(); if (err < 0) - goto err1; + goto err3; return 0; -err1: +err3: + nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc, + nf_ct_expect_hsize); +err2: kmem_cache_destroy(nf_ct_expect_cachep); +err1: return err; } @@ -458,4 +516,6 @@ void nf_conntrack_expect_fini(void) { exp_proc_remove(); kmem_cache_destroy(nf_ct_expect_cachep); + nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc, + nf_ct_expect_hsize); } -- cgit v1.2.3 From b560580a13b180bc1e3cad7ffbc93388cc39be5d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:35:56 -0700 Subject: [NETFILTER]: nf_conntrack_expect: maintain per conntrack expectation list This patch brings back the per-conntrack expectation list that was removed around 2.6.10 to avoid walking all expectations on expectation eviction and conntrack destruction. As these were the last users of the global expectation list, this patch also kills that. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 2 ++ include/net/netfilter/nf_conntrack_expect.h | 5 ++-- include/net/netfilter/nf_conntrack_helper.h | 2 ++ net/netfilter/nf_conntrack_core.c | 18 +++---------- net/netfilter/nf_conntrack_expect.c | 40 ++++++++++++++--------------- net/netfilter/nf_conntrack_helper.c | 13 ++++++++++ net/netfilter/nf_conntrack_netlink.c | 4 +-- 7 files changed, 45 insertions(+), 39 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 8f2cbb965f3d..d4f02eb0c66c 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -82,6 +82,8 @@ struct nf_conn_help { union nf_conntrack_help help; + struct hlist_head expectations; + /* Current number of expected connections */ unsigned int expecting; }; diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 424d4bdb9848..9d5af4e22c4f 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -6,14 +6,13 @@ #define _NF_CONNTRACK_EXPECT_H #include -extern struct list_head nf_ct_expect_list; extern struct hlist_head *nf_ct_expect_hash; extern unsigned int nf_ct_expect_hsize; struct nf_conntrack_expect { - /* Internal linked list (global expectation list) */ - struct list_head list; + /* Conntrack expectation list member */ + struct hlist_node lnode; /* Hash member */ struct hlist_node hnode; diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index d62e6f093af4..2c0e2e0fb7ff 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -52,6 +52,8 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); +extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); + static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ed44a09ae739..d1fc019760a1 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -502,12 +502,9 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = exp->master; if (exp->helper) { - help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, - GFP_ATOMIC); + help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); if (help) rcu_assign_pointer(help->helper, exp->helper); - else - DEBUGP("failed to add helper extension area"); } #ifdef CONFIG_NF_CONNTRACK_MARK @@ -523,14 +520,9 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, helper = __nf_ct_helper_find(&repl_tuple); if (helper) { - help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, - GFP_ATOMIC); + help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); if (help) - /* not in hash table yet, so not strictly - necessary */ rcu_assign_pointer(help->helper, helper); - else - DEBUGP("failed to add helper extension area"); } NF_CT_STAT_INC(new); } @@ -721,11 +713,9 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, } if (help == NULL) { - help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_ATOMIC); - if (help == NULL) { - DEBUGP("failed to add helper extension area"); + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); + if (help == NULL) goto out; - } } else { memset(&help->help, 0, sizeof(help->help)); } diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index c5006b0a4e65..5ef0dd439e76 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -27,9 +27,6 @@ #include #include -LIST_HEAD(nf_ct_expect_list); -EXPORT_SYMBOL_GPL(nf_ct_expect_list); - struct hlist_head *nf_ct_expect_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_ct_expect_hash); @@ -52,13 +49,14 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) NF_CT_ASSERT(master_help); NF_CT_ASSERT(!timer_pending(&exp->timeout)); - list_del(&exp->list); hlist_del(&exp->hnode); nf_ct_expect_count--; - NF_CT_STAT_INC(expect_delete); + hlist_del(&exp->lnode); master_help->expecting--; nf_ct_expect_put(exp); + + NF_CT_STAT_INC(expect_delete); } EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); @@ -153,17 +151,18 @@ nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple) /* delete all expectations for this conntrack */ void nf_ct_remove_expectations(struct nf_conn *ct) { - struct nf_conntrack_expect *i, *tmp; struct nf_conn_help *help = nfct_help(ct); + struct nf_conntrack_expect *exp; + struct hlist_node *n, *next; /* Optimization: most connection never expect any others. */ if (!help || help->expecting == 0) return; - list_for_each_entry_safe(i, tmp, &nf_ct_expect_list, list) { - if (i->master == ct && del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - nf_ct_expect_put(i); + hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { + if (del_timer(&exp->timeout)) { + nf_ct_unlink_expect(exp); + nf_ct_expect_put(exp); } } } @@ -289,9 +288,10 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); atomic_inc(&exp->use); + + hlist_add_head(&exp->lnode, &master_help->expectations); master_help->expecting++; - list_add(&exp->list, &nf_ct_expect_list); hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]); nf_ct_expect_count++; @@ -308,16 +308,16 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) /* Race with expectations being used means we could have none to find; OK. */ static void evict_oldest_expect(struct nf_conn *master) { - struct nf_conntrack_expect *i; + struct nf_conn_help *master_help = nfct_help(master); + struct nf_conntrack_expect *exp = NULL; + struct hlist_node *n; - list_for_each_entry_reverse(i, &nf_ct_expect_list, list) { - if (i->master == master) { - if (del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - nf_ct_expect_put(i); - } - break; - } + hlist_for_each_entry(exp, n, &master_help->expectations, lnode) + ; /* nothing */ + + if (exp && del_timer(&exp->timeout)) { + nf_ct_unlink_expect(exp); + nf_ct_expect_put(exp); } } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index cc8ae7404ac4..66c209d7e09d 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -87,6 +87,19 @@ __nf_conntrack_helper_find_byname(const char *name) } EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); +struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) +{ + struct nf_conn_help *help; + + help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp); + if (help) + INIT_HLIST_HEAD(&help->expectations); + else + pr_debug("failed to add helper extension area"); + return help; +} +EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); + static inline int unhelp(struct nf_conntrack_tuple_hash *i, const struct nf_conntrack_helper *me) { diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 60af9b6b9e00..6f89b105a205 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -868,7 +868,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) /* need to zero data of old helper */ memset(&help->help, 0, sizeof(help->help)); } else { - help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); + help = nf_ct_helper_ext_add(ct, GFP_KERNEL); if (help == NULL) return -ENOMEM; } @@ -989,7 +989,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], helper = nf_ct_helper_find_get(rtuple); if (helper) { - help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); + help = nf_ct_helper_ext_add(ct, GFP_KERNEL); if (help == NULL) { nf_ct_helper_put(helper); err = -ENOMEM; -- cgit v1.2.3 From f264a7df08d50bb4a23be6a9aa06940e497ac1c4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:36:24 -0700 Subject: [NETFILTER]: nf_conntrack_expect: introduce nf_conntrack_expect_max sysct As a last step of preventing DoS by creating lots of expectations, this patch introduces a global maximum and a sysctl to control it. The default is initialized to 4 * the expectation hash table size, which results in 1/64 of the default maxmimum of conntracks. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_expect.h | 1 + net/netfilter/nf_conntrack_expect.c | 10 ++++++++++ net/netfilter/nf_conntrack_standalone.c | 9 ++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 9d5af4e22c4f..cae1a0dce365 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -8,6 +8,7 @@ extern struct hlist_head *nf_ct_expect_hash; extern unsigned int nf_ct_expect_hsize; +extern unsigned int nf_ct_expect_max; struct nf_conntrack_expect { diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 5ef0dd439e76..513828fdaa2c 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -35,6 +35,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); static unsigned int nf_ct_expect_hash_rnd __read_mostly; static unsigned int nf_ct_expect_count; +unsigned int nf_ct_expect_max __read_mostly; static int nf_ct_expect_hash_rnd_initted __read_mostly; static int nf_ct_expect_vmalloc; @@ -367,6 +368,14 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) master_help->expecting >= master_help->helper->max_expected) evict_oldest_expect(master); + if (nf_ct_expect_count >= nf_ct_expect_max) { + if (net_ratelimit()) + printk(KERN_WARNING + "nf_conntrack: expectation table full"); + ret = -EMFILE; + goto out; + } + nf_ct_expect_insert(expect); nf_ct_expect_event(IPEXP_NEW, expect); ret = 0; @@ -522,6 +531,7 @@ int __init nf_conntrack_expect_init(void) if (!nf_ct_expect_hsize) nf_ct_expect_hsize = 1; } + nf_ct_expect_max = nf_ct_expect_hsize * 4; nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, &nf_ct_expect_vmalloc); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 098e7993932a..6af96c6e29fb 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -372,7 +372,14 @@ static ctl_table nf_ct_sysctl_table[] = { .extra1 = &log_invalid_proto_min, .extra2 = &log_invalid_proto_max, }, - + { + .ctl_name = CTL_UNNUMBERED, + .procname = "nf_conntrack_expect_max", + .data = &nf_ct_expect_max, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0 } }; -- cgit v1.2.3 From b8a7fe6c10511fce10b20efa163123f4041f2550 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:36:46 -0700 Subject: [NETFILTER]: nf_conntrack_helper: use hashtable for conntrack helpers Eliminate the last global list searched for every new connection. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_helper.h | 4 +- net/netfilter/nf_conntrack_helper.c | 70 +++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 15 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 2c0e2e0fb7ff..d04f99964d94 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -15,8 +15,8 @@ struct module; struct nf_conntrack_helper -{ - struct list_head list; /* Internal use. */ +{ + struct hlist_node hnode; /* Internal use. */ const char *name; /* name of the module */ struct module *me; /* pointer to self */ diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 66c209d7e09d..b1179dd3d8c3 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -28,23 +28,41 @@ #include #include -static __read_mostly LIST_HEAD(helpers); +static struct hlist_head *nf_ct_helper_hash __read_mostly; +static unsigned int nf_ct_helper_hsize __read_mostly; +static unsigned int nf_ct_helper_count __read_mostly; +static int nf_ct_helper_vmalloc; + + +/* Stupid hash, but collision free for the default registrations of the + * helpers currently in the kernel. */ +static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple) +{ + return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^ + tuple->src.u.all) % nf_ct_helper_hsize; +} struct nf_conntrack_helper * __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) { - struct nf_conntrack_helper *h; + struct nf_conntrack_helper *helper; struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; + struct hlist_node *n; + unsigned int h; - list_for_each_entry(h, &helpers, list) { - if (nf_ct_tuple_src_mask_cmp(tuple, &h->tuple, &mask)) - return h; + if (!nf_ct_helper_count) + return NULL; + + h = helper_hash(tuple); + hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) { + if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask)) + return helper; } return NULL; } struct nf_conntrack_helper * -nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) +nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_helper *helper; @@ -77,12 +95,15 @@ struct nf_conntrack_helper * __nf_conntrack_helper_find_byname(const char *name) { struct nf_conntrack_helper *h; + struct hlist_node *n; + unsigned int i; - list_for_each_entry(h, &helpers, list) { - if (!strcmp(h->name, name)) - return h; + for (i = 0; i < nf_ct_helper_hsize; i++) { + hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) { + if (!strcmp(h->name, name)) + return h; + } } - return NULL; } EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); @@ -115,10 +136,13 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { + unsigned int h = helper_hash(&me->tuple); + BUG_ON(me->timeout == 0); write_lock_bh(&nf_conntrack_lock); - list_add(&me->list, &helpers); + hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]); + nf_ct_helper_count++; write_unlock_bh(&nf_conntrack_lock); return 0; @@ -134,7 +158,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Need write lock here, to delete helper. */ write_lock_bh(&nf_conntrack_lock); - list_del(&me->list); + hlist_del(&me->hnode); + nf_ct_helper_count--; /* Get rid of expectations */ for (i = 0; i < nf_ct_expect_hsize; i++) { @@ -171,10 +196,29 @@ static struct nf_ct_ext_type helper_extend __read_mostly = { int nf_conntrack_helper_init() { - return nf_ct_extend_register(&helper_extend); + int err; + + nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ + nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize, + &nf_ct_helper_vmalloc); + if (!nf_ct_helper_hash) + return -ENOMEM; + + err = nf_ct_extend_register(&helper_extend); + if (err < 0) + goto err1; + + return 0; + +err1: + nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc, + nf_ct_helper_hsize); + return err; } void nf_conntrack_helper_fini() { nf_ct_extend_unregister(&helper_extend); + nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc, + nf_ct_helper_hsize); } -- cgit v1.2.3 From 0d53778e81ac7af266dac8a20cc328328c327112 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 7 Jul 2007 22:39:38 -0700 Subject: [NETFILTER]: Convert DEBUGP to pr_debug Convert DEBUGP to pr_debug and fix lots of non-compiling debug statements. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_pptp.h | 2 + include/net/netfilter/nf_conntrack_tuple.h | 10 +- net/ipv4/netfilter/ipt_CLUSTERIP.c | 27 ++-- net/ipv4/netfilter/ipt_LOG.c | 12 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 10 +- net/ipv4/netfilter/ipt_NETMAP.c | 13 +- net/ipv4/netfilter/ipt_REDIRECT.c | 10 +- net/ipv4/netfilter/ipt_REJECT.c | 10 +- net/ipv4/netfilter/ipt_SAME.c | 53 +++---- net/ipv4/netfilter/ipt_ULOG.c | 35 ++--- net/ipv4/netfilter/ipt_iprange.c | 30 ++-- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 22 +-- .../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 6 - net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 22 +-- net/ipv4/netfilter/nf_nat_core.c | 15 +- net/ipv4/netfilter/nf_nat_ftp.c | 14 +- net/ipv4/netfilter/nf_nat_h323.c | 95 ++++++------ net/ipv4/netfilter/nf_nat_helper.c | 40 +++-- net/ipv4/netfilter/nf_nat_irc.c | 13 +- net/ipv4/netfilter/nf_nat_pptp.c | 37 ++--- net/ipv4/netfilter/nf_nat_proto_gre.c | 17 +-- net/ipv4/netfilter/nf_nat_rule.c | 14 +- net/ipv4/netfilter/nf_nat_sip.c | 8 - net/ipv4/netfilter/nf_nat_standalone.c | 16 +- net/ipv6/netfilter/ip6t_LOG.c | 12 +- net/ipv6/netfilter/ip6t_REJECT.c | 23 ++- net/ipv6/netfilter/ip6t_ah.c | 47 +++--- net/ipv6/netfilter/ip6t_frag.c | 76 +++++----- net/ipv6/netfilter/ip6t_hbh.c | 45 +++--- net/ipv6/netfilter/ip6t_rt.c | 82 +++++------ net/ipv6/netfilter/ip6table_mangle.c | 6 - net/ipv6/netfilter/ip6table_raw.c | 6 - net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 10 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 24 ++- net/ipv6/netfilter/nf_conntrack_reasm.c | 52 +++---- net/netfilter/nf_conntrack_core.c | 41 +++--- net/netfilter/nf_conntrack_ftp.c | 94 ++++++------ net/netfilter/nf_conntrack_h323_main.c | 161 ++++++++++----------- net/netfilter/nf_conntrack_irc.c | 24 ++- net/netfilter/nf_conntrack_l3proto_generic.c | 6 - net/netfilter/nf_conntrack_pptp.c | 71 +++++---- net/netfilter/nf_conntrack_proto_gre.c | 28 ++-- net/netfilter/nf_conntrack_proto_sctp.c | 92 ++++-------- net/netfilter/nf_conntrack_proto_tcp.c | 129 ++++++++--------- net/netfilter/nf_conntrack_sane.c | 27 ++-- net/netfilter/nf_conntrack_sip.c | 22 +-- net/netfilter/nf_conntrack_standalone.c | 6 - net/netfilter/nf_conntrack_tftp.c | 17 +-- 48 files changed, 662 insertions(+), 970 deletions(-) (limited to 'include/net') diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index 9d8144a488cd..c93061f33144 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -4,6 +4,8 @@ #include +extern const char *pptp_msg_name[]; + /* state of the control session */ enum pptp_ctrlsess_state { PPTP_SESSION_NONE, /* no session present */ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 99934ab538e6..040dae5f0c9e 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -120,11 +120,11 @@ struct nf_conntrack_tuple_mask #ifdef __KERNEL__ -#define NF_CT_DUMP_TUPLE(tp) \ -DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ - (tp), (tp)->src.l3num, (tp)->dst.protonum, \ - NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ - NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) +#define NF_CT_DUMP_TUPLE(tp) \ +pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ + (tp), (tp)->src.l3num, (tp)->dst.protonum, \ + NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ + NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) /* If we're the first tuple, it's the original dir. */ #define NF_CT_DIRECTION(h) \ diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 1981acedbfe8..8bacda3f6f6c 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -30,14 +30,6 @@ #define CLUSTERIP_VERSION "0.8" -#define DEBUG_CLUSTERIP - -#ifdef DEBUG_CLUSTERIP -#define DEBUGP printk -#else -#define DEBUGP -#endif - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("iptables target for CLUSTERIP"); @@ -351,15 +343,15 @@ target(struct sk_buff **pskb, break; } -#ifdef DEBUG_CLUSTERP +#ifdef DEBUG DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); #endif - DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark); + pr_debug("hash=%u ct_hash=%u ", hash, ct->mark); if (!clusterip_responsible(cipinfo->config, hash)) { - DEBUGP("not responsible\n"); + pr_debug("not responsible\n"); return NF_DROP; } - DEBUGP("responsible\n"); + pr_debug("responsible\n"); /* despite being received via linklayer multicast, this is * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ @@ -490,7 +482,7 @@ struct arp_payload { __be32 dst_ip; } __attribute__ ((packed)); -#ifdef CLUSTERIP_DEBUG +#ifdef DEBUG static void arp_print(struct arp_payload *payload) { #define HBUFFERLEN 30 @@ -546,8 +538,9 @@ arp_mangle(unsigned int hook, * this wouldn't work, since we didn't subscribe the mcast group on * other interfaces */ if (c->dev != out) { - DEBUGP("CLUSTERIP: not mangling arp reply on different " - "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name); + pr_debug("CLUSTERIP: not mangling arp reply on different " + "interface: cip'%s'-skb'%s'\n", + c->dev->name, out->name); clusterip_config_put(c); return NF_ACCEPT; } @@ -555,8 +548,8 @@ arp_mangle(unsigned int hook, /* mangle reply hardware address */ memcpy(payload->src_hw, c->clustermac, arp->ar_hln); -#ifdef CLUSTERIP_DEBUG - DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: "); +#ifdef DEBUG + pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: "); arp_print(payload); #endif diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 9bfce614ec28..5937ad150b9f 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -27,12 +27,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables syslog logging module"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Use lock to serialize, so printks don't overlap */ static DEFINE_SPINLOCK(log_lock); @@ -452,12 +446,12 @@ static bool ipt_log_checkentry(const char *tablename, const struct ipt_log_info *loginfo = targinfo; if (loginfo->level >= 8) { - DEBUGP("LOG: level %u >= 8\n", loginfo->level); + pr_debug("LOG: level %u >= 8\n", loginfo->level); return false; } if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { - DEBUGP("LOG: prefix term %i\n", - loginfo->prefix[sizeof(loginfo->prefix)-1]); + pr_debug("LOG: prefix term %i\n", + loginfo->prefix[sizeof(loginfo->prefix)-1]); return false; } return true; diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index bc033e0f424d..7c4e4be7c8b3 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -27,12 +27,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables MASQUERADE target module"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Lock protects masq region inside conntrack */ static DEFINE_RWLOCK(masq_lock); @@ -47,11 +41,11 @@ masquerade_check(const char *tablename, const struct nf_nat_multi_range_compat *mr = targinfo; if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { - DEBUGP("masquerade_check: bad MAP_IPS.\n"); + pr_debug("masquerade_check: bad MAP_IPS.\n"); return false; } if (mr->rangesize != 1) { - DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize); + pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize); return false; } return true; diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 0a7ce15bbdd0..41a011d5a065 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c @@ -18,17 +18,10 @@ #include #include -#define MODULENAME "NETMAP" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Svenning Soerensen "); MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static bool check(const char *tablename, const void *e, @@ -39,11 +32,11 @@ check(const char *tablename, const struct nf_nat_multi_range_compat *mr = targinfo; if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { - DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); + pr_debug("NETMAP:check: bad MAP_IPS.\n"); return false; } if (mr->rangesize != 1) { - DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize); + pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize); return false; } return true; @@ -86,7 +79,7 @@ target(struct sk_buff **pskb, } static struct xt_target target_module __read_mostly = { - .name = MODULENAME, + .name = "NETMAP", .family = AF_INET, .target = target, .targetsize = sizeof(struct nf_nat_multi_range_compat), diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 61e1e4772e37..6ac7a2373316 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -25,12 +25,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables REDIRECT target module"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* FIXME: Take multiple ranges --RR */ static bool redirect_check(const char *tablename, @@ -42,11 +36,11 @@ redirect_check(const char *tablename, const struct nf_nat_multi_range_compat *mr = targinfo; if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { - DEBUGP("redirect_check: bad MAP_IPS.\n"); + pr_debug("redirect_check: bad MAP_IPS.\n"); return false; } if (mr->rangesize != 1) { - DEBUGP("redirect_check: bad rangesize %u.\n", mr->rangesize); + pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize); return false; } return true; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index dd5432c3f365..cb038c8fbc9d 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -31,12 +31,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables REJECT target module"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Send RST reply */ static void send_reset(struct sk_buff *oldskb, int hook) { @@ -227,13 +221,13 @@ static bool check(const char *tablename, const struct ipt_entry *e = e_void; if (rejinfo->with == IPT_ICMP_ECHOREPLY) { - printk("REJECT: ECHOREPLY no longer supported.\n"); + printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); return false; } else if (rejinfo->with == IPT_TCP_RESET) { /* Must specify that it's a TCP packet */ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO)) { - DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n"); + printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n"); return false; } } diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 3a0d7dac0af8..97641f1a97f6 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c @@ -27,12 +27,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Josefsson "); MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static bool same_check(const char *tablename, const void *e, @@ -46,54 +40,52 @@ same_check(const char *tablename, mr->ipnum = 0; if (mr->rangesize < 1) { - DEBUGP("same_check: need at least one dest range.\n"); + pr_debug("same_check: need at least one dest range.\n"); return false; } if (mr->rangesize > IPT_SAME_MAX_RANGE) { - DEBUGP("same_check: too many ranges specified, maximum " - "is %u ranges\n", - IPT_SAME_MAX_RANGE); + pr_debug("same_check: too many ranges specified, maximum " + "is %u ranges\n", IPT_SAME_MAX_RANGE); return false; } for (count = 0; count < mr->rangesize; count++) { if (ntohl(mr->range[count].min_ip) > ntohl(mr->range[count].max_ip)) { - DEBUGP("same_check: min_ip is larger than max_ip in " - "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n", - NIPQUAD(mr->range[count].min_ip), - NIPQUAD(mr->range[count].max_ip)); + pr_debug("same_check: min_ip is larger than max_ip in " + "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n", + NIPQUAD(mr->range[count].min_ip), + NIPQUAD(mr->range[count].max_ip)); return false; } if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) { - DEBUGP("same_check: bad MAP_IPS.\n"); + pr_debug("same_check: bad MAP_IPS.\n"); return false; } rangeip = (ntohl(mr->range[count].max_ip) - ntohl(mr->range[count].min_ip) + 1); mr->ipnum += rangeip; - DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip); + pr_debug("same_check: range %u, ipnum = %u\n", count, rangeip); } - DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum); + pr_debug("same_check: total ipaddresses = %u\n", mr->ipnum); mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL); if (!mr->iparray) { - DEBUGP("same_check: Couldn't allocate %u bytes " - "for %u ipaddresses!\n", - (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); + pr_debug("same_check: Couldn't allocate %Zu bytes " + "for %u ipaddresses!\n", + (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); return false; } - DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n", - (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); + pr_debug("same_check: Allocated %Zu bytes for %u ipaddresses.\n", + (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); for (count = 0; count < mr->rangesize; count++) { for (countess = ntohl(mr->range[count].min_ip); countess <= ntohl(mr->range[count].max_ip); countess++) { mr->iparray[index] = countess; - DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' " - "in index %u.\n", - HIPQUAD(countess), index); + pr_debug("same_check: Added ipaddress `%u.%u.%u.%u' " + "in index %u.\n", HIPQUAD(countess), index); index++; } } @@ -107,8 +99,8 @@ same_destroy(const struct xt_target *target, void *targinfo) kfree(mr->iparray); - DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n", - (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); + pr_debug("same_destroy: Deallocated %Zu bytes for %u ipaddresses.\n", + (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); } static unsigned int @@ -146,10 +138,9 @@ same_target(struct sk_buff **pskb, new_ip = htonl(same->iparray[aindex]); - DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, " - "new src=%u.%u.%u.%u\n", - NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip), - NIPQUAD(new_ip)); + pr_debug("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, " + "new src=%u.%u.%u.%u\n", + NIPQUAD(t->src.u3.ip), NIPQUAD(t->dst.u3.ip), NIPQUAD(new_ip)); /* Transfer from original range. */ newrange = ((struct nf_nat_range) diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 226750d1f89b..6ca43e4ca7e3 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -55,13 +55,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); #define ULOG_NL_EVENT 111 /* Harald's favorite number */ #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ -#if 0 -#define DEBUGP(format, args...) printk("%s:%s:" format, \ - __FILE__, __FUNCTION__ , ## args) -#else -#define DEBUGP(format, args...) -#endif - #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) static unsigned int nlbufsiz = NLMSG_GOODSIZE; @@ -96,12 +89,12 @@ static void ulog_send(unsigned int nlgroupnum) ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; if (timer_pending(&ub->timer)) { - DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n"); + pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n"); del_timer(&ub->timer); } if (!ub->skb) { - DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); + pr_debug("ipt_ULOG: ulog_send: nothing to send\n"); return; } @@ -110,8 +103,8 @@ static void ulog_send(unsigned int nlgroupnum) ub->lastnlh->nlmsg_type = NLMSG_DONE; NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; - DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n", - ub->qlen, nlgroupnum + 1); + pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n", + ub->qlen, nlgroupnum + 1); netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); ub->qlen = 0; @@ -123,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum) /* timer function to flush queue in flushtimeout time */ static void ulog_timer(unsigned long data) { - DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n"); + pr_debug("ipt_ULOG: timer function called, calling ulog_send\n"); /* lock to protect against somebody modifying our structure * from ipt_ulog_target at the same time */ @@ -204,8 +197,8 @@ static void ipt_ulog_packet(unsigned int hooknum, goto alloc_failure; } - DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen, - loginfo->qthreshold); + pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen, + loginfo->qthreshold); /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */ nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, @@ -334,13 +327,13 @@ static bool ipt_ulog_checkentry(const char *tablename, const struct ipt_ulog_info *loginfo = targinfo; if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { - DEBUGP("ipt_ULOG: prefix term %i\n", - loginfo->prefix[sizeof(loginfo->prefix) - 1]); + pr_debug("ipt_ULOG: prefix term %i\n", + loginfo->prefix[sizeof(loginfo->prefix) - 1]); return false; } if (loginfo->qthreshold > ULOG_MAX_QLEN) { - DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n", - loginfo->qthreshold); + pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n", + loginfo->qthreshold); return false; } return true; @@ -405,7 +398,7 @@ static int __init ipt_ulog_init(void) { int ret, i; - DEBUGP("ipt_ULOG: init module\n"); + pr_debug("ipt_ULOG: init module\n"); if (nlbufsiz > 128*1024) { printk("Netlink buffer has to be <= 128kB\n"); @@ -437,7 +430,7 @@ static void __exit ipt_ulog_fini(void) ulog_buff_t *ub; int i; - DEBUGP("ipt_ULOG: cleanup_module\n"); + pr_debug("ipt_ULOG: cleanup_module\n"); if (nflog) nf_log_unregister(&ipt_ulog_logger); @@ -448,7 +441,7 @@ static void __exit ipt_ulog_fini(void) for (i = 0; i < ULOG_MAXNLGROUPS; i++) { ub = &ulog_buffers[i]; if (timer_pending(&ub->timer)) { - DEBUGP("timer was pending, deleting\n"); + pr_debug("timer was pending, deleting\n"); del_timer(&ub->timer); } diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index 6a3a033a6808..0106dc955a69 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c @@ -17,12 +17,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); MODULE_DESCRIPTION("iptables arbitrary IP range match module"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static bool match(const struct sk_buff *skb, const struct net_device *in, @@ -38,12 +32,12 @@ match(const struct sk_buff *skb, if ((ntohl(iph->saddr) < ntohl(info->src.min_ip) || ntohl(iph->saddr) > ntohl(info->src.max_ip)) ^ !!(info->flags & IPRANGE_SRC_INV)) { - DEBUGP("src IP %u.%u.%u.%u NOT in range %s" - "%u.%u.%u.%u-%u.%u.%u.%u\n", - NIPQUAD(iph->saddr), - info->flags & IPRANGE_SRC_INV ? "(INV) " : "", - NIPQUAD(info->src.min_ip), - NIPQUAD(info->src.max_ip)); + pr_debug("src IP %u.%u.%u.%u NOT in range %s" + "%u.%u.%u.%u-%u.%u.%u.%u\n", + NIPQUAD(iph->saddr), + info->flags & IPRANGE_SRC_INV ? "(INV) " : "", + NIPQUAD(info->src.min_ip), + NIPQUAD(info->src.max_ip)); return false; } } @@ -51,12 +45,12 @@ match(const struct sk_buff *skb, if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip) || ntohl(iph->daddr) > ntohl(info->dst.max_ip)) ^ !!(info->flags & IPRANGE_DST_INV)) { - DEBUGP("dst IP %u.%u.%u.%u NOT in range %s" - "%u.%u.%u.%u-%u.%u.%u.%u\n", - NIPQUAD(iph->daddr), - info->flags & IPRANGE_DST_INV ? "(INV) " : "", - NIPQUAD(info->dst.min_ip), - NIPQUAD(info->dst.max_ip)); + pr_debug("dst IP %u.%u.%u.%u NOT in range %s" + "%u.%u.%u.%u-%u.%u.%u.%u\n", + NIPQUAD(iph->daddr), + info->flags & IPRANGE_DST_INV ? "(INV) " : "", + NIPQUAD(info->dst.min_ip), + NIPQUAD(info->dst.max_ip)); return false; } } diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index a103f597d446..3c5629938487 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -24,12 +24,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -324,13 +318,13 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) /* We only do TCP at the moment: is there a better way? */ if (strcmp(sk->sk_prot->name, "TCP")) { - DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n"); + pr_debug("SO_ORIGINAL_DST: Not a TCP socket\n"); return -ENOPROTOOPT; } if ((unsigned int) *len < sizeof(struct sockaddr_in)) { - DEBUGP("SO_ORIGINAL_DST: len %u not %u\n", - *len, sizeof(struct sockaddr_in)); + pr_debug("SO_ORIGINAL_DST: len %d not %Zu\n", + *len, sizeof(struct sockaddr_in)); return -EINVAL; } @@ -346,17 +340,17 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) .tuple.dst.u3.ip; memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); - DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", - NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); + pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", + NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); nf_ct_put(ct); if (copy_to_user(user, &sin, sizeof(sin)) != 0) return -EFAULT; else return 0; } - DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", - NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), - NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); + pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", + NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), + NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); return -ENOENT; } diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index ab8e4c607b7a..434e08410879 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -18,12 +18,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - #ifdef CONFIG_NF_CT_ACCT static unsigned int seq_print_counters(struct seq_file *s, diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 91fb277045ef..0fe8fb0466ef 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -21,12 +21,6 @@ static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) @@ -125,8 +119,8 @@ static int icmp_new(struct nf_conn *conntrack, if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { /* Can't create a new ICMP `conn' with this. */ - DEBUGP("icmp: can't create new conn with type %u\n", - conntrack->tuplehash[0].tuple.dst.u.icmp.type); + pr_debug("icmp: can't create new conn with type %u\n", + conntrack->tuplehash[0].tuple.dst.u.icmp.type); NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); return 0; } @@ -159,8 +153,8 @@ icmp_error_message(struct sk_buff *skb, /* Ignore ICMP's containing fragments (shouldn't happen) */ if (inside->ip.frag_off & htons(IP_OFFSET)) { - DEBUGP("icmp_error_message: fragment of proto %u\n", - inside->ip.protocol); + pr_debug("icmp_error_message: fragment of proto %u\n", + inside->ip.protocol); return -NF_ACCEPT; } @@ -172,8 +166,8 @@ icmp_error_message(struct sk_buff *skb, if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, inside->ip.protocol, &origtuple, &nf_conntrack_l3proto_ipv4, innerproto)) { - DEBUGP("icmp_error_message: ! get_tuple p=%u", - inside->ip.protocol); + pr_debug("icmp_error_message: ! get_tuple p=%u", + inside->ip.protocol); return -NF_ACCEPT; } @@ -181,7 +175,7 @@ icmp_error_message(struct sk_buff *skb, been preserved inside the ICMP. */ if (!nf_ct_invert_tuple(&innertuple, &origtuple, &nf_conntrack_l3proto_ipv4, innerproto)) { - DEBUGP("icmp_error_message: no match\n"); + pr_debug("icmp_error_message: no match\n"); return -NF_ACCEPT; } @@ -196,7 +190,7 @@ icmp_error_message(struct sk_buff *skb, h = nf_conntrack_find_get(&origtuple); if (!h) { - DEBUGP("icmp_error_message: no match\n"); + pr_debug("icmp_error_message: no match\n"); return -NF_ACCEPT; } diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index f242ac61b3eb..e848d8d6292f 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -31,12 +31,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static DEFINE_RWLOCK(nf_nat_lock); static struct nf_conntrack_l3proto *l3proto = NULL; @@ -242,7 +236,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, manips not an issue. */ if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { - DEBUGP("get_unique_tuple: Found current src map\n"); + pr_debug("get_unique_tuple: Found current src map\n"); if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) if (!nf_nat_used_tuple(tuple, ct)) return; @@ -293,7 +287,7 @@ nf_nat_setup_info(struct nf_conn *ct, if (!nat) { nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); if (nat == NULL) { - DEBUGP("failed to add NAT extension\n"); + pr_debug("failed to add NAT extension\n"); return NF_ACCEPT; } } @@ -462,8 +456,9 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, return 0; } - DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n", - *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); + pr_debug("icmp_reply_translation: translating error %p manip %u " + "dir %s\n", *pskb, manip, + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); /* rcu_read_lock()ed by nf_hook_slow */ l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index cae4b460aee1..3663bd879c39 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c @@ -25,12 +25,6 @@ MODULE_AUTHOR("Rusty Russell "); MODULE_DESCRIPTION("ftp NAT helper"); MODULE_ALIAS("ip_nat_ftp"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* FIXME: Time out? --RR */ static int @@ -47,7 +41,7 @@ mangle_rfc959_packet(struct sk_buff **pskb, sprintf(buffer, "%u,%u,%u,%u,%u,%u", NIPQUAD(newip), port>>8, port&0xFF); - DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + pr_debug("calling nf_nat_mangle_tcp_packet\n"); return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, strlen(buffer)); @@ -67,7 +61,7 @@ mangle_eprt_packet(struct sk_buff **pskb, sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); - DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + pr_debug("calling nf_nat_mangle_tcp_packet\n"); return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, strlen(buffer)); @@ -87,7 +81,7 @@ mangle_epsv_packet(struct sk_buff **pskb, sprintf(buffer, "|||%u|", port); - DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + pr_debug("calling nf_nat_mangle_tcp_packet\n"); return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, strlen(buffer)); @@ -117,7 +111,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, int dir = CTINFO2DIR(ctinfo); struct nf_conn *ct = exp->master; - DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); + pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); /* Connection will come from wherever this packet goes, hence !dir */ newip = ct->tuplehash[!dir].tuple.dst.u3.ip; diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 3d760dd657c7..c1b059a73708 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -21,12 +21,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /****************************************************************************/ static int set_addr(struct sk_buff **pskb, unsigned char **data, int dataoff, @@ -126,12 +120,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, (ntohl(addr.ip) & 0xff000000) == 0x7f000000) i = 0; - DEBUGP - ("nf_nat_ras: set signal address " - "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(ip), port, - NIPQUAD(ct->tuplehash[!dir].tuple.dst. - ip), info->sig_port[!dir]); + pr_debug("nf_nat_ras: set signal address " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(addr.ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), + info->sig_port[!dir]); return set_h225_addr(pskb, data, 0, &taddr[i], &ct->tuplehash[!dir]. tuple.dst.u3, @@ -139,12 +132,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && port == info->sig_port[dir]) { /* GK->GW */ - DEBUGP - ("nf_nat_ras: set signal address " - "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(ip), port, - NIPQUAD(ct->tuplehash[!dir].tuple.src. - ip), info->sig_port[!dir]); + pr_debug("nf_nat_ras: set signal address " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(addr.ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), + info->sig_port[!dir]); return set_h225_addr(pskb, data, 0, &taddr[i], &ct->tuplehash[!dir]. tuple.src.u3, @@ -171,12 +163,11 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && port == ct->tuplehash[dir].tuple.src.u.udp.port) { - DEBUGP("nf_nat_ras: set rasAddress " - "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(ip), ntohs(port), - NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), - ntohs(ct->tuplehash[!dir].tuple.dst.u.udp. - port)); + pr_debug("nf_nat_ras: set rasAddress " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(addr.ip), ntohs(port), + NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), + ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); return set_h225_addr(pskb, data, 0, &taddr[i], &ct->tuplehash[!dir].tuple.dst.u3, ct->tuplehash[!dir].tuple. @@ -267,16 +258,16 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, } /* Success */ - DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(rtp_exp->tuple.src.ip), - ntohs(rtp_exp->tuple.src.u.udp.port), - NIPQUAD(rtp_exp->tuple.dst.ip), - ntohs(rtp_exp->tuple.dst.u.udp.port)); - DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(rtcp_exp->tuple.src.ip), - ntohs(rtcp_exp->tuple.src.u.udp.port), - NIPQUAD(rtcp_exp->tuple.dst.ip), - ntohs(rtcp_exp->tuple.dst.u.udp.port)); + pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtp_exp->tuple.src.u3.ip), + ntohs(rtp_exp->tuple.src.u.udp.port), + NIPQUAD(rtp_exp->tuple.dst.u3.ip), + ntohs(rtp_exp->tuple.dst.u.udp.port)); + pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtcp_exp->tuple.src.u3.ip), + ntohs(rtcp_exp->tuple.src.u.udp.port), + NIPQUAD(rtcp_exp->tuple.dst.u3.ip), + ntohs(rtcp_exp->tuple.dst.u.udp.port)); return 0; } @@ -317,9 +308,11 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, return -1; } - DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), - NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.u3.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.u3.ip), + ntohs(exp->tuple.dst.u.tcp.port)); return 0; } @@ -369,9 +362,11 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, return -1; } - DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), - NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.u3.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.u3.ip), + ntohs(exp->tuple.dst.u.tcp.port)); return 0; } @@ -465,9 +460,11 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, } /* Success */ - DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), - NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.u3.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.u3.ip), + ntohs(exp->tuple.dst.u.tcp.port)); return 0; } @@ -536,10 +533,12 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, } /* Success */ - DEBUGP("nf_nat_q931: expect Call Forwarding " - "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", - NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), - NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + pr_debug("nf_nat_q931: expect Call Forwarding " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.u3.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.u3.ip), + ntohs(exp->tuple.dst.u.tcp.port)); return 0; } @@ -566,8 +565,6 @@ static int __init init(void) rcu_assign_pointer(nat_h245_hook, nat_h245); rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding); rcu_assign_pointer(nat_q931_hook, nat_q931); - - DEBUGP("nf_nat_h323: init success\n"); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index f3383fc14e1c..93d8a0a8f035 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -26,13 +26,9 @@ #include #include -#if 0 -#define DEBUGP printk -#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos); -#else -#define DEBUGP(format, args...) -#define DUMP_OFFSET(x) -#endif +#define DUMP_OFFSET(x) \ + pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \ + x->offset_before, x->offset_after, x->correction_pos); static DEFINE_SPINLOCK(nf_nat_seqofs_lock); @@ -47,15 +43,15 @@ adjust_tcp_sequence(u32 seq, struct nf_nat_seq *this_way, *other_way; struct nf_conn_nat *nat = nfct_nat(ct); - DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n", - (*skb)->len, new_size); + pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", + ntohl(seq), seq); dir = CTINFO2DIR(ctinfo); this_way = &nat->seq[dir]; other_way = &nat->seq[!dir]; - DEBUGP("nf_nat_resize_packet: Seq_offset before: "); + pr_debug("nf_nat_resize_packet: Seq_offset before: "); DUMP_OFFSET(this_way); spin_lock_bh(&nf_nat_seqofs_lock); @@ -72,7 +68,7 @@ adjust_tcp_sequence(u32 seq, } spin_unlock_bh(&nf_nat_seqofs_lock); - DEBUGP("nf_nat_resize_packet: Seq_offset after: "); + pr_debug("nf_nat_resize_packet: Seq_offset after: "); DUMP_OFFSET(this_way); } @@ -100,14 +96,12 @@ static void mangle_contents(struct sk_buff *skb, /* update skb info */ if (rep_len > match_len) { - DEBUGP("nf_nat_mangle_packet: Extending packet by " - "%u from %u bytes\n", rep_len - match_len, - skb->len); + pr_debug("nf_nat_mangle_packet: Extending packet by " + "%u from %u bytes\n", rep_len - match_len, skb->len); skb_put(skb, rep_len - match_len); } else { - DEBUGP("nf_nat_mangle_packet: Shrinking packet from " - "%u from %u bytes\n", match_len - rep_len, - skb->len); + pr_debug("nf_nat_mangle_packet: Shrinking packet from " + "%u from %u bytes\n", match_len - rep_len, skb->len); __skb_trim(skb, skb->len + rep_len - match_len); } @@ -320,9 +314,9 @@ sack_adjust(struct sk_buff *skb, new_end_seq = htonl(ntohl(sack->end_seq) - natseq->offset_before); - DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", - ntohl(sack->start_seq), new_start_seq, - ntohl(sack->end_seq), new_end_seq); + pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", + ntohl(sack->start_seq), new_start_seq, + ntohl(sack->end_seq), new_end_seq); nf_proto_csum_replace4(&tcph->check, skb, sack->start_seq, new_start_seq, 0); @@ -414,9 +408,9 @@ nf_nat_seq_adjust(struct sk_buff **pskb, nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); - DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", - ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), - ntohl(newack)); + pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", + ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), + ntohl(newack)); tcph->seq = newseq; tcph->ack_seq = newack; diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index db7fbf66fec0..bcf274bba602 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c @@ -22,12 +22,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) NAT helper"); MODULE_LICENSE("GPL"); @@ -44,9 +38,6 @@ static unsigned int help(struct sk_buff **pskb, u_int16_t port; unsigned int ret; - DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", - expect->seq, exp_irc_info->len, ntohl(tcph->seq)); - /* Reply comes from server. */ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; exp->dir = IP_CT_DIR_REPLY; @@ -64,8 +55,8 @@ static unsigned int help(struct sk_buff **pskb, ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip); sprintf(buffer, "%u %u", ip, port); - DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", - buffer, NIPQUAD(ip), port); + pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", + buffer, NIPQUAD(ip), port); ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, matchoff, matchlen, buffer, diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index deb80ae2831e..984ec8308b2e 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -37,14 +37,6 @@ MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); MODULE_ALIAS("ip_nat_pptp"); -#if 0 -extern const char *pptp_msg_name[]; -#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ - __FUNCTION__, ## args) -#else -#define DEBUGP(format, args...) -#endif - static void pptp_nat_expected(struct nf_conn *ct, struct nf_conntrack_expect *exp) { @@ -60,7 +52,7 @@ static void pptp_nat_expected(struct nf_conn *ct, /* And here goes the grand finale of corrosion... */ if (exp->dir == IP_CT_DIR_ORIGINAL) { - DEBUGP("we are PNS->PAC\n"); + pr_debug("we are PNS->PAC\n"); /* therefore, build tuple for PAC->PNS */ t.src.l3num = AF_INET; t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; @@ -69,7 +61,7 @@ static void pptp_nat_expected(struct nf_conn *ct, t.dst.u.gre.key = ct_pptp_info->pns_call_id; t.dst.protonum = IPPROTO_GRE; } else { - DEBUGP("we are PAC->PNS\n"); + pr_debug("we are PAC->PNS\n"); /* build tuple for PNS->PAC */ t.src.l3num = AF_INET; t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; @@ -79,15 +71,15 @@ static void pptp_nat_expected(struct nf_conn *ct, t.dst.protonum = IPPROTO_GRE; } - DEBUGP("trying to unexpect other dir: "); + pr_debug("trying to unexpect other dir: "); NF_CT_DUMP_TUPLE(&t); other_exp = nf_ct_expect_find_get(&t); if (other_exp) { nf_ct_unexpect_related(other_exp); nf_ct_expect_put(other_exp); - DEBUGP("success\n"); + pr_debug("success\n"); } else { - DEBUGP("not found!\n"); + pr_debug("not found!\n"); } /* This must be a fresh one. */ @@ -161,9 +153,9 @@ pptp_outbound_pkt(struct sk_buff **pskb, cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); break; default: - DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, - (msg <= PPTP_MSG_MAX)? - pptp_msg_name[msg]:pptp_msg_name[0]); + pr_debug("unknown outbound packet 0x%04x:%s\n", msg, + msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : + pptp_msg_name[0]); /* fall through */ case PPTP_SET_LINK_INFO: /* only need to NAT in case PAC is behind NAT box */ @@ -179,8 +171,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass * down to here */ - DEBUGP("altering call id from 0x%04x to 0x%04x\n", - ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); + pr_debug("altering call id from 0x%04x to 0x%04x\n", + ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); /* mangle packet */ if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, @@ -255,8 +247,9 @@ pptp_inbound_pkt(struct sk_buff **pskb, pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); break; default: - DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? - pptp_msg_name[msg]:pptp_msg_name[0]); + pr_debug("unknown inbound packet %s\n", + msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : + pptp_msg_name[0]); /* fall through */ case PPTP_START_SESSION_REQUEST: case PPTP_START_SESSION_REPLY: @@ -272,8 +265,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ /* mangle packet */ - DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", - ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); + pr_debug("altering peer call id from 0x%04x to 0x%04x\n", + ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, pcid_off + sizeof(struct pptp_pkt_hdr) + diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index c3908bc5a709..2e40cc83526a 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c @@ -36,13 +36,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); -#if 0 -#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ - __FUNCTION__, ## args) -#else -#define DEBUGP(x, args...) -#endif - /* is key in given range between min and max */ static int gre_in_range(const struct nf_conntrack_tuple *tuple, @@ -83,7 +76,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, keyptr = &tuple->dst.u.gre.key; if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { - DEBUGP("%p: NATing GRE PPTP\n", conntrack); + pr_debug("%p: NATing GRE PPTP\n", conntrack); min = 1; range_size = 0xffff; } else { @@ -91,7 +84,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, range_size = ntohs(range->max.gre.key) - min + 1; } - DEBUGP("min = %u, range_size = %u\n", min, range_size); + pr_debug("min = %u, range_size = %u\n", min, range_size); for (i = 0; i < range_size; i++, key++) { *keyptr = htons(min + key % range_size); @@ -99,7 +92,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, return 1; } - DEBUGP("%p: no NAT mapping\n", conntrack); + pr_debug("%p: no NAT mapping\n", conntrack); return 0; } @@ -132,11 +125,11 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, * Try to behave like "nf_nat_proto_unknown" */ break; case GRE_VERSION_PPTP: - DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); + pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); pgreh->call_id = tuple->dst.u.gre.key; break; default: - DEBUGP("can't nat unknown GRE version\n"); + pr_debug("can't nat unknown GRE version\n"); return 0; } return 1; diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 080393a143d7..0f45427e5fdc 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -24,12 +24,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - #define NAT_VALID_HOOKS ((1<"); MODULE_DESCRIPTION("SIP NAT helper"); MODULE_ALIAS("ip_nat_sip"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - struct addr_map { struct { char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; @@ -257,8 +251,6 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, __be32 newip; u_int16_t port; - DEBUGP("ip_nat_sdp():\n"); - /* Connection will come from reply */ if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip) diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 30eeaa4c645c..332814dac503 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -27,12 +27,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - #ifdef CONFIG_XFRM static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) { @@ -117,7 +111,7 @@ nf_nat_fn(unsigned int hooknum, if (!nat) { nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); if (nat == NULL) { - DEBUGP("failed to add NAT extension\n"); + pr_debug("failed to add NAT extension\n"); return NF_ACCEPT; } } @@ -154,9 +148,9 @@ nf_nat_fn(unsigned int hooknum, return ret; } } else - DEBUGP("Already setup manip %s for ct %p\n", - maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", - ct); + pr_debug("Already setup manip %s for ct %p\n", + maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", + ct); break; default: @@ -270,7 +264,7 @@ nf_nat_adjust(unsigned int hooknum, ct = nf_ct_get(*pskb, &ctinfo); if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { - DEBUGP("nf_nat_standalone: adjusting sequence number\n"); + pr_debug("nf_nat_standalone: adjusting sequence number\n"); if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) return NF_DROP; } diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 540bf14b851c..b05327ebd332 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -32,12 +32,6 @@ struct in_device; #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Use lock to serialize, so printks don't overlap */ static DEFINE_SPINLOCK(log_lock); @@ -466,12 +460,12 @@ static bool ip6t_log_checkentry(const char *tablename, const struct ip6t_log_info *loginfo = targinfo; if (loginfo->level >= 8) { - DEBUGP("LOG: level %u >= 8\n", loginfo->level); + pr_debug("LOG: level %u >= 8\n", loginfo->level); return false; } if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { - DEBUGP("LOG: prefix term %i\n", - loginfo->prefix[sizeof(loginfo->prefix)-1]); + pr_debug("LOG: prefix term %i\n", + loginfo->prefix[sizeof(loginfo->prefix)-1]); return false; } return true; diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 14008dc6a197..2f487cda3b6b 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -34,12 +34,6 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI "); MODULE_DESCRIPTION("IP6 tables REJECT target module"); MODULE_LICENSE("GPL"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Send RST reply */ static void send_reset(struct sk_buff *oldskb) { @@ -54,7 +48,7 @@ static void send_reset(struct sk_buff *oldskb) if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { - DEBUGP("ip6t_REJECT: addr is not unicast.\n"); + pr_debug("ip6t_REJECT: addr is not unicast.\n"); return; } @@ -62,7 +56,7 @@ static void send_reset(struct sk_buff *oldskb) tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); if ((tcphoff < 0) || (tcphoff > oldskb->len)) { - DEBUGP("ip6t_REJECT: Can't get TCP header.\n"); + pr_debug("ip6t_REJECT: Can't get TCP header.\n"); return; } @@ -70,8 +64,9 @@ static void send_reset(struct sk_buff *oldskb) /* IP header checks: fragment, too short. */ if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { - DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n", - proto, otcplen); + pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, " + "or too short. otcplen = %d\n", + proto, otcplen); return; } @@ -80,14 +75,14 @@ static void send_reset(struct sk_buff *oldskb) /* No RST for RST. */ if (otcph.rst) { - DEBUGP("ip6t_REJECT: RST is set\n"); + pr_debug("ip6t_REJECT: RST is set\n"); return; } /* Check checksum. */ if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, skb_checksum(oldskb, tcphoff, otcplen, 0))) { - DEBUGP("ip6t_REJECT: TCP checksum is invalid\n"); + pr_debug("ip6t_REJECT: TCP checksum is invalid\n"); return; } @@ -186,7 +181,7 @@ static unsigned int reject6_target(struct sk_buff **pskb, { const struct ip6t_reject_info *reject = targinfo; - DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__); + pr_debug("%s: medium point\n", __FUNCTION__); /* WARNING: This code causes reentry within ip6tables. This means that the ip6tables jump stack is now crap. We must return an absolute verdict. --RR */ @@ -237,7 +232,7 @@ static bool check(const char *tablename, /* Must specify that it's a TCP packet */ if (e->ipv6.proto != IPPROTO_TCP || (e->ipv6.invflags & XT_INV_PROTO)) { - DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); + printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); return false; } } diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index a9fe2aa97072..2a25fe25e0e0 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -23,21 +23,16 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 AH match"); MODULE_AUTHOR("Andras Kis-Szabo "); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Returns 1 if the spi is matched by the range, 0 otherwise */ static inline bool spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) { bool r; - DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', - min,spi,max); + + pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x", + invert ? '!' : ' ', min, spi, max); r = (spi >= min && spi <= max) ^ invert; - DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n"); + pr_debug(" result %s\n", r ? "PASS" : "FAILED"); return r; } @@ -73,22 +68,22 @@ match(const struct sk_buff *skb, hdrlen = (ah->hdrlen + 2) << 2; - DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); - DEBUGP("RES %04X ", ah->reserved); - DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); - - DEBUGP("IPv6 AH spi %02X ", - spi_match(ahinfo->spis[0], ahinfo->spis[1], - ntohl(ah->spi), - !!(ahinfo->invflags & IP6T_AH_INV_SPI))); - DEBUGP("len %02X %04X %02X ", - ahinfo->hdrlen, hdrlen, - (!ahinfo->hdrlen || - (ahinfo->hdrlen == hdrlen) ^ - !!(ahinfo->invflags & IP6T_AH_INV_LEN))); - DEBUGP("res %02X %04X %02X\n", - ahinfo->hdrres, ah->reserved, - !(ahinfo->hdrres && ah->reserved)); + pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); + pr_debug("RES %04X ", ah->reserved); + pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); + + pr_debug("IPv6 AH spi %02X ", + spi_match(ahinfo->spis[0], ahinfo->spis[1], + ntohl(ah->spi), + !!(ahinfo->invflags & IP6T_AH_INV_SPI))); + pr_debug("len %02X %04X %02X ", + ahinfo->hdrlen, hdrlen, + (!ahinfo->hdrlen || + (ahinfo->hdrlen == hdrlen) ^ + !!(ahinfo->invflags & IP6T_AH_INV_LEN))); + pr_debug("res %02X %04X %02X\n", + ahinfo->hdrres, ah->reserved, + !(ahinfo->hdrres && ah->reserved)); return (ah != NULL) && @@ -114,7 +109,7 @@ checkentry(const char *tablename, const struct ip6t_ah *ahinfo = matchinfo; if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { - DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags); + pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags); return false; } return true; diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index bb1cfa82b47c..968aeba02073 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -22,21 +22,15 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 FRAG match"); MODULE_AUTHOR("Andras Kis-Szabo "); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Returns 1 if the id is matched by the range, 0 otherwise */ static inline bool id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) { bool r; - DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', - min, id, max); + pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', + min, id, max); r = (id >= min && id <= max) ^ invert; - DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); + pr_debug(" result %s\n", r ? "PASS" : "FAILED"); return r; } @@ -69,37 +63,37 @@ match(const struct sk_buff *skb, return false; } - DEBUGP("INFO %04X ", fh->frag_off); - DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); - DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); - DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF)); - DEBUGP("ID %u %08X\n", ntohl(fh->identification), - ntohl(fh->identification)); - - DEBUGP("IPv6 FRAG id %02X ", - id_match(fraginfo->ids[0], fraginfo->ids[1], - ntohl(fh->identification), - !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))); - DEBUGP("res %02X %02X%04X %02X ", - fraginfo->flags & IP6T_FRAG_RES, fh->reserved, - ntohs(fh->frag_off) & 0x6, - !((fraginfo->flags & IP6T_FRAG_RES) - && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); - DEBUGP("first %02X %02X %02X ", - fraginfo->flags & IP6T_FRAG_FST, - ntohs(fh->frag_off) & ~0x7, - !((fraginfo->flags & IP6T_FRAG_FST) - && (ntohs(fh->frag_off) & ~0x7))); - DEBUGP("mf %02X %02X %02X ", - fraginfo->flags & IP6T_FRAG_MF, - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_MF) - && !((ntohs(fh->frag_off) & IP6_MF)))); - DEBUGP("last %02X %02X %02X\n", - fraginfo->flags & IP6T_FRAG_NMF, - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_NMF) - && (ntohs(fh->frag_off) & IP6_MF))); + pr_debug("INFO %04X ", fh->frag_off); + pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); + pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); + pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF)); + pr_debug("ID %u %08X\n", ntohl(fh->identification), + ntohl(fh->identification)); + + pr_debug("IPv6 FRAG id %02X ", + id_match(fraginfo->ids[0], fraginfo->ids[1], + ntohl(fh->identification), + !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))); + pr_debug("res %02X %02X%04X %02X ", + fraginfo->flags & IP6T_FRAG_RES, fh->reserved, + ntohs(fh->frag_off) & 0x6, + !((fraginfo->flags & IP6T_FRAG_RES) + && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); + pr_debug("first %02X %02X %02X ", + fraginfo->flags & IP6T_FRAG_FST, + ntohs(fh->frag_off) & ~0x7, + !((fraginfo->flags & IP6T_FRAG_FST) + && (ntohs(fh->frag_off) & ~0x7))); + pr_debug("mf %02X %02X %02X ", + fraginfo->flags & IP6T_FRAG_MF, + ntohs(fh->frag_off) & IP6_MF, + !((fraginfo->flags & IP6T_FRAG_MF) + && !((ntohs(fh->frag_off) & IP6_MF)))); + pr_debug("last %02X %02X %02X\n", + fraginfo->flags & IP6T_FRAG_NMF, + ntohs(fh->frag_off) & IP6_MF, + !((fraginfo->flags & IP6T_FRAG_NMF) + && (ntohs(fh->frag_off) & IP6_MF))); return (fh != NULL) && @@ -131,7 +125,7 @@ checkentry(const char *tablename, const struct ip6t_frag *fraginfo = matchinfo; if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { - DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags); + pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags); return false; } return true; diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 6247d4cdad99..e6ca6018b1ea 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -25,12 +25,6 @@ MODULE_DESCRIPTION("IPv6 opts match"); MODULE_AUTHOR("Andras Kis-Szabo "); MODULE_ALIAS("ip6t_dst"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* * (Type & 0xC0) >> 6 * 0 -> ignorable @@ -90,13 +84,13 @@ match(const struct sk_buff *skb, return false; } - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); + pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); - DEBUGP("len %02X %04X %02X ", - optinfo->hdrlen, hdrlen, - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); + pr_debug("len %02X %04X %02X ", + optinfo->hdrlen, hdrlen, + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); ret = (oh != NULL) && (!(optinfo->flags & IP6T_OPTS_LEN) || @@ -108,10 +102,10 @@ match(const struct sk_buff *skb, if (!(optinfo->flags & IP6T_OPTS_OPTS)) { return ret; } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { - DEBUGP("Not strict - not implemented"); + pr_debug("Not strict - not implemented"); } else { - DEBUGP("Strict "); - DEBUGP("#%d ", optinfo->optsnr); + pr_debug("Strict "); + pr_debug("#%d ", optinfo->optsnr); for (temp = 0; temp < optinfo->optsnr; temp++) { /* type field exists ? */ if (hdrlen < 1) @@ -123,12 +117,11 @@ match(const struct sk_buff *skb, /* Type check */ if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { - DEBUGP("Tbad %02X %02X\n", - *tp, - (optinfo->opts[temp] & 0xFF00) >> 8); + pr_debug("Tbad %02X %02X\n", *tp, + (optinfo->opts[temp] & 0xFF00) >> 8); return false; } else { - DEBUGP("Tok "); + pr_debug("Tok "); } /* Length check */ if (*tp) { @@ -145,23 +138,23 @@ match(const struct sk_buff *skb, spec_len = optinfo->opts[temp] & 0x00FF; if (spec_len != 0x00FF && spec_len != *lp) { - DEBUGP("Lbad %02X %04X\n", *lp, - spec_len); + pr_debug("Lbad %02X %04X\n", *lp, + spec_len); return false; } - DEBUGP("Lok "); + pr_debug("Lok "); optlen = *lp + 2; } else { - DEBUGP("Pad1\n"); + pr_debug("Pad1\n"); optlen = 1; } /* Step to the next */ - DEBUGP("len%04X \n", optlen); + pr_debug("len%04X \n", optlen); if ((ptr > skb->len - optlen || hdrlen < optlen) && temp < optinfo->optsnr - 1) { - DEBUGP("new pointer is too large! \n"); + pr_debug("new pointer is too large! \n"); break; } ptr += optlen; @@ -187,7 +180,7 @@ checkentry(const char *tablename, const struct ip6t_opts *optsinfo = matchinfo; if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { - DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); + pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); return false; } return true; diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 549deea26418..357cea703bd9 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -24,21 +24,15 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 RT match"); MODULE_AUTHOR("Andras Kis-Szabo "); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Returns 1 if the id is matched by the range, 0 otherwise */ static inline bool segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) { bool r; - DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", - invert ? '!' : ' ', min, id, max); + pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", + invert ? '!' : ' ', min, id, max); r = (id >= min && id <= max) ^ invert; - DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); + pr_debug(" result %s\n", r ? "PASS" : "FAILED"); return r; } @@ -82,29 +76,29 @@ match(const struct sk_buff *skb, return false; } - DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); - DEBUGP("TYPE %04X ", rh->type); - DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); - - DEBUGP("IPv6 RT segsleft %02X ", - segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], - rh->segments_left, - !!(rtinfo->invflags & IP6T_RT_INV_SGS))); - DEBUGP("type %02X %02X %02X ", - rtinfo->rt_type, rh->type, - (!(rtinfo->flags & IP6T_RT_TYP) || - ((rtinfo->rt_type == rh->type) ^ - !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); - DEBUGP("len %02X %04X %02X ", - rtinfo->hdrlen, hdrlen, - !(rtinfo->flags & IP6T_RT_LEN) || - ((rtinfo->hdrlen == hdrlen) ^ - !!(rtinfo->invflags & IP6T_RT_INV_LEN))); - DEBUGP("res %02X %02X %02X ", - rtinfo->flags & IP6T_RT_RES, - ((const struct rt0_hdr *)rh)->reserved, - !((rtinfo->flags & IP6T_RT_RES) && - (((const struct rt0_hdr *)rh)->reserved))); + pr_debug("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); + pr_debug("TYPE %04X ", rh->type); + pr_debug("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); + + pr_debug("IPv6 RT segsleft %02X ", + segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], + rh->segments_left, + !!(rtinfo->invflags & IP6T_RT_INV_SGS))); + pr_debug("type %02X %02X %02X ", + rtinfo->rt_type, rh->type, + (!(rtinfo->flags & IP6T_RT_TYP) || + ((rtinfo->rt_type == rh->type) ^ + !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); + pr_debug("len %02X %04X %02X ", + rtinfo->hdrlen, hdrlen, + !(rtinfo->flags & IP6T_RT_LEN) || + ((rtinfo->hdrlen == hdrlen) ^ + !!(rtinfo->invflags & IP6T_RT_INV_LEN))); + pr_debug("res %02X %02X %02X ", + rtinfo->flags & IP6T_RT_RES, + ((const struct rt0_hdr *)rh)->reserved, + !((rtinfo->flags & IP6T_RT_RES) && + (((const struct rt0_hdr *)rh)->reserved))); ret = (rh != NULL) && @@ -131,18 +125,18 @@ match(const struct sk_buff *skb, ret = (*rp == 0); } - DEBUGP("#%d ", rtinfo->addrnr); + pr_debug("#%d ", rtinfo->addrnr); if (!(rtinfo->flags & IP6T_RT_FST)) { return ret; } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { - DEBUGP("Not strict "); + pr_debug("Not strict "); if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { - DEBUGP("There isn't enough space\n"); + pr_debug("There isn't enough space\n"); return false; } else { unsigned int i = 0; - DEBUGP("#%d ", rtinfo->addrnr); + pr_debug("#%d ", rtinfo->addrnr); for (temp = 0; temp < (unsigned int)((hdrlen - 8) / 16); temp++) { @@ -156,25 +150,25 @@ match(const struct sk_buff *skb, BUG_ON(ap == NULL); if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) { - DEBUGP("i=%d temp=%d;\n", i, temp); + pr_debug("i=%d temp=%d;\n", i, temp); i++; } if (i == rtinfo->addrnr) break; } - DEBUGP("i=%d #%d\n", i, rtinfo->addrnr); + pr_debug("i=%d #%d\n", i, rtinfo->addrnr); if (i == rtinfo->addrnr) return ret; else return false; } } else { - DEBUGP("Strict "); + pr_debug("Strict "); if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { - DEBUGP("There isn't enough space\n"); + pr_debug("There isn't enough space\n"); return false; } else { - DEBUGP("#%d ", rtinfo->addrnr); + pr_debug("#%d ", rtinfo->addrnr); for (temp = 0; temp < rtinfo->addrnr; temp++) { ap = skb_header_pointer(skb, ptr @@ -187,7 +181,7 @@ match(const struct sk_buff *skb, if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp])) break; } - DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr); + pr_debug("temp=%d #%d\n", temp, rtinfo->addrnr); if (temp == rtinfo->addrnr && temp == (unsigned int)((hdrlen - 8) / 16)) return ret; @@ -210,14 +204,14 @@ checkentry(const char *tablename, const struct ip6t_rt *rtinfo = matchinfo; if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { - DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags); + pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags); return false; } if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && (!(rtinfo->flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP))) { - DEBUGP("`--rt-type 0' required before `--rt-0-*'"); + pr_debug("`--rt-type 0' required before `--rt-0-*'"); return false; } diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index f2d26495f413..f0a9efa67fb5 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -21,12 +21,6 @@ MODULE_DESCRIPTION("ip6tables mangle table"); (1 << NF_IP6_LOCAL_OUT) | \ (1 << NF_IP6_POST_ROUTING)) -#if 0 -#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args) -#else -#define DEBUGP(x, args...) -#endif - static struct { struct ip6t_replace repl; diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 0acda45d455d..ec290e4ebdd8 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -8,12 +8,6 @@ #define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT)) -#if 0 -#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args) -#else -#define DEBUGP(x, args...) -#endif - static struct { struct ip6t_replace repl; diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 747b01e53132..89e20ab494b8 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -26,12 +26,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -136,7 +130,7 @@ ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, * except of IPv6 & ext headers. but it's tracked anyway. - YK */ if ((protoff < 0) || (protoff > (*pskb)->len)) { - DEBUGP("ip6_conntrack_core: can't find proto in pkt\n"); + pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); NF_CT_STAT_INC_ATOMIC(error); NF_CT_STAT_INC_ATOMIC(invalid); return -NF_ACCEPT; @@ -178,7 +172,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, (*pskb)->len - extoff); if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { - DEBUGP("proto header not found\n"); + pr_debug("proto header not found\n"); return NF_ACCEPT; } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index a514661d25dd..9defc7e14554 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -27,12 +27,6 @@ static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int icmpv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) @@ -125,8 +119,8 @@ static int icmpv6_new(struct nf_conn *conntrack, if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { /* Can't create a new ICMPv6 `conn' with this. */ - DEBUGP("icmpv6: can't create new conn with type %u\n", - type + 128); + pr_debug("icmpv6: can't create new conn with type %u\n", + type + 128); NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); return 0; } @@ -152,14 +146,15 @@ icmpv6_error_message(struct sk_buff *skb, hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr); if (hp == NULL) { - DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n"); + pr_debug("icmpv6_error: Can't get ICMPv6 hdr.\n"); return -NF_ACCEPT; } inip6off = icmp6off + sizeof(_hdr); if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr), &inprotonum, sizeof(inprotonum)) != 0) { - DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n"); + pr_debug("icmpv6_error: Can't get nexthdr in inner IPv6 " + "header.\n"); return -NF_ACCEPT; } inprotoff = nf_ct_ipv6_skip_exthdr(skb, @@ -169,7 +164,8 @@ icmpv6_error_message(struct sk_buff *skb, - sizeof(struct ipv6hdr)); if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) { - DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n"); + pr_debug("icmpv6_error: Can't get protocol header in ICMPv6 " + "payload.\n"); return -NF_ACCEPT; } @@ -179,7 +175,7 @@ icmpv6_error_message(struct sk_buff *skb, /* Are they talking about one of our connections? */ if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) { - DEBUGP("icmpv6_error: Can't get tuple\n"); + pr_debug("icmpv6_error: Can't get tuple\n"); return -NF_ACCEPT; } @@ -187,7 +183,7 @@ icmpv6_error_message(struct sk_buff *skb, been preserved inside the ICMP. */ if (!nf_ct_invert_tuple(&intuple, &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) { - DEBUGP("icmpv6_error: Can't invert tuple\n"); + pr_debug("icmpv6_error: Can't invert tuple\n"); return -NF_ACCEPT; } @@ -195,7 +191,7 @@ icmpv6_error_message(struct sk_buff *skb, h = nf_conntrack_find_get(&intuple); if (!h) { - DEBUGP("icmpv6_error: no match\n"); + pr_debug("icmpv6_error: no match\n"); return -NF_ACCEPT; } else { if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 347ab7608231..25442a8c1ba8 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -44,12 +44,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */ #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT @@ -343,7 +337,7 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str struct nf_ct_frag6_queue *fq; if ((fq = frag_alloc_queue()) == NULL) { - DEBUGP("Can't alloc new queue\n"); + pr_debug("Can't alloc new queue\n"); goto oom; } @@ -393,7 +387,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, int offset, end; if (fq->last_in & COMPLETE) { - DEBUGP("Allready completed\n"); + pr_debug("Allready completed\n"); goto err; } @@ -402,7 +396,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); if ((unsigned int)end > IPV6_MAXPLEN) { - DEBUGP("offset is too large.\n"); + pr_debug("offset is too large.\n"); return -1; } @@ -420,7 +414,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, */ if (end < fq->len || ((fq->last_in & LAST_IN) && end != fq->len)) { - DEBUGP("already received last fragment\n"); + pr_debug("already received last fragment\n"); goto err; } fq->last_in |= LAST_IN; @@ -433,13 +427,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, /* RFC2460 says always send parameter problem in * this case. -DaveM */ - DEBUGP("the end of this fragment is not rounded to 8 bytes.\n"); + pr_debug("end of fragment not rounded to 8 bytes.\n"); return -1; } if (end > fq->len) { /* Some bits beyond end -> corruption. */ if (fq->last_in & LAST_IN) { - DEBUGP("last packet already reached.\n"); + pr_debug("last packet already reached.\n"); goto err; } fq->len = end; @@ -451,11 +445,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, /* Point into the IP datagram 'data' part. */ if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) { - DEBUGP("queue: message is too short.\n"); + pr_debug("queue: message is too short.\n"); goto err; } if (pskb_trim_rcsum(skb, end - offset)) { - DEBUGP("Can't trim\n"); + pr_debug("Can't trim\n"); goto err; } @@ -480,11 +474,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, if (i > 0) { offset += i; if (end <= offset) { - DEBUGP("overlap\n"); + pr_debug("overlap\n"); goto err; } if (!pskb_pull(skb, i)) { - DEBUGP("Can't pull\n"); + pr_debug("Can't pull\n"); goto err; } if (skb->ip_summed != CHECKSUM_UNNECESSARY) @@ -503,7 +497,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, /* Eat head of the next overlapped fragment * and leave the loop. The next ones cannot overlap. */ - DEBUGP("Eat head of the overlapped parts.: %d", i); + pr_debug("Eat head of the overlapped parts.: %d", i); if (!pskb_pull(next, i)) goto err; @@ -586,13 +580,13 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr)); if (payload_len > IPV6_MAXPLEN) { - DEBUGP("payload len is too large.\n"); + pr_debug("payload len is too large.\n"); goto out_oversize; } /* Head of list must not be cloned. */ if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) { - DEBUGP("skb is cloned but can't expand head"); + pr_debug("skb is cloned but can't expand head"); goto out_oom; } @@ -604,7 +598,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) int i, plen = 0; if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) { - DEBUGP("Can't alloc skb\n"); + pr_debug("Can't alloc skb\n"); goto out_oom; } clone->next = head->next; @@ -719,11 +713,11 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) return -1; } if (len < (int)sizeof(struct ipv6_opt_hdr)) { - DEBUGP("too short\n"); + pr_debug("too short\n"); return -1; } if (nexthdr == NEXTHDR_NONE) { - DEBUGP("next header is none\n"); + pr_debug("next header is none\n"); return -1; } if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) @@ -764,7 +758,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) /* Jumbo payload inhibits frag. header */ if (ipv6_hdr(skb)->payload_len == 0) { - DEBUGP("payload len = 0\n"); + pr_debug("payload len = 0\n"); return skb; } @@ -773,14 +767,14 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) clone = skb_clone(skb, GFP_ATOMIC); if (clone == NULL) { - DEBUGP("Can't clone skb\n"); + pr_debug("Can't clone skb\n"); return skb; } NFCT_FRAG6_CB(clone)->orig = skb; if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) { - DEBUGP("message is too short.\n"); + pr_debug("message is too short.\n"); goto ret_orig; } @@ -789,7 +783,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) fhdr = (struct frag_hdr *)skb_transport_header(clone); if (!(fhdr->frag_off & htons(0xFFF9))) { - DEBUGP("Invalid fragment offset\n"); + pr_debug("Invalid fragment offset\n"); /* It is not a fragmented frame */ goto ret_orig; } @@ -799,7 +793,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); if (fq == NULL) { - DEBUGP("Can't find and can't create new queue\n"); + pr_debug("Can't find and can't create new queue\n"); goto ret_orig; } @@ -807,7 +801,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { spin_unlock(&fq->lock); - DEBUGP("Can't insert skb to queue\n"); + pr_debug("Can't insert skb to queue\n"); fq_put(fq, NULL); goto ret_orig; } @@ -815,7 +809,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) { ret_skb = nf_ct_frag6_reasm(fq, dev); if (ret_skb == NULL) - DEBUGP("Can't reassemble fragmented packets\n"); + pr_debug("Can't reassemble fragmented packets\n"); } spin_unlock(&fq->lock); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 472396dac05c..3d1411012a2c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -40,12 +40,6 @@ #define NF_CONNTRACK_VERSION "0.5.0" -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - DEFINE_RWLOCK(nf_conntrack_lock); EXPORT_SYMBOL_GPL(nf_conntrack_lock); @@ -141,7 +135,7 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); static void clean_from_lists(struct nf_conn *ct) { - DEBUGP("clean_from_lists(%p)\n", ct); + pr_debug("clean_from_lists(%p)\n", ct); hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); @@ -155,7 +149,7 @@ destroy_conntrack(struct nf_conntrack *nfct) struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conntrack_l4proto *l4proto; - DEBUGP("destroy_conntrack(%p)\n", ct); + pr_debug("destroy_conntrack(%p)\n", ct); NF_CT_ASSERT(atomic_read(&nfct->use) == 0); NF_CT_ASSERT(!timer_pending(&ct->timeout)); @@ -194,7 +188,7 @@ destroy_conntrack(struct nf_conntrack *nfct) if (ct->master) nf_ct_put(ct->master); - DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct); + pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct); nf_conntrack_free(ct); } @@ -313,7 +307,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) /* No external references means noone else could have confirmed us. */ NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); - DEBUGP("Confirming conntrack %p\n", ct); + pr_debug("Confirming conntrack %p\n", ct); write_lock_bh(&nf_conntrack_lock); @@ -446,7 +440,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC); if (conntrack == NULL) { - DEBUGP("nf_conntrack_alloc: Can't alloc conntrack.\n"); + pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); atomic_dec(&nf_conntrack_count); return ERR_PTR(-ENOMEM); } @@ -485,27 +479,27 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, struct nf_conntrack_expect *exp; if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { - DEBUGP("Can't invert tuple.\n"); + pr_debug("Can't invert tuple.\n"); return NULL; } conntrack = nf_conntrack_alloc(tuple, &repl_tuple); if (conntrack == NULL || IS_ERR(conntrack)) { - DEBUGP("Can't allocate conntrack.\n"); + pr_debug("Can't allocate conntrack.\n"); return (struct nf_conntrack_tuple_hash *)conntrack; } if (!l4proto->new(conntrack, skb, dataoff)) { nf_conntrack_free(conntrack); - DEBUGP("init conntrack: can't track with proto module\n"); + pr_debug("init conntrack: can't track with proto module\n"); return NULL; } write_lock_bh(&nf_conntrack_lock); exp = nf_ct_find_expectation(tuple); if (exp) { - DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", - conntrack, exp); + pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", + conntrack, exp); /* Welcome, Mr. Bond. We've been expecting you... */ __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = exp->master; @@ -568,7 +562,7 @@ resolve_normal_ct(struct sk_buff *skb, if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num, protonum, &tuple, l3proto, l4proto)) { - DEBUGP("resolve_normal_ct: Can't get tuple\n"); + pr_debug("resolve_normal_ct: Can't get tuple\n"); return NULL; } @@ -591,13 +585,14 @@ resolve_normal_ct(struct sk_buff *skb, } else { /* Once we've had two way comms, always ESTABLISHED. */ if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { - DEBUGP("nf_conntrack_in: normal packet for %p\n", ct); + pr_debug("nf_conntrack_in: normal packet for %p\n", ct); *ctinfo = IP_CT_ESTABLISHED; } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) { - DEBUGP("nf_conntrack_in: related packet for %p\n", ct); + pr_debug("nf_conntrack_in: related packet for %p\n", + ct); *ctinfo = IP_CT_RELATED; } else { - DEBUGP("nf_conntrack_in: new packet for %p\n", ct); + pr_debug("nf_conntrack_in: new packet for %p\n", ct); *ctinfo = IP_CT_NEW; } *set_reply = 0; @@ -629,7 +624,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) l3proto = __nf_ct_l3proto_find((u_int16_t)pf); if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) { - DEBUGP("not prepared to track yet or error occured\n"); + pr_debug("not prepared to track yet or error occured\n"); return -ret; } @@ -665,7 +660,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) if (ret < 0) { /* Invalid: inverse of the return code tells * the netfilter core what to do */ - DEBUGP("nf_conntrack_in: Can't track with proto module\n"); + pr_debug("nf_conntrack_in: Can't track with proto module\n"); nf_conntrack_put((*pskb)->nfct); (*pskb)->nfct = NULL; NF_CT_STAT_INC_ATOMIC(invalid); @@ -706,7 +701,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, /* Should be unconfirmed, so not in hash table yet */ NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); - DEBUGP("Altering reply tuple of %p to ", ct); + pr_debug("Altering reply tuple of %p to ", ct); NF_CT_DUMP_TUPLE(newreply); ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index cd9c2d00cc09..c763ee74ea02 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -51,12 +51,6 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, struct nf_conntrack_expect *exp); EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, @@ -138,13 +132,13 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[], if (*data == term && i == array_size - 1) return len; - DEBUGP("Char %u (got %u nums) `%u' unexpected\n", - len, i, *data); + pr_debug("Char %u (got %u nums) `%u' unexpected\n", + len, i, *data); return 0; } } - DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep); - + pr_debug("Failed to fill %u numbers separated by %c\n", + array_size, sep); return 0; } @@ -178,13 +172,13 @@ static int get_port(const char *data, int start, size_t dlen, char delim, if (tmp_port == 0) break; *port = htons(tmp_port); - DEBUGP("get_port: return %d\n", tmp_port); + pr_debug("get_port: return %d\n", tmp_port); return i + 1; } else if (data[i] >= '0' && data[i] <= '9') tmp_port = tmp_port*10 + data[i] - '0'; else { /* Some other crap */ - DEBUGP("get_port: invalid char.\n"); + pr_debug("get_port: invalid char.\n"); break; } } @@ -201,22 +195,22 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, /* First character is delimiter, then "1" for IPv4 or "2" for IPv6, then delimiter again. */ if (dlen <= 3) { - DEBUGP("EPRT: too short\n"); + pr_debug("EPRT: too short\n"); return 0; } delim = data[0]; if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) { - DEBUGP("try_eprt: invalid delimitter.\n"); + pr_debug("try_eprt: invalid delimitter.\n"); return 0; } if ((cmd->l3num == PF_INET && data[1] != '1') || (cmd->l3num == PF_INET6 && data[1] != '2')) { - DEBUGP("EPRT: invalid protocol number.\n"); + pr_debug("EPRT: invalid protocol number.\n"); return 0; } - DEBUGP("EPRT: Got %c%c%c\n", delim, data[1], delim); + pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim); if (data[1] == '1') { u_int32_t array[4]; @@ -234,7 +228,7 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, if (length == 0) return 0; - DEBUGP("EPRT: Got IP address!\n"); + pr_debug("EPRT: Got IP address!\n"); /* Start offset includes initial "|1|", and trailing delimiter */ return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port); } @@ -267,7 +261,7 @@ static int find_pattern(const char *data, size_t dlen, { size_t i; - DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen); + pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen); if (dlen == 0) return 0; @@ -282,17 +276,17 @@ static int find_pattern(const char *data, size_t dlen, #if 0 size_t i; - DEBUGP("ftp: string mismatch\n"); + pr_debug("ftp: string mismatch\n"); for (i = 0; i < plen; i++) { - DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n", - i, data[i], data[i], - pattern[i], pattern[i]); + pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n", + i, data[i], data[i], + pattern[i], pattern[i]); } #endif return 0; } - DEBUGP("Pattern matches!\n"); + pr_debug("Pattern matches!\n"); /* Now we've found the constant string, try to skip to the 'skip' character */ for (i = plen; data[i] != skip; i++) @@ -301,14 +295,14 @@ static int find_pattern(const char *data, size_t dlen, /* Skip over the last character */ i++; - DEBUGP("Skipped up to `%c'!\n", skip); + pr_debug("Skipped up to `%c'!\n", skip); *numoff = i; *numlen = getnum(data + i, dlen - i, cmd, term); if (!*numlen) return -1; - DEBUGP("Match succeeded!\n"); + pr_debug("Match succeeded!\n"); return 1; } @@ -373,7 +367,7 @@ static int help(struct sk_buff **pskb, /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { - DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo); + pr_debug("ftp: Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } @@ -384,8 +378,8 @@ static int help(struct sk_buff **pskb, dataoff = protoff + th->doff * 4; /* No data? */ if (dataoff >= (*pskb)->len) { - DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, - (*pskb)->len); + pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, + (*pskb)->len); return NF_ACCEPT; } datalen = (*pskb)->len - dataoff; @@ -400,11 +394,11 @@ static int help(struct sk_buff **pskb, /* Look up to see if we're just after a \n. */ if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { /* Now if this ends in \n, update ftp info. */ - DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n", - ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", - ct_ftp_info->seq_aft_nl[dir][0], - ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)", - ct_ftp_info->seq_aft_nl[dir][1]); + pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", + ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", + ct_ftp_info->seq_aft_nl[dir][0], + ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)", + ct_ftp_info->seq_aft_nl[dir][1]); ret = NF_ACCEPT; goto out_update_nl; } @@ -442,9 +436,9 @@ static int help(struct sk_buff **pskb, goto out_update_nl; } - DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", - (int)matchlen, fb_ptr + matchoff, - matchlen, ntohl(th->seq) + matchoff); + pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", + matchlen, fb_ptr + matchoff, + matchlen, ntohl(th->seq) + matchoff); exp = nf_ct_expect_alloc(ct); if (exp == NULL) { @@ -466,14 +460,16 @@ static int help(struct sk_buff **pskb, different IP address. Simply don't record it for NAT. */ if (cmd.l3num == PF_INET) { - DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n", - NIPQUAD(cmd.u3.ip), - NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); + pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT + " != " NIPQUAD_FMT "\n", + NIPQUAD(cmd.u3.ip), + NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); } else { - DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n", - NIP6(*((struct in6_addr *)cmd.u3.ip6)), - NIP6(*((struct in6_addr *)ct->tuplehash[dir] - .tuple.src.u3.ip6))); + pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT + " != " NIP6_FMT "\n", + NIP6(*((struct in6_addr *)cmd.u3.ip6)), + NIP6(*((struct in6_addr *) + ct->tuplehash[dir].tuple.src.u3.ip6))); } /* Thanks to Cristiano Lincoln Mattos @@ -530,9 +526,9 @@ static void nf_conntrack_ftp_fini(void) if (ftp[i][j].me == NULL) continue; - DEBUGP("nf_ct_ftp: unregistering helper for pf: %d " - "port: %d\n", - ftp[i][j].tuple.src.l3num, ports[i]); + pr_debug("nf_ct_ftp: unregistering helper for pf: %d " + "port: %d\n", + ftp[i][j].tuple.src.l3num, ports[i]); nf_conntrack_helper_unregister(&ftp[i][j]); } } @@ -571,9 +567,9 @@ static int __init nf_conntrack_ftp_init(void) sprintf(tmpname, "ftp-%d", ports[i]); ftp[i][j].name = tmpname; - DEBUGP("nf_ct_ftp: registering helper for pf: %d " - "port: %d\n", - ftp[i][j].tuple.src.l3num, ports[i]); + pr_debug("nf_ct_ftp: registering helper for pf: %d " + "port: %d\n", + ftp[i][j].tuple.src.l3num, ports[i]); ret = nf_conntrack_helper_register(&ftp[i][j]); if (ret) { printk("nf_ct_ftp: failed to register helper " diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index aa5ba99b7a08..a8a9dfbe7a67 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -31,12 +31,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - /* Parameters */ static unsigned int default_rrq_ttl __read_mostly = 300; module_param(default_rrq_ttl, uint, 0600); @@ -150,9 +144,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) { /* Netmeeting sends TPKT header and data separately */ if (info->tpkt_len[dir] > 0) { - DEBUGP("nf_ct_h323: previous packet " - "indicated separate TPKT data of %hu " - "bytes\n", info->tpkt_len[dir]); + pr_debug("nf_ct_h323: previous packet " + "indicated separate TPKT data of %hu " + "bytes\n", info->tpkt_len[dir]); if (info->tpkt_len[dir] <= tcpdatalen) { /* Yes, there was a TPKT header * received */ @@ -163,7 +157,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, } /* Fragmented TPKT */ - DEBUGP("nf_ct_h323: fragmented TPKT\n"); + pr_debug("nf_ct_h323: fragmented TPKT\n"); goto clear_out; } @@ -190,9 +184,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, if (tpktlen > tcpdatalen) { if (tcpdatalen == 4) { /* Separate TPKT header */ /* Netmeeting sends TPKT header and data separately */ - DEBUGP("nf_ct_h323: separate TPKT header indicates " - "there will be TPKT data of %hu bytes\n", - tpktlen - 4); + pr_debug("nf_ct_h323: separate TPKT header indicates " + "there will be TPKT data of %hu bytes\n", + tpktlen - 4); info->tpkt_len[dir] = tpktlen - 4; return 0; } @@ -308,9 +302,9 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, } else { /* Conntrack only */ if (nf_ct_expect_related(rtp_exp) == 0) { if (nf_ct_expect_related(rtcp_exp) == 0) { - DEBUGP("nf_ct_h323: expect RTP "); + pr_debug("nf_ct_h323: expect RTP "); NF_CT_DUMP_TUPLE(&rtp_exp->tuple); - DEBUGP("nf_ct_h323: expect RTCP "); + pr_debug("nf_ct_h323: expect RTCP "); NF_CT_DUMP_TUPLE(&rtcp_exp->tuple); } else { nf_ct_unexpect_related(rtp_exp); @@ -365,7 +359,7 @@ static int expect_t120(struct sk_buff **pskb, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_h323: expect T.120 "); + pr_debug("nf_ct_h323: expect T.120 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -413,7 +407,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, { int ret; - DEBUGP("nf_ct_h323: OpenLogicalChannel\n"); + pr_debug("nf_ct_h323: OpenLogicalChannel\n"); if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) @@ -473,7 +467,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, H2250LogicalChannelAckParameters *ack; int ret; - DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n"); + pr_debug("nf_ct_h323: OpenLogicalChannelAck\n"); if ((olca->options & eOpenLogicalChannelAck_reverseLogicalChannelParameters) && @@ -544,8 +538,8 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, return process_olc(pskb, ct, ctinfo, data, dataoff, &mscm->request.openLogicalChannel); } - DEBUGP("nf_ct_h323: H.245 Request %d\n", - mscm->request.choice); + pr_debug("nf_ct_h323: H.245 Request %d\n", + mscm->request.choice); break; case eMultimediaSystemControlMessage_response: if (mscm->response.choice == @@ -554,11 +548,11 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, &mscm->response. openLogicalChannelAck); } - DEBUGP("nf_ct_h323: H.245 Response %d\n", - mscm->response.choice); + pr_debug("nf_ct_h323: H.245 Response %d\n", + mscm->response.choice); break; default: - DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice); + pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice); break; } @@ -580,23 +574,23 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { return NF_ACCEPT; } - DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len); + pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len); spin_lock_bh(&nf_h323_lock); /* Process each TPKT */ while (get_tpkt_data(pskb, protoff, ct, ctinfo, &data, &datalen, &dataoff)) { - DEBUGP("nf_ct_h245: TPKT len=%d ", datalen); + pr_debug("nf_ct_h245: TPKT len=%d ", datalen); NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); /* Decode H.245 signal */ ret = DecodeMultimediaSystemControlMessage(data, datalen, &mscm); if (ret < 0) { - DEBUGP("nf_ct_h245: decoding error: %s\n", - ret == H323_ERROR_BOUND ? - "out of bound" : "out of range"); + pr_debug("nf_ct_h245: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); /* We don't drop when decoding error */ break; } @@ -697,7 +691,7 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_q931: expect H.245 "); + pr_debug("nf_ct_q931: expect H.245 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -786,7 +780,7 @@ static int expect_callforwarding(struct sk_buff **pskb, if (callforward_filter && callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, ct->tuplehash[!dir].tuple.src.l3num)) { - DEBUGP("nf_ct_q931: Call Forwarding not tracked\n"); + pr_debug("nf_ct_q931: Call Forwarding not tracked\n"); return 0; } @@ -808,7 +802,7 @@ static int expect_callforwarding(struct sk_buff **pskb, taddr, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_q931: expect Call Forwarding "); + pr_debug("nf_ct_q931: expect Call Forwarding "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -832,7 +826,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, union nf_conntrack_address addr; typeof(set_h225_addr_hook) set_h225_addr; - DEBUGP("nf_ct_q931: Setup\n"); + pr_debug("nf_ct_q931: Setup\n"); if (setup->options & eSetup_UUIE_h245Address) { ret = expect_h245(pskb, ct, ctinfo, data, dataoff, @@ -847,11 +841,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, get_h225_addr(ct, *data, &setup->destCallSignalAddress, &addr, &port) && memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { - DEBUGP("nf_ct_q931: set destCallSignalAddress " - NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", - NIP6(*(struct in6_addr *)&addr), ntohs(port), - NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), - ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); + pr_debug("nf_ct_q931: set destCallSignalAddress " + NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", + NIP6(*(struct in6_addr *)&addr), ntohs(port), + NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), + ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); ret = set_h225_addr(pskb, data, dataoff, &setup->destCallSignalAddress, &ct->tuplehash[!dir].tuple.src.u3, @@ -865,11 +859,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, &addr, &port) && memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { - DEBUGP("nf_ct_q931: set sourceCallSignalAddress " - NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", - NIP6(*(struct in6_addr *)&addr), ntohs(port), - NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), - ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); + pr_debug("nf_ct_q931: set sourceCallSignalAddress " + NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", + NIP6(*(struct in6_addr *)&addr), ntohs(port), + NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), + ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); ret = set_h225_addr(pskb, data, dataoff, &setup->sourceCallSignalAddress, &ct->tuplehash[!dir].tuple.dst.u3, @@ -900,7 +894,7 @@ static int process_callproceeding(struct sk_buff **pskb, int ret; int i; - DEBUGP("nf_ct_q931: CallProceeding\n"); + pr_debug("nf_ct_q931: CallProceeding\n"); if (callproc->options & eCallProceeding_UUIE_h245Address) { ret = expect_h245(pskb, ct, ctinfo, data, dataoff, @@ -930,7 +924,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, int ret; int i; - DEBUGP("nf_ct_q931: Connect\n"); + pr_debug("nf_ct_q931: Connect\n"); if (connect->options & eConnect_UUIE_h245Address) { ret = expect_h245(pskb, ct, ctinfo, data, dataoff, @@ -960,7 +954,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, int ret; int i; - DEBUGP("nf_ct_q931: Alerting\n"); + pr_debug("nf_ct_q931: Alerting\n"); if (alert->options & eAlerting_UUIE_h245Address) { ret = expect_h245(pskb, ct, ctinfo, data, dataoff, @@ -990,7 +984,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, int ret; int i; - DEBUGP("nf_ct_q931: Facility\n"); + pr_debug("nf_ct_q931: Facility\n"); if (facility->reason.choice == eFacilityReason_callForwarded) { if (facility->options & eFacility_UUIE_alternativeAddress) @@ -1029,7 +1023,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, int ret; int i; - DEBUGP("nf_ct_q931: Progress\n"); + pr_debug("nf_ct_q931: Progress\n"); if (progress->options & eProgress_UUIE_h245Address) { ret = expect_h245(pskb, ct, ctinfo, data, dataoff, @@ -1086,8 +1080,8 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, &pdu->h323_message_body.progress); break; default: - DEBUGP("nf_ct_q931: Q.931 signal %d\n", - pdu->h323_message_body.choice); + pr_debug("nf_ct_q931: Q.931 signal %d\n", + pdu->h323_message_body.choice); break; } @@ -1121,22 +1115,22 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { return NF_ACCEPT; } - DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len); + pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len); spin_lock_bh(&nf_h323_lock); /* Process each TPKT */ while (get_tpkt_data(pskb, protoff, ct, ctinfo, &data, &datalen, &dataoff)) { - DEBUGP("nf_ct_q931: TPKT len=%d ", datalen); + pr_debug("nf_ct_q931: TPKT len=%d ", datalen); NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); /* Decode Q.931 signal */ ret = DecodeQ931(data, datalen, &q931); if (ret < 0) { - DEBUGP("nf_ct_q931: decoding error: %s\n", - ret == H323_ERROR_BOUND ? - "out of bound" : "out of range"); + pr_debug("nf_ct_q931: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); /* We don't drop when decoding error */ break; } @@ -1274,7 +1268,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_ras: expect Q.931 "); + pr_debug("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); /* Save port for looking up expect in processing RCF */ @@ -1295,7 +1289,7 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, { typeof(set_ras_addr_hook) set_ras_addr; - DEBUGP("nf_ct_ras: GRQ\n"); + pr_debug("nf_ct_ras: GRQ\n"); set_ras_addr = rcu_dereference(set_ras_addr_hook); if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ @@ -1315,7 +1309,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, union nf_conntrack_address addr; struct nf_conntrack_expect *exp; - DEBUGP("nf_ct_ras: GCF\n"); + pr_debug("nf_ct_ras: GCF\n"); if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port)) return 0; @@ -1338,7 +1332,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, exp->helper = nf_conntrack_helper_ras; if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_ras: expect RAS "); + pr_debug("nf_ct_ras: expect RAS "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -1357,7 +1351,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, int ret; typeof(set_ras_addr_hook) set_ras_addr; - DEBUGP("nf_ct_ras: RRQ\n"); + pr_debug("nf_ct_ras: RRQ\n"); ret = expect_q931(pskb, ct, ctinfo, data, rrq->callSignalAddress.item, @@ -1375,7 +1369,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, } if (rrq->options & eRegistrationRequest_timeToLive) { - DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); + pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); info->timeout = rrq->timeToLive; } else info->timeout = default_rrq_ttl; @@ -1394,7 +1388,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, struct nf_conntrack_expect *exp; typeof(set_sig_addr_hook) set_sig_addr; - DEBUGP("nf_ct_ras: RCF\n"); + pr_debug("nf_ct_ras: RCF\n"); set_sig_addr = rcu_dereference(set_sig_addr_hook); if (set_sig_addr && ct->status & IPS_NAT_MASK) { @@ -1406,14 +1400,13 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, } if (rcf->options & eRegistrationConfirm_timeToLive) { - DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); + pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); info->timeout = rcf->timeToLive; } if (info->timeout > 0) { - DEBUGP - ("nf_ct_ras: set RAS connection timeout to %u seconds\n", - info->timeout); + pr_debug("nf_ct_ras: set RAS connection timeout to " + "%u seconds\n", info->timeout); nf_ct_refresh(ct, *pskb, info->timeout * HZ); /* Set expect timeout */ @@ -1421,9 +1414,9 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, info->sig_port[!dir]); if (exp) { - DEBUGP("nf_ct_ras: set Q.931 expect " - "timeout to %u seconds for", - info->timeout); + pr_debug("nf_ct_ras: set Q.931 expect " + "timeout to %u seconds for", + info->timeout); NF_CT_DUMP_TUPLE(&exp->tuple); set_expect_timeout(exp, info->timeout); } @@ -1443,7 +1436,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, int ret; typeof(set_sig_addr_hook) set_sig_addr; - DEBUGP("nf_ct_ras: URQ\n"); + pr_debug("nf_ct_ras: URQ\n"); set_sig_addr = rcu_dereference(set_sig_addr_hook); if (set_sig_addr && ct->status & IPS_NAT_MASK) { @@ -1476,7 +1469,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, union nf_conntrack_address addr; typeof(set_h225_addr_hook) set_h225_addr; - DEBUGP("nf_ct_ras: ARQ\n"); + pr_debug("nf_ct_ras: ARQ\n"); set_h225_addr = rcu_dereference(set_h225_addr_hook); if ((arq->options & eAdmissionRequest_destCallSignalAddress) && @@ -1519,7 +1512,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, struct nf_conntrack_expect *exp; typeof(set_sig_addr_hook) set_sig_addr; - DEBUGP("nf_ct_ras: ACF\n"); + pr_debug("nf_ct_ras: ACF\n"); if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress, &addr, &port)) @@ -1544,7 +1537,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, exp->helper = nf_conntrack_helper_q931; if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_ras: expect Q.931 "); + pr_debug("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -1561,7 +1554,7 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, { typeof(set_ras_addr_hook) set_ras_addr; - DEBUGP("nf_ct_ras: LRQ\n"); + pr_debug("nf_ct_ras: LRQ\n"); set_ras_addr = rcu_dereference(set_ras_addr_hook); if (set_ras_addr && ct->status & IPS_NAT_MASK) @@ -1581,7 +1574,7 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, union nf_conntrack_address addr; struct nf_conntrack_expect *exp; - DEBUGP("nf_ct_ras: LCF\n"); + pr_debug("nf_ct_ras: LCF\n"); if (!get_h225_addr(ct, *data, &lcf->callSignalAddress, &addr, &port)) @@ -1597,7 +1590,7 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, exp->helper = nf_conntrack_helper_q931; if (nf_ct_expect_related(exp) == 0) { - DEBUGP("nf_ct_ras: expect Q.931 "); + pr_debug("nf_ct_ras: expect Q.931 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; @@ -1618,7 +1611,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, typeof(set_ras_addr_hook) set_ras_addr; typeof(set_sig_addr_hook) set_sig_addr; - DEBUGP("nf_ct_ras: IRR\n"); + pr_debug("nf_ct_ras: IRR\n"); set_ras_addr = rcu_dereference(set_ras_addr_hook); if (set_ras_addr && ct->status & IPS_NAT_MASK) { @@ -1677,7 +1670,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, return process_irr(pskb, ct, ctinfo, data, &ras->infoRequestResponse); default: - DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice); + pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); break; } @@ -1693,7 +1686,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, int datalen = 0; int ret; - DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len); + pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len); spin_lock_bh(&nf_h323_lock); @@ -1701,15 +1694,15 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, data = get_udp_data(pskb, protoff, &datalen); if (data == NULL) goto accept; - DEBUGP("nf_ct_ras: RAS message len=%d ", datalen); + pr_debug("nf_ct_ras: RAS message len=%d ", datalen); NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); /* Decode RAS message */ ret = DecodeRasMessage(data, datalen, &ras); if (ret < 0) { - DEBUGP("nf_ct_ras: decoding error: %s\n", - ret == H323_ERROR_BOUND ? - "out of bound" : "out of range"); + pr_debug("nf_ct_ras: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); goto accept; } @@ -1760,7 +1753,7 @@ static void __exit nf_conntrack_h323_fini(void) nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); kfree(h323_buffer); - DEBUGP("nf_ct_h323: fini\n"); + pr_debug("nf_ct_h323: fini\n"); } /****************************************************************************/ @@ -1783,7 +1776,7 @@ static int __init nf_conntrack_h323_init(void) ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); if (ret < 0) goto err4; - DEBUGP("nf_ct_h323: init success\n"); + pr_debug("nf_ct_h323: init success\n"); return 0; err4: diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 8c7340794bf6..1562ca97a349 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -55,13 +56,6 @@ static const char *dccprotos[] = { #define MINMATCHLEN 5 -#if 0 -#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \ - __FILE__, __FUNCTION__ , ## args) -#else -#define DEBUGP(format, args...) -#endif - /* tries to get the ip_addr and port out of a dcc command * return value: -1 on failure, 0 on success * data pointer to first byte of DCC command data @@ -99,6 +93,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff; + struct iphdr *iph; struct tcphdr _tcph, *th; char *data, *data_limit, *ib_ptr; int dir = CTINFO2DIR(ctinfo); @@ -148,9 +143,10 @@ static int help(struct sk_buff **pskb, unsigned int protoff, data += 5; /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ - DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n", - NIPQUAD(iph->saddr), ntohs(th->source), - NIPQUAD(iph->daddr), ntohs(th->dest)); + iph = ip_hdr(*pskb); + pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", + NIPQUAD(iph->saddr), ntohs(th->source), + NIPQUAD(iph->daddr), ntohs(th->dest)); for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { @@ -158,18 +154,18 @@ static int help(struct sk_buff **pskb, unsigned int protoff, continue; } data += strlen(dccprotos[i]); - DEBUGP("DCC %s detected\n", dccprotos[i]); + pr_debug("DCC %s detected\n", dccprotos[i]); /* we have at least * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid * data left (== 14/13 bytes) */ if (parse_dcc((char *)data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { - DEBUGP("unable to parse dcc command\n"); + pr_debug("unable to parse dcc command\n"); continue; } - DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n", - HIPQUAD(dcc_ip), dcc_port); + pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n", + HIPQUAD(dcc_ip), dcc_port); /* dcc_ip can be the internal OR external (NAT'ed) IP */ tuple = &ct->tuplehash[dir].tuple; diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 2fd0f11b8fb2..b1bfa207a850 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -31,12 +31,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 63dac5eb959f..b0804199ab59 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -65,7 +65,7 @@ void struct nf_conntrack_expect *exp) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); -#if 0 +#ifdef DEBUG /* PptpControlMessageType names */ const char *pptp_msg_name[] = { "UNKNOWN_MESSAGE", @@ -86,9 +86,6 @@ const char *pptp_msg_name[] = { "SET_LINK_INFO" }; EXPORT_SYMBOL(pptp_msg_name); -#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) -#else -#define DEBUGP(format, args...) #endif #define SECS *HZ @@ -102,7 +99,7 @@ static void pptp_expectfn(struct nf_conn *ct, struct nf_conntrack_expect *exp) { typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn; - DEBUGP("increasing timeouts\n"); + pr_debug("increasing timeouts\n"); /* increase timeout of GRE data channel conntrack entry */ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; @@ -121,17 +118,17 @@ static void pptp_expectfn(struct nf_conn *ct, /* obviously this tuple inversion only works until you do NAT */ nf_ct_invert_tuplepr(&inv_t, &exp->tuple); - DEBUGP("trying to unexpect other dir: "); + pr_debug("trying to unexpect other dir: "); NF_CT_DUMP_TUPLE(&inv_t); exp_other = nf_ct_expect_find_get(&inv_t); if (exp_other) { /* delete other expectation. */ - DEBUGP("found\n"); + pr_debug("found\n"); nf_ct_unexpect_related(exp_other); nf_ct_expect_put(exp_other); } else { - DEBUGP("not found\n"); + pr_debug("not found\n"); } } rcu_read_unlock(); @@ -143,13 +140,13 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) struct nf_conntrack_expect *exp; struct nf_conn *sibling; - DEBUGP("trying to timeout ct or exp for tuple "); + pr_debug("trying to timeout ct or exp for tuple "); NF_CT_DUMP_TUPLE(t); h = nf_conntrack_find_get(t); if (h) { sibling = nf_ct_tuplehash_to_ctrack(h); - DEBUGP("setting timeout of conntrack %p to 0\n", sibling); + pr_debug("setting timeout of conntrack %p to 0\n", sibling); sibling->proto.gre.timeout = 0; sibling->proto.gre.stream_timeout = 0; if (del_timer(&sibling->timeout)) @@ -159,7 +156,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) } else { exp = nf_ct_expect_find_get(t); if (exp) { - DEBUGP("unexpect_related of expect %p\n", exp); + pr_debug("unexpect_related of expect %p\n", exp); nf_ct_unexpect_related(exp); nf_ct_expect_put(exp); return 1; @@ -182,7 +179,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; if (!destroy_sibling_or_exp(&t)) - DEBUGP("failed to timeout original pns->pac ct/exp\n"); + pr_debug("failed to timeout original pns->pac ct/exp\n"); /* try reply (pac->pns) tuple */ memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); @@ -190,7 +187,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; if (!destroy_sibling_or_exp(&t)) - DEBUGP("failed to timeout reply pac->pns ct/exp\n"); + pr_debug("failed to timeout reply pac->pns ct/exp\n"); } /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ @@ -270,7 +267,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; msg = ntohs(ctlh->messageType); - DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); + pr_debug("inbound control message %s\n", pptp_msg_name[msg]); switch (msg) { case PPTP_START_SESSION_REPLY: @@ -305,8 +302,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, pcid = pptpReq->ocack.peersCallID; if (info->pns_call_id != pcid) goto invalid; - DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], - ntohs(cid), ntohs(pcid)); + pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], + ntohs(cid), ntohs(pcid)); if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { info->cstate = PPTP_CALL_OUT_CONF; @@ -322,7 +319,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, goto invalid; cid = pptpReq->icreq.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); info->cstate = PPTP_CALL_IN_REQ; info->pac_call_id = cid; break; @@ -341,7 +338,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, if (info->pns_call_id != pcid) goto invalid; - DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); + pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); info->cstate = PPTP_CALL_IN_CONF; /* we expect a GRE connection from PAC to PNS */ @@ -351,7 +348,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, case PPTP_CALL_DISCONNECT_NOTIFY: /* server confirms disconnect */ cid = pptpReq->disc.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); info->cstate = PPTP_CALL_NONE; /* untrack this call id, unexpect GRE packets */ @@ -374,11 +371,11 @@ pptp_inbound_pkt(struct sk_buff **pskb, return NF_ACCEPT; invalid: - DEBUGP("invalid %s: type=%d cid=%u pcid=%u " - "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", - msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], - msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, - ntohs(info->pns_call_id), ntohs(info->pac_call_id)); + pr_debug("invalid %s: type=%d cid=%u pcid=%u " + "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", + msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], + msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, + ntohs(info->pns_call_id), ntohs(info->pac_call_id)); return NF_ACCEPT; } @@ -396,7 +393,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; msg = ntohs(ctlh->messageType); - DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); + pr_debug("outbound control message %s\n", pptp_msg_name[msg]); switch (msg) { case PPTP_START_SESSION_REQUEST: @@ -418,7 +415,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, info->cstate = PPTP_CALL_OUT_REQ; /* track PNS call id */ cid = pptpReq->ocreq.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); info->pns_call_id = cid; break; @@ -432,8 +429,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, pcid = pptpReq->icack.peersCallID; if (info->pac_call_id != pcid) goto invalid; - DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], - ntohs(cid), ntohs(pcid)); + pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], + ntohs(cid), ntohs(pcid)); if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { /* part two of the three-way handshake */ @@ -469,11 +466,11 @@ pptp_outbound_pkt(struct sk_buff **pskb, return NF_ACCEPT; invalid: - DEBUGP("invalid %s: type=%d cid=%u pcid=%u " - "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", - msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], - msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, - ntohs(info->pns_call_id), ntohs(info->pac_call_id)); + pr_debug("invalid %s: type=%d cid=%u pcid=%u " + "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", + msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], + msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, + ntohs(info->pns_call_id), ntohs(info->pac_call_id)); return NF_ACCEPT; } @@ -524,7 +521,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); if (!pptph) { - DEBUGP("no full PPTP header, can't track\n"); + pr_debug("no full PPTP header, can't track\n"); return NF_ACCEPT; } nexthdr_off += sizeof(_pptph); @@ -533,7 +530,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, /* if it's not a control message we can't do anything with it */ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { - DEBUGP("not a control packet\n"); + pr_debug("not a control packet\n"); return NF_ACCEPT; } @@ -569,8 +566,8 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, /* server -> client (PAC -> PNS) */ ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, ctinfo); - DEBUGP("sstate: %d->%d, cstate: %d->%d\n", - oldsstate, info->sstate, oldcstate, info->cstate); + pr_debug("sstate: %d->%d, cstate: %d->%d\n", + oldsstate, info->sstate, oldcstate, info->cstate); spin_unlock_bh(&nf_pptp_lock); return ret; diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 339c397d1b5f..771c4c29936e 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -40,12 +40,6 @@ #define GRE_TIMEOUT (30 * HZ) #define GRE_STREAM_TIMEOUT (180 * HZ) -#if 0 -#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) -#else -#define DEBUGP(x, args...) -#endif - static DEFINE_RWLOCK(nf_ct_gre_lock); static LIST_HEAD(gre_keymap_list); @@ -87,7 +81,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t) } read_unlock_bh(&nf_ct_gre_lock); - DEBUGP("lookup src key 0x%x for ", key); + pr_debug("lookup src key 0x%x for ", key); NF_CT_DUMP_TUPLE(t); return key; @@ -107,8 +101,8 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, if (gre_key_cmpfn(km, t) && km == *kmp) return 0; } - DEBUGP("trying to override keymap_%s for ct %p\n", - dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); + pr_debug("trying to override keymap_%s for ct %p\n", + dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); return -EEXIST; } @@ -118,7 +112,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, memcpy(&km->tuple, t, sizeof(*t)); *kmp = km; - DEBUGP("adding new entry %p: ", km); + pr_debug("adding new entry %p: ", km); NF_CT_DUMP_TUPLE(&km->tuple); write_lock_bh(&nf_ct_gre_lock); @@ -135,13 +129,13 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct) struct nf_conn_help *help = nfct_help(ct); enum ip_conntrack_dir dir; - DEBUGP("entering for ct %p\n", ct); + pr_debug("entering for ct %p\n", ct); write_lock_bh(&nf_ct_gre_lock); for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { if (help->help.ct_pptp_info.keymap[dir]) { - DEBUGP("removing %p from list\n", - help->help.ct_pptp_info.keymap[dir]); + pr_debug("removing %p from list\n", + help->help.ct_pptp_info.keymap[dir]); list_del(&help->help.ct_pptp_info.keymap[dir]->list); kfree(help->help.ct_pptp_info.keymap[dir]); help->help.ct_pptp_info.keymap[dir] = NULL; @@ -186,7 +180,7 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb, return 1; if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { - DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); + pr_debug("GRE_VERSION_PPTP but unknown proto\n"); return 0; } @@ -242,7 +236,7 @@ static int gre_packet(struct nf_conn *ct, static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { - DEBUGP(": "); + pr_debug(": "); NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); /* initialize to sane value. Ideally a conntrack helper @@ -258,10 +252,10 @@ static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, static void gre_destroy(struct nf_conn *ct) { struct nf_conn *master = ct->master; - DEBUGP(" entering\n"); + pr_debug(" entering\n"); if (!master) - DEBUGP("no master !?!\n"); + pr_debug("no master !?!\n"); else nf_ct_gre_keymap_destroy(master); } diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 0d3254b974c5..265769e5002b 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -25,12 +25,6 @@ #include #include -#if 0 -#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__) -#else -#define DEBUGP(format, args...) -#endif - /* Protects conntrack->proto.sctp */ static DEFINE_RWLOCK(sctp_lock); @@ -151,9 +145,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb, { sctp_sctphdr_t _hdr, *hp; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - /* Actually only need first 8 bytes. */ hp = skb_header_pointer(skb, dataoff, 8, &_hdr); if (hp == NULL) @@ -167,9 +158,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb, static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *orig) { - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - tuple->src.u.sctp.port = orig->dst.u.sctp.port; tuple->dst.u.sctp.port = orig->src.u.sctp.port; return 1; @@ -179,9 +167,6 @@ static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple, static int sctp_print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple) { - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - return seq_printf(s, "sport=%hu dport=%hu ", ntohs(tuple->src.u.sctp.port), ntohs(tuple->dst.u.sctp.port)); @@ -193,9 +178,6 @@ static int sctp_print_conntrack(struct seq_file *s, { enum sctp_conntrack state; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - read_lock_bh(&sctp_lock); state = conntrack->proto.sctp.state; read_unlock_bh(&sctp_lock); @@ -219,13 +201,10 @@ static int do_basic_checks(struct nf_conn *conntrack, sctp_chunkhdr_t _sch, *sch; int flag; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - flag = 0; for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { - DEBUGP("Chunk Num: %d Type: %d\n", count, sch->type); + pr_debug("Chunk Num: %d Type: %d\n", count, sch->type); if (sch->type == SCTP_CID_INIT || sch->type == SCTP_CID_INIT_ACK @@ -242,7 +221,7 @@ static int do_basic_checks(struct nf_conn *conntrack, || sch->type == SCTP_CID_COOKIE_ECHO || flag) && count !=0) || !sch->length) { - DEBUGP("Basic checks failed\n"); + pr_debug("Basic checks failed\n"); return 1; } @@ -251,7 +230,7 @@ static int do_basic_checks(struct nf_conn *conntrack, } } - DEBUGP("Basic checks passed\n"); + pr_debug("Basic checks passed\n"); return count == 0; } @@ -261,50 +240,47 @@ static int new_state(enum ip_conntrack_dir dir, { int i; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - - DEBUGP("Chunk type: %d\n", chunk_type); + pr_debug("Chunk type: %d\n", chunk_type); switch (chunk_type) { case SCTP_CID_INIT: - DEBUGP("SCTP_CID_INIT\n"); + pr_debug("SCTP_CID_INIT\n"); i = 0; break; case SCTP_CID_INIT_ACK: - DEBUGP("SCTP_CID_INIT_ACK\n"); + pr_debug("SCTP_CID_INIT_ACK\n"); i = 1; break; case SCTP_CID_ABORT: - DEBUGP("SCTP_CID_ABORT\n"); + pr_debug("SCTP_CID_ABORT\n"); i = 2; break; case SCTP_CID_SHUTDOWN: - DEBUGP("SCTP_CID_SHUTDOWN\n"); + pr_debug("SCTP_CID_SHUTDOWN\n"); i = 3; break; case SCTP_CID_SHUTDOWN_ACK: - DEBUGP("SCTP_CID_SHUTDOWN_ACK\n"); + pr_debug("SCTP_CID_SHUTDOWN_ACK\n"); i = 4; break; case SCTP_CID_ERROR: - DEBUGP("SCTP_CID_ERROR\n"); + pr_debug("SCTP_CID_ERROR\n"); i = 5; break; case SCTP_CID_COOKIE_ECHO: - DEBUGP("SCTP_CID_COOKIE_ECHO\n"); + pr_debug("SCTP_CID_COOKIE_ECHO\n"); i = 6; break; case SCTP_CID_COOKIE_ACK: - DEBUGP("SCTP_CID_COOKIE_ACK\n"); + pr_debug("SCTP_CID_COOKIE_ACK\n"); i = 7; break; case SCTP_CID_SHUTDOWN_COMPLETE: - DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n"); + pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n"); i = 8; break; default: /* Other chunks like DATA, SACK, HEARTBEAT and its ACK do not cause a change in state */ - DEBUGP("Unknown chunk type, Will stay in %s\n", - sctp_conntrack_names[cur_state]); + pr_debug("Unknown chunk type, Will stay in %s\n", + sctp_conntrack_names[cur_state]); return cur_state; } - DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n", - dir, sctp_conntrack_names[cur_state], chunk_type, - sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]); + pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n", + dir, sctp_conntrack_names[cur_state], chunk_type, + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]); return sctp_conntracks[dir][i][cur_state]; } @@ -323,9 +299,6 @@ static int sctp_packet(struct nf_conn *conntrack, u_int32_t offset, count; char map[256 / sizeof (char)] = {0}; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); if (sh == NULL) return -1; @@ -340,7 +313,7 @@ static int sctp_packet(struct nf_conn *conntrack, && !test_bit(SCTP_CID_ABORT, (void *)map) && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map) && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { - DEBUGP("Verification tag check failed\n"); + pr_debug("Verification tag check failed\n"); return -1; } @@ -385,8 +358,9 @@ static int sctp_packet(struct nf_conn *conntrack, /* Invalid */ if (newconntrack == SCTP_CONNTRACK_MAX) { - DEBUGP("nf_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n", - CTINFO2DIR(ctinfo), sch->type, oldsctpstate); + pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u " + "conntrack=%u\n", + CTINFO2DIR(ctinfo), sch->type, oldsctpstate); write_unlock_bh(&sctp_lock); return -1; } @@ -402,8 +376,8 @@ static int sctp_packet(struct nf_conn *conntrack, write_unlock_bh(&sctp_lock); return -1; } - DEBUGP("Setting vtag %x for dir %d\n", - ih->init_tag, !CTINFO2DIR(ctinfo)); + pr_debug("Setting vtag %x for dir %d\n", + ih->init_tag, !CTINFO2DIR(ctinfo)); conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag; } @@ -418,7 +392,7 @@ static int sctp_packet(struct nf_conn *conntrack, if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY && newconntrack == SCTP_CONNTRACK_ESTABLISHED) { - DEBUGP("Setting assured bit\n"); + pr_debug("Setting assured bit\n"); set_bit(IPS_ASSURED_BIT, &conntrack->status); nf_conntrack_event_cache(IPCT_STATUS, skb); } @@ -436,9 +410,6 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, u_int32_t offset, count; char map[256 / sizeof (char)] = {0}; - DEBUGP(__FUNCTION__); - DEBUGP("\n"); - sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); if (sh == NULL) return 0; @@ -461,7 +432,7 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, /* Invalid: delete conntrack */ if (newconntrack == SCTP_CONNTRACK_MAX) { - DEBUGP("nf_conntrack_sctp: invalid new deleting.\n"); + pr_debug("nf_conntrack_sctp: invalid new deleting.\n"); return 0; } @@ -475,8 +446,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, if (ih == NULL) return 0; - DEBUGP("Setting vtag %x for new conn\n", - ih->init_tag); + pr_debug("Setting vtag %x for new conn\n", + ih->init_tag); conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag; @@ -488,8 +459,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, /* If it is a shutdown ack OOTB packet, we expect a return shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ else { - DEBUGP("Setting vtag %x for new conn OOTB\n", - sh->vtag); + pr_debug("Setting vtag %x for new conn OOTB\n", + sh->vtag); conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; } @@ -688,8 +659,6 @@ int __init nf_conntrack_proto_sctp_init(void) cleanup_sctp4: nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); out: - DEBUGP("SCTP conntrack module loading %s\n", - ret ? "failed": "succeeded"); return ret; } @@ -697,7 +666,6 @@ void __exit nf_conntrack_proto_sctp_fini(void) { nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); - DEBUGP("SCTP conntrack module unloaded\n"); } module_init(nf_conntrack_proto_sctp_init); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index ccdd5d231e0d..1c8206e6560a 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -26,13 +26,6 @@ #include #include -#if 0 -#define DEBUGP printk -#define DEBUGP_VARS -#else -#define DEBUGP(format, args...) -#endif - /* Protects conntrack->proto.tcp */ static DEFINE_RWLOCK(tcp_lock); @@ -496,7 +489,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, } } -static int tcp_in_window(struct ip_ct_tcp *state, +static int tcp_in_window(struct nf_conn *ct, + struct ip_ct_tcp *state, enum ip_conntrack_dir dir, unsigned int index, const struct sk_buff *skb, @@ -506,6 +500,7 @@ static int tcp_in_window(struct ip_ct_tcp *state, { struct ip_ct_tcp_state *sender = &state->seen[dir]; struct ip_ct_tcp_state *receiver = &state->seen[!dir]; + struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; __u32 seq, ack, sack, end, win, swin; int res; @@ -520,18 +515,17 @@ static int tcp_in_window(struct ip_ct_tcp *state, if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) tcp_sack(skb, dataoff, tcph, &sack); - DEBUGP("tcp_in_window: START\n"); - DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " - "seq=%u ack=%u sack=%u win=%u end=%u\n", - NIPQUAD(iph->saddr), ntohs(tcph->source), - NIPQUAD(iph->daddr), ntohs(tcph->dest), - seq, ack, sack, win, end); - DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " - "receiver end=%u maxend=%u maxwin=%u scale=%i\n", - sender->td_end, sender->td_maxend, sender->td_maxwin, - sender->td_scale, - receiver->td_end, receiver->td_maxend, receiver->td_maxwin, - receiver->td_scale); + pr_debug("tcp_in_window: START\n"); + pr_debug("tcp_in_window: "); + NF_CT_DUMP_TUPLE(tuple); + pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n", + seq, ack, sack, win, end); + pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", + sender->td_end, sender->td_maxend, sender->td_maxwin, + sender->td_scale, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); if (sender->td_end == 0) { /* @@ -609,23 +603,22 @@ static int tcp_in_window(struct ip_ct_tcp *state, */ seq = end = sender->td_end; - DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " - "seq=%u ack=%u sack =%u win=%u end=%u\n", - NIPQUAD(iph->saddr), ntohs(tcph->source), - NIPQUAD(iph->daddr), ntohs(tcph->dest), - seq, ack, sack, win, end); - DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " - "receiver end=%u maxend=%u maxwin=%u scale=%i\n", - sender->td_end, sender->td_maxend, sender->td_maxwin, - sender->td_scale, - receiver->td_end, receiver->td_maxend, receiver->td_maxwin, - receiver->td_scale); - - DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n", - before(seq, sender->td_maxend + 1), - after(end, sender->td_end - receiver->td_maxwin - 1), - before(sack, receiver->td_end + 1), - after(ack, receiver->td_end - MAXACKWINDOW(sender))); + pr_debug("tcp_in_window: "); + NF_CT_DUMP_TUPLE(tuple); + pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n", + seq, ack, sack, win, end); + pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", + sender->td_end, sender->td_maxend, sender->td_maxwin, + sender->td_scale, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); + + pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n", + before(seq, sender->td_maxend + 1), + after(end, sender->td_end - receiver->td_maxwin - 1), + before(sack, receiver->td_end + 1), + after(ack, receiver->td_end - MAXACKWINDOW(sender))); if (before(seq, sender->td_maxend + 1) && after(end, sender->td_end - receiver->td_maxwin - 1) && @@ -694,10 +687,10 @@ static int tcp_in_window(struct ip_ct_tcp *state, : "SEQ is over the upper bound (over the window of the receiver)"); } - DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " - "receiver end=%u maxend=%u maxwin=%u\n", - res, sender->td_end, sender->td_maxend, sender->td_maxwin, - receiver->td_end, receiver->td_maxend, receiver->td_maxwin); + pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " + "receiver end=%u maxend=%u maxwin=%u\n", + res, sender->td_end, sender->td_maxend, sender->td_maxwin, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin); return res; } @@ -711,11 +704,9 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, int dir) { struct tcphdr *tcph = (void *)skb->data + dataoff; - __u32 end; -#ifdef DEBUGP_VARS struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir]; struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir]; -#endif + __u32 end; end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); @@ -727,12 +718,12 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, conntrack->proto.tcp.seen[dir].td_end = end; conntrack->proto.tcp.last_end = end; write_unlock_bh(&tcp_lock); - DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " - "receiver end=%u maxend=%u maxwin=%u scale=%i\n", - sender->td_end, sender->td_maxend, sender->td_maxwin, - sender->td_scale, - receiver->td_end, receiver->td_maxend, receiver->td_maxwin, - receiver->td_scale); + pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", + sender->td_end, sender->td_maxend, sender->td_maxwin, + sender->td_scale, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); } EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); #endif @@ -823,6 +814,7 @@ static int tcp_packet(struct nf_conn *conntrack, int pf, unsigned int hooknum) { + struct nf_conntrack_tuple *tuple; enum tcp_conntrack new_state, old_state; enum ip_conntrack_dir dir; struct tcphdr *th, _tcph; @@ -837,6 +829,7 @@ static int tcp_packet(struct nf_conn *conntrack, dir = CTINFO2DIR(ctinfo); index = get_conntrack_index(th); new_state = tcp_conntracks[dir][index][old_state]; + tuple = &conntrack->tuplehash[dir].tuple; switch (new_state) { case TCP_CONNTRACK_IGNORE: @@ -880,9 +873,8 @@ static int tcp_packet(struct nf_conn *conntrack, return NF_ACCEPT; case TCP_CONNTRACK_MAX: /* Invalid packet */ - DEBUGP("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", - dir, get_conntrack_index(th), - old_state); + pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", + dir, get_conntrack_index(th), old_state); write_unlock_bh(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, @@ -933,7 +925,7 @@ static int tcp_packet(struct nf_conn *conntrack, break; } - if (!tcp_in_window(&conntrack->proto.tcp, dir, index, + if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index, skb, dataoff, th, pf)) { write_unlock_bh(&tcp_lock); return -NF_ACCEPT; @@ -942,13 +934,12 @@ static int tcp_packet(struct nf_conn *conntrack, /* From now on we have got in-window packets */ conntrack->proto.tcp.last_index = index; - DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " - "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n", - NIPQUAD(iph->saddr), ntohs(th->source), - NIPQUAD(iph->daddr), ntohs(th->dest), - (th->syn ? 1 : 0), (th->ack ? 1 : 0), - (th->fin ? 1 : 0), (th->rst ? 1 : 0), - old_state, new_state); + pr_debug("tcp_conntracks: "); + NF_CT_DUMP_TUPLE(tuple); + pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n", + (th->syn ? 1 : 0), (th->ack ? 1 : 0), + (th->fin ? 1 : 0), (th->rst ? 1 : 0), + old_state, new_state); conntrack->proto.tcp.state = new_state; if (old_state != new_state @@ -997,10 +988,8 @@ static int tcp_new(struct nf_conn *conntrack, { enum tcp_conntrack new_state; struct tcphdr *th, _tcph; -#ifdef DEBUGP_VARS struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0]; struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1]; -#endif th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); BUG_ON(th == NULL); @@ -1012,7 +1001,7 @@ static int tcp_new(struct nf_conn *conntrack, /* Invalid: delete conntrack */ if (new_state >= TCP_CONNTRACK_MAX) { - DEBUGP("nf_ct_tcp: invalid new deleting.\n"); + pr_debug("nf_ct_tcp: invalid new deleting.\n"); return 0; } @@ -1065,12 +1054,12 @@ static int tcp_new(struct nf_conn *conntrack, conntrack->proto.tcp.state = TCP_CONNTRACK_NONE; conntrack->proto.tcp.last_index = TCP_NONE_SET; - DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " - "receiver end=%u maxend=%u maxwin=%u scale=%i\n", - sender->td_end, sender->td_maxend, sender->td_maxwin, - sender->td_scale, - receiver->td_end, receiver->td_maxend, receiver->td_maxwin, - receiver->td_scale); + pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", + sender->td_end, sender->td_maxend, sender->td_maxwin, + sender->td_scale, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); return 1; } diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 627eda79d154..355d371bac93 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -40,12 +40,6 @@ static u_int16_t ports[MAX_PORTS]; static unsigned int ports_c; module_param_array(ports, ushort, &ports_c, 0400); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - struct sane_request { __be32 RPC_code; #define SANE_NET_START 7 /* RPC code */ @@ -125,15 +119,15 @@ static int help(struct sk_buff **pskb, ct_sane_info->state = SANE_STATE_NORMAL; if (datalen < sizeof(struct sane_reply_net_start)) { - DEBUGP("nf_ct_sane: NET_START reply too short\n"); + pr_debug("nf_ct_sane: NET_START reply too short\n"); goto out; } reply = (struct sane_reply_net_start *)sb_ptr; if (reply->status != htonl(SANE_STATUS_SUCCESS)) { /* saned refused the command */ - DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", - ntohl(reply->status)); + pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", + ntohl(reply->status)); goto out; } @@ -151,9 +145,8 @@ static int help(struct sk_buff **pskb, nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, IPPROTO_TCP, NULL, &reply->port); - DEBUGP("nf_ct_sane: expect: "); + pr_debug("nf_ct_sane: expect: "); NF_CT_DUMP_TUPLE(&exp->tuple); - NF_CT_DUMP_TUPLE(&exp->mask); /* Can't expect this? Best to drop packet now. */ if (nf_ct_expect_related(exp) != 0) @@ -176,9 +169,9 @@ static void nf_conntrack_sane_fini(void) for (i = 0; i < ports_c; i++) { for (j = 0; j < 2; j++) { - DEBUGP("nf_ct_sane: unregistering helper for pf: %d " - "port: %d\n", - sane[i][j].tuple.src.l3num, ports[i]); + pr_debug("nf_ct_sane: unregistering helper for pf: %d " + "port: %d\n", + sane[i][j].tuple.src.l3num, ports[i]); nf_conntrack_helper_unregister(&sane[i][j]); } } @@ -217,9 +210,9 @@ static int __init nf_conntrack_sane_init(void) sprintf(tmpname, "sane-%d", ports[i]); sane[i][j].name = tmpname; - DEBUGP("nf_ct_sane: registering helper for pf: %d " - "port: %d\n", - sane[i][j].tuple.src.l3num, ports[i]); + pr_debug("nf_ct_sane: registering helper for pf: %d " + "port: %d\n", + sane[i][j].tuple.src.l3num, ports[i]); ret = nf_conntrack_helper_register(&sane[i][j]); if (ret) { printk(KERN_ERR "nf_ct_sane: failed to " diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 5b78f0e1f63b..1276a442f10c 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -21,12 +21,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Hentschel "); MODULE_DESCRIPTION("SIP connection tracking helper"); @@ -285,7 +279,7 @@ static int epaddr_len(struct nf_conn *ct, const char *dptr, const char *aux = dptr; if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { - DEBUGP("ip: %s parse failed.!\n", dptr); + pr_debug("ip: %s parse failed.!\n", dptr); return 0; } @@ -344,8 +338,8 @@ int ct_sip_get_info(struct nf_conn *ct, ct_sip_lnlen(dptr, limit), hnfo->case_sensitive); if (!aux) { - DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, - hnfo->lname); + pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str, + hnfo->lname); return -1; } aux += hnfo->ln_strlen; @@ -356,11 +350,11 @@ int ct_sip_get_info(struct nf_conn *ct, *matchoff = (aux - k) + shift; - DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, - *matchlen); + pr_debug("%s match succeeded! - len: %u\n", hnfo->lname, + *matchlen); return 1; } - DEBUGP("%s header not found.\n", hnfo->lname); + pr_debug("%s header not found.\n", hnfo->lname); return 0; } EXPORT_SYMBOL_GPL(ct_sip_get_info); @@ -424,7 +418,7 @@ static int sip_help(struct sk_buff **pskb, if (!skb_is_nonlinear(*pskb)) dptr = (*pskb)->data + dataoff; else { - DEBUGP("Copy of skbuff not supported yet.\n"); + pr_debug("Copy of skbuff not supported yet.\n"); goto out; } @@ -518,7 +512,7 @@ static int __init nf_conntrack_sip_init(void) sprintf(tmpname, "sip-%u", i); sip[i][j].name = tmpname; - DEBUGP("port #%u: %u\n", i, ports[i]); + pr_debug("port #%u: %u\n", i, ports[i]); ret = nf_conntrack_helper_register(&sip[i][j]); if (ret) { diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 6af96c6e29fb..54498bcfa862 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -25,12 +25,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - MODULE_LICENSE("GPL"); #ifdef CONFIG_PROC_FS diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index db0387cf9bac..cc19506cf2f8 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -29,13 +29,6 @@ static int ports_c; module_param_array(ports, ushort, &ports_c, 0400); MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); -#if 0 -#define DEBUGP(format, args...) printk("%s:%s:" format, \ - __FILE__, __FUNCTION__ , ## args) -#else -#define DEBUGP(format, args...) -#endif - unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, struct nf_conntrack_expect *exp) __read_mostly; @@ -62,7 +55,6 @@ static int tftp_help(struct sk_buff **pskb, case TFTP_OPCODE_READ: case TFTP_OPCODE_WRITE: /* RRQ and WRQ works the same way */ - DEBUGP(""); NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); @@ -73,9 +65,8 @@ static int tftp_help(struct sk_buff **pskb, nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, IPPROTO_UDP, NULL, &tuple->dst.u.udp.port); - DEBUGP("expect: "); + pr_debug("expect: "); NF_CT_DUMP_TUPLE(&exp->tuple); - NF_CT_DUMP_TUPLE(&exp->mask); nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); if (nf_nat_tftp && ct->status & IPS_NAT_MASK) @@ -86,13 +77,13 @@ static int tftp_help(struct sk_buff **pskb, break; case TFTP_OPCODE_DATA: case TFTP_OPCODE_ACK: - DEBUGP("Data/ACK opcode\n"); + pr_debug("Data/ACK opcode\n"); break; case TFTP_OPCODE_ERROR: - DEBUGP("Error opcode\n"); + pr_debug("Error opcode\n"); break; default: - DEBUGP("Unknown opcode\n"); + pr_debug("Unknown opcode\n"); } return ret; } -- cgit v1.2.3 From 4839c52b01ca91be1c62761e08fb3deb3881e857 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Mon, 9 Jul 2007 15:32:57 -0700 Subject: [IPV4]: Make ip_tos2prio const. Signed-off-by: Philippe De Muyter Signed-off-by: David S. Miller --- include/net/route.h | 2 +- net/ipv4/route.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/net') diff --git a/include/net/route.h b/include/net/route.h index 188b8936bb27..f7ce6259f86f 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -135,7 +135,7 @@ static inline void ip_rt_put(struct rtable * rt) #define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3) -extern __u8 ip_tos2prio[16]; +extern const __u8 ip_tos2prio[16]; static inline char rt_tos2priority(u8 tos) { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 85285021518b..88fa648d7ba3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -167,7 +167,7 @@ static struct dst_ops ipv4_dst_ops = { #define ECN_OR_COST(class) TC_PRIO_##class -__u8 ip_tos2prio[16] = { +const __u8 ip_tos2prio[16] = { TC_PRIO_BESTEFFORT, ECN_OR_COST(FILLER), TC_PRIO_BESTEFFORT, -- cgit v1.2.3 From 5b7f990927fe87ad3bec762a33c0e72bcbf6841e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jul 2007 09:51:55 +0200 Subject: [Bluetooth] Add basics to better support and handle eSCO links To better support and handle eSCO links in the future a bunch of constants needs to be added and some basic routines need to be updated. This is the initial step. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 18 ++++++++++++-- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_conn.c | 51 ++++++++++++++++++++-------------------- net/bluetooth/hci_core.c | 3 ++- net/bluetooth/hci_event.c | 29 ++++++++++++++++------- 5 files changed, 66 insertions(+), 37 deletions(-) (limited to 'include/net') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 93ce272a5d27..ebfb96b41106 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -107,14 +107,14 @@ enum { #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ -/* HCI Packet types */ +/* HCI data types */ #define HCI_COMMAND_PKT 0x01 #define HCI_ACLDATA_PKT 0x02 #define HCI_SCODATA_PKT 0x03 #define HCI_EVENT_PKT 0x04 #define HCI_VENDOR_PKT 0xff -/* HCI Packet types */ +/* HCI packet types */ #define HCI_DM1 0x0008 #define HCI_DM3 0x0400 #define HCI_DM5 0x4000 @@ -129,6 +129,14 @@ enum { #define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3) #define ACL_PTYPE_MASK (~SCO_PTYPE_MASK) +/* eSCO packet types */ +#define ESCO_HV1 0x0001 +#define ESCO_HV2 0x0002 +#define ESCO_HV3 0x0004 +#define ESCO_EV3 0x0008 +#define ESCO_EV4 0x0010 +#define ESCO_EV5 0x0020 + /* ACL flags */ #define ACL_CONT 0x01 #define ACL_START 0x02 @@ -138,6 +146,7 @@ enum { /* Baseband links */ #define SCO_LINK 0x00 #define ACL_LINK 0x01 +#define ESCO_LINK 0x02 /* LMP features */ #define LMP_3SLOT 0x01 @@ -162,6 +171,11 @@ enum { #define LMP_PSCHEME 0x02 #define LMP_PCONTROL 0x04 +#define LMP_ESCO 0x80 + +#define LMP_EV4 0x01 +#define LMP_EV5 0x02 + #define LMP_SNIFF_SUBR 0x02 /* Connection modes */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7c78744ec0fd..8f67c8a7169b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -78,6 +78,7 @@ struct hci_dev { __u16 voice_setting; __u16 pkt_type; + __u16 esco_type; __u16 link_policy; __u16 link_mode; @@ -452,6 +453,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) +#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) /* ----- HCI protocols ----- */ struct hci_proto { diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 63980bd6b5f2..5fdfc9a67d39 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) conn->state = BT_CONNECT; conn->out = 1; - cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); cp.handle = cpu_to_le16(handle); + cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); } @@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->disc_timer); - if (conn->type == SCO_LINK) { - struct hci_conn *acl = conn->link; - if (acl) { - acl->link = NULL; - hci_conn_put(acl); - } - } else { + if (conn->type == ACL_LINK) { struct hci_conn *sco = conn->link; if (sco) sco->link = NULL; /* Unacked frames */ hdev->acl_cnt += conn->sent; + } else { + struct hci_conn *acl = conn->link; + if (acl) { + acl->link = NULL; + hci_conn_put(acl); + } } tasklet_disable(&hdev->tx_task); @@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route); /* Create SCO or ACL connection. * Device _must_ be locked */ -struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) { struct hci_conn *acl; + struct hci_conn *sco; BT_DBG("%s dst %s", hdev->name, batostr(dst)); @@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) if (acl->state == BT_OPEN || acl->state == BT_CLOSED) hci_acl_connect(acl); - if (type == SCO_LINK) { - struct hci_conn *sco; + if (type == ACL_LINK) + return acl; - if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) { - if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) { - hci_conn_put(acl); - return NULL; - } + if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { + if (!(sco = hci_conn_add(hdev, type, dst))) { + hci_conn_put(acl); + return NULL; } - acl->link = sco; - sco->link = acl; + } - hci_conn_hold(sco); + acl->link = sco; + sco->link = acl; - if (acl->state == BT_CONNECTED && - (sco->state == BT_OPEN || sco->state == BT_CLOSED)) - hci_add_sco(sco, acl->handle); + hci_conn_hold(sco); - return sco; - } else { - return acl; - } + if (acl->state == BT_CONNECTED && + (sco->state == BT_OPEN || sco->state == BT_CLOSED)) + hci_add_sco(sco, acl->handle); + + return sco; } EXPORT_SYMBOL(hci_connect); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9c71cffbc6b0..f6d867e0179f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev) hdev->flags = 0; hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); + hdev->esco_type = (ESCO_HV1); hdev->link_mode = (HCI_LM_ACCEPT); hdev->idle_timeout = 0; @@ -1254,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco); static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) { struct hci_conn_hash *h = &hdev->conn_hash; - struct hci_conn *conn = NULL; + struct hci_conn *conn = NULL; int num = 0, min = ~0; struct list_head *p; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 447ba7131220..4baea1e38652 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s if (hdev->features[0] & LMP_5SLOT) hdev->pkt_type |= (HCI_DM5 | HCI_DH5); - if (hdev->features[1] & LMP_HV2) - hdev->pkt_type |= (HCI_HV2); + if (hdev->features[1] & LMP_HV2) { + hdev->pkt_type |= (HCI_HV2); + hdev->esco_type |= (ESCO_HV2); + } + + if (hdev->features[1] & LMP_HV3) { + hdev->pkt_type |= (HCI_HV3); + hdev->esco_type |= (ESCO_HV3); + } - if (hdev->features[1] & LMP_HV3) - hdev->pkt_type |= (HCI_HV3); + if (hdev->features[3] & LMP_ESCO) + hdev->esco_type |= (ESCO_EV3); + + if (hdev->features[4] & LMP_EV4) + hdev->esco_type |= (ESCO_EV4); + + if (hdev->features[4] & LMP_EV5) + hdev->esco_type |= (ESCO_EV5); BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]); @@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s if (conn) { conn->sent -= count; - if (conn->type == SCO_LINK) { - if ((hdev->sco_cnt += count) > hdev->sco_pkts) - hdev->sco_cnt = hdev->sco_pkts; - } else { + if (conn->type == ACL_LINK) { if ((hdev->acl_cnt += count) > hdev->acl_pkts) hdev->acl_cnt = hdev->acl_pkts; + } else { + if ((hdev->sco_cnt += count) > hdev->sco_pkts) + hdev->sco_cnt = hdev->sco_pkts; } } } -- cgit v1.2.3 From bb4dbf9e61d0801927e7df2569bb3dd8287ea301 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 10 Jul 2007 22:55:49 -0700 Subject: [IPV6]: Do not send RH0 anymore. Based on . Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 3 +- include/linux/ipv6.h | 4 +- include/net/ipv6.h | 4 -- net/dccp/ipv6.c | 20 --------- net/ipv6/datagram.c | 3 +- net/ipv6/exthdrs.c | 78 ---------------------------------- net/ipv6/ipv6_sockglue.c | 3 +- net/ipv6/tcp_ipv6.c | 20 --------- 8 files changed, 5 insertions(+), 130 deletions(-) (limited to 'include/net') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index af6a63ab9026..09c184e41cf8 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -874,8 +874,7 @@ accept_redirects - BOOLEAN accept_source_route - INTEGER Accept source routing (routing extension header). - > 0: Accept routing header. - = 0: Accept only routing header type 2. + >= 0: Accept only routing header type 2. < 0: Do not accept routing header. Default: 0 diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 213b63be3c8f..cb3118cf277c 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -27,8 +27,8 @@ struct in6_ifreq { int ifr6_ifindex; }; -#define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */ -#define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */ +#define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */ +#define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */ #define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ /* diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 78a0d06d98d5..46b9dce82f6e 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -512,10 +512,6 @@ extern int ipv6_ext_hdr(u8 nexthdr); extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); -extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk, - struct ipv6_rt_hdr *hdr); - - /* * socket options (ipv6_sockglue.c) */ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 31737cdf156a..b158c661867b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -253,17 +253,6 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, if (dst == NULL) { opt = np->opt; - if (opt == NULL && - np->rxopt.bits.osrcrt == 2 && - ireq6->pktopts) { - struct sk_buff *pktopts = ireq6->pktopts; - struct inet6_skb_parm *rxopt = IP6CB(pktopts); - - if (rxopt->srcrt) - opt = ipv6_invert_rthdr(sk, - (struct ipv6_rt_hdr *)(skb_network_header(pktopts) + - rxopt->srcrt)); - } if (opt != NULL && opt->srcrt != NULL) { const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; @@ -570,15 +559,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, if (sk_acceptq_is_full(sk)) goto out_overflow; - if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) { - const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts); - - if (rxopt->srcrt) - opt = ipv6_invert_rthdr(sk, - (struct ipv6_rt_hdr *)(skb_network_header(ireq6->pktopts) + - rxopt->srcrt)); - } - if (dst == NULL) { struct in6_addr *final_p = NULL, final; struct flowi fl; diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index ba1386dd4168..fe0f49024a0a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -657,11 +657,10 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg); switch (rthdr->type) { - case IPV6_SRCRT_TYPE_0: #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: -#endif break; +#endif default: err = -EINVAL; goto exit_f; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index fc3a961fc5ba..c82d4d49f71f 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -427,18 +427,6 @@ looped_back: } switch (hdr->type) { - case IPV6_SRCRT_TYPE_0: - if (accept_source_route <= 0) - goto unknown_rh; - if (hdr->hdrlen & 0x01) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), - IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, - ((&hdr->hdrlen) - - skb_network_header(skb))); - return -1; - } - break; #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: if (accept_source_route < 0) @@ -576,72 +564,6 @@ void __init ipv6_rthdr_init(void) printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n"); }; -/* - This function inverts received rthdr. - NOTE: specs allow to make it automatically only if - packet authenticated. - - I will not discuss it here (though, I am really pissed off at - this stupid requirement making rthdr idea useless) - - Actually, it creates severe problems for us. - Embryonic requests has no associated sockets, - so that user have no control over it and - cannot not only to set reply options, but - even to know, that someone wants to connect - without success. :-( - - For now we need to test the engine, so that I created - temporary (or permanent) backdoor. - If listening socket set IPV6_RTHDR to 2, then we invert header. - --ANK (980729) - */ - -struct ipv6_txoptions * -ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr) -{ - /* Received rthdr: - - [ H1 -> H2 -> ... H_prev ] daddr=ME - - Inverted result: - [ H_prev -> ... -> H1 ] daddr =sender - - Note, that IP output engine will rewrite this rthdr - by rotating it left by one addr. - */ - - int n, i; - struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr; - struct rt0_hdr *irthdr; - struct ipv6_txoptions *opt; - int hdrlen = ipv6_optlen(hdr); - - if (hdr->segments_left || - hdr->type != IPV6_SRCRT_TYPE_0 || - hdr->hdrlen & 0x01) - return NULL; - - n = hdr->hdrlen >> 1; - opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC); - if (opt == NULL) - return NULL; - memset(opt, 0, sizeof(*opt)); - opt->tot_len = sizeof(*opt) + hdrlen; - opt->srcrt = (void*)(opt+1); - opt->opt_nflen = hdrlen; - - memcpy(opt->srcrt, hdr, sizeof(*hdr)); - irthdr = (struct rt0_hdr*)opt->srcrt; - irthdr->reserved = 0; - opt->srcrt->segments_left = n; - for (i=0; iaddr+i, rthdr->addr+(n-1-i), 16); - return opt; -} - -EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); - /********************************** Hop-by-hop options. **********************************/ diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 1c3506696cb5..1841714ac419 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -416,11 +416,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (optname == IPV6_RTHDR && opt && opt->srcrt) { struct ipv6_rt_hdr *rthdr = opt->srcrt; switch (rthdr->type) { - case IPV6_SRCRT_TYPE_0: #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) case IPV6_SRCRT_TYPE_2: -#endif break; +#endif default: goto sticky_done; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 193d9d60bb7a..d67fb1ef751e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -484,17 +484,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, if (dst == NULL) { opt = np->opt; - if (opt == NULL && - np->rxopt.bits.osrcrt == 2 && - treq->pktopts) { - struct sk_buff *pktopts = treq->pktopts; - struct inet6_skb_parm *rxopt = IP6CB(pktopts); - if (rxopt->srcrt) - opt = ipv6_invert_rthdr(sk, - (struct ipv6_rt_hdr *)(skb_network_header(pktopts) + - rxopt->srcrt)); - } - if (opt && opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; ipv6_addr_copy(&final, &fl.fl6_dst); @@ -1391,15 +1380,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, if (sk_acceptq_is_full(sk)) goto out_overflow; - if (np->rxopt.bits.osrcrt == 2 && - opt == NULL && treq->pktopts) { - struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); - if (rxopt->srcrt) - opt = ipv6_invert_rthdr(sk, - (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) + - rxopt->srcrt)); - } - if (dst == NULL) { struct in6_addr *final_p = NULL, final; struct flowi fl; -- cgit v1.2.3 From ed8b548ce3cb988f59a0fd9af6ccdc4f8198cd19 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 10 Jul 2007 23:02:12 -0700 Subject: [DECNET]: Another unnecessary net/tcp.h inclusion in net/dn.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No longer needed. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/net/dn.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/net') diff --git a/include/net/dn.h b/include/net/dn.h index ac4ce9091747..627778384c84 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -3,7 +3,6 @@ #include #include -#include #include #define dn_ntohs(x) le16_to_cpu(x) -- cgit v1.2.3 From 1fd05ba5a2f2aa8e7b9b52ef55df850e2e7d54c9 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 11 Jul 2007 14:22:39 -0700 Subject: [AF_UNIX]: Rewrite garbage collector, fixes race. Throw out the old mark & sweep garbage collector and put in a refcounting cycle detecting one. The old one had a race with recvmsg, that resulted in false positives and hence data loss. The old algorithm operated on all unix sockets in the system, so any additional locking would have meant performance problems for all users of these. The new algorithm instead only operates on "in flight" sockets, which are very rare, and the additional locking for these doesn't negatively impact the vast majority of users. In fact it's probable, that there weren't *any* heavy senders of sockets over sockets, otherwise the above race would have been discovered long ago. The patch works OK with the app that exposed the race with the old code. The garbage collection has also been verified to work in a few simple cases. Signed-off-by: Miklos Szeredi Signed-off-by: David S. Miller --- include/net/af_unix.h | 3 +- net/unix/af_unix.c | 6 +- net/unix/garbage.c | 325 +++++++++++++++++++++++++++++--------------------- 3 files changed, 190 insertions(+), 144 deletions(-) (limited to 'include/net') diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 65f49fd7deff..6de1e9e35c73 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -79,9 +79,10 @@ struct unix_sock { struct mutex readlock; struct sock *peer; struct sock *other; - struct sock *gc_tree; + struct list_head link; atomic_t inflight; spinlock_t lock; + unsigned int gc_candidate : 1; wait_queue_head_t peer_wait; }; #define unix_sk(__sk) ((struct unix_sock *)__sk) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3654b647ac79..65ebccc0a698 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -592,7 +592,8 @@ static struct sock * unix_create1(struct socket *sock) u->dentry = NULL; u->mnt = NULL; spin_lock_init(&u->lock); - atomic_set(&u->inflight, sock ? 0 : -1); + atomic_set(&u->inflight, 0); + INIT_LIST_HEAD(&u->link); mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); unix_insert_socket(unix_sockets_unbound, sk); @@ -1134,9 +1135,6 @@ restart: /* take ten and and send info to listening sock */ spin_lock(&other->sk_receive_queue.lock); __skb_queue_tail(&other->sk_receive_queue, skb); - /* Undo artificially decreased inflight after embrion - * is installed to listening socket. */ - atomic_inc(&newu->inflight); spin_unlock(&other->sk_receive_queue.lock); unix_state_unlock(other); other->sk_data_ready(other, 0); diff --git a/net/unix/garbage.c b/net/unix/garbage.c index f20b7ea7c555..406b6433e467 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -62,6 +62,10 @@ * AV 1 Mar 1999 * Damn. Added missing check for ->dead in listen queues scanning. * + * Miklos Szeredi 25 Jun 2007 + * Reimplement with a cycle collecting algorithm. This should + * solve several problems with the previous code, like being racy + * wrt receive and holding up unrelated socket operations. */ #include @@ -84,10 +88,9 @@ /* Internal data structures and random procedures: */ -#define GC_HEAD ((struct sock *)(-1)) -#define GC_ORPHAN ((struct sock *)(-3)) - -static struct sock *gc_current = GC_HEAD; /* stack of objects to mark */ +static LIST_HEAD(gc_inflight_list); +static LIST_HEAD(gc_candidates); +static DEFINE_SPINLOCK(unix_gc_lock); atomic_t unix_tot_inflight = ATOMIC_INIT(0); @@ -122,8 +125,16 @@ void unix_inflight(struct file *fp) { struct sock *s = unix_get_socket(fp); if(s) { - atomic_inc(&unix_sk(s)->inflight); + struct unix_sock *u = unix_sk(s); + spin_lock(&unix_gc_lock); + if (atomic_inc_return(&u->inflight) == 1) { + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &gc_inflight_list); + } else { + BUG_ON(list_empty(&u->link)); + } atomic_inc(&unix_tot_inflight); + spin_unlock(&unix_gc_lock); } } @@ -131,182 +142,218 @@ void unix_notinflight(struct file *fp) { struct sock *s = unix_get_socket(fp); if(s) { - atomic_dec(&unix_sk(s)->inflight); + struct unix_sock *u = unix_sk(s); + spin_lock(&unix_gc_lock); + BUG_ON(list_empty(&u->link)); + if (atomic_dec_and_test(&u->inflight)) + list_del_init(&u->link); atomic_dec(&unix_tot_inflight); + spin_unlock(&unix_gc_lock); } } +static inline struct sk_buff *sock_queue_head(struct sock *sk) +{ + return (struct sk_buff *) &sk->sk_receive_queue; +} -/* - * Garbage Collector Support Functions - */ +#define receive_queue_for_each_skb(sk, next, skb) \ + for (skb = sock_queue_head(sk)->next, next = skb->next; \ + skb != sock_queue_head(sk); skb = next, next = skb->next) -static inline struct sock *pop_stack(void) +static void scan_inflight(struct sock *x, void (*func)(struct sock *), + struct sk_buff_head *hitlist) { - struct sock *p = gc_current; - gc_current = unix_sk(p)->gc_tree; - return p; + struct sk_buff *skb; + struct sk_buff *next; + + spin_lock(&x->sk_receive_queue.lock); + receive_queue_for_each_skb(x, next, skb) { + /* + * Do we have file descriptors ? + */ + if (UNIXCB(skb).fp) { + bool hit = false; + /* + * Process the descriptors of this socket + */ + int nfd = UNIXCB(skb).fp->count; + struct file **fp = UNIXCB(skb).fp->fp; + while (nfd--) { + /* + * Get the socket the fd matches + * if it indeed does so + */ + struct sock *sk = unix_get_socket(*fp++); + if(sk) { + hit = true; + func(sk); + } + } + if (hit && hitlist != NULL) { + __skb_unlink(skb, &x->sk_receive_queue); + __skb_queue_tail(hitlist, skb); + } + } + } + spin_unlock(&x->sk_receive_queue.lock); } -static inline int empty_stack(void) +static void scan_children(struct sock *x, void (*func)(struct sock *), + struct sk_buff_head *hitlist) { - return gc_current == GC_HEAD; + if (x->sk_state != TCP_LISTEN) + scan_inflight(x, func, hitlist); + else { + struct sk_buff *skb; + struct sk_buff *next; + struct unix_sock *u; + LIST_HEAD(embryos); + + /* + * For a listening socket collect the queued embryos + * and perform a scan on them as well. + */ + spin_lock(&x->sk_receive_queue.lock); + receive_queue_for_each_skb(x, next, skb) { + u = unix_sk(skb->sk); + + /* + * An embryo cannot be in-flight, so it's safe + * to use the list link. + */ + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &embryos); + } + spin_unlock(&x->sk_receive_queue.lock); + + while (!list_empty(&embryos)) { + u = list_entry(embryos.next, struct unix_sock, link); + scan_inflight(&u->sk, func, hitlist); + list_del_init(&u->link); + } + } } -static void maybe_unmark_and_push(struct sock *x) +static void dec_inflight(struct sock *sk) { - struct unix_sock *u = unix_sk(x); + atomic_dec(&unix_sk(sk)->inflight); +} - if (u->gc_tree != GC_ORPHAN) - return; - sock_hold(x); - u->gc_tree = gc_current; - gc_current = x; +static void inc_inflight(struct sock *sk) +{ + atomic_inc(&unix_sk(sk)->inflight); } +static void inc_inflight_move_tail(struct sock *sk) +{ + struct unix_sock *u = unix_sk(sk); + + atomic_inc(&u->inflight); + /* + * If this is still a candidate, move it to the end of the + * list, so that it's checked even if it was already passed + * over + */ + if (u->gc_candidate) + list_move_tail(&u->link, &gc_candidates); +} /* The external entry point: unix_gc() */ void unix_gc(void) { - static DEFINE_MUTEX(unix_gc_sem); - int i; - struct sock *s; - struct sk_buff_head hitlist; - struct sk_buff *skb; + static bool gc_in_progress = false; - /* - * Avoid a recursive GC. - */ + struct unix_sock *u; + struct unix_sock *next; + struct sk_buff_head hitlist; + struct list_head cursor; - if (!mutex_trylock(&unix_gc_sem)) - return; + spin_lock(&unix_gc_lock); - spin_lock(&unix_table_lock); + /* Avoid a recursive GC. */ + if (gc_in_progress) + goto out; - forall_unix_sockets(i, s) - { - unix_sk(s)->gc_tree = GC_ORPHAN; - } + gc_in_progress = true; /* - * Everything is now marked - */ - - /* Invariant to be maintained: - - everything unmarked is either: - -- (a) on the stack, or - -- (b) has all of its children unmarked - - everything on the stack is always unmarked - - nothing is ever pushed onto the stack twice, because: - -- nothing previously unmarked is ever pushed on the stack + * First, select candidates for garbage collection. Only + * in-flight sockets are considered, and from those only ones + * which don't have any external reference. + * + * Holding unix_gc_lock will protect these candidates from + * being detached, and hence from gaining an external + * reference. This also means, that since there are no + * possible receivers, the receive queues of these sockets are + * static during the GC, even though the dequeue is done + * before the detach without atomicity guarantees. */ + list_for_each_entry_safe(u, next, &gc_inflight_list, link) { + int total_refs; + int inflight_refs; + + total_refs = file_count(u->sk.sk_socket->file); + inflight_refs = atomic_read(&u->inflight); + + BUG_ON(inflight_refs < 1); + BUG_ON(total_refs < inflight_refs); + if (total_refs == inflight_refs) { + list_move_tail(&u->link, &gc_candidates); + u->gc_candidate = 1; + } + } /* - * Push root set + * Now remove all internal in-flight reference to children of + * the candidates. */ - - forall_unix_sockets(i, s) - { - int open_count = 0; - - /* - * If all instances of the descriptor are not - * in flight we are in use. - * - * Special case: when socket s is embrion, it may be - * hashed but still not in queue of listening socket. - * In this case (see unix_create1()) we set artificial - * negative inflight counter to close race window. - * It is trick of course and dirty one. - */ - if (s->sk_socket && s->sk_socket->file) - open_count = file_count(s->sk_socket->file); - if (open_count > atomic_read(&unix_sk(s)->inflight)) - maybe_unmark_and_push(s); - } + list_for_each_entry(u, &gc_candidates, link) + scan_children(&u->sk, dec_inflight, NULL); /* - * Mark phase + * Restore the references for children of all candidates, + * which have remaining references. Do this recursively, so + * only those remain, which form cyclic references. + * + * Use a "cursor" link, to make the list traversal safe, even + * though elements might be moved about. */ + list_add(&cursor, &gc_candidates); + while (cursor.next != &gc_candidates) { + u = list_entry(cursor.next, struct unix_sock, link); - while (!empty_stack()) - { - struct sock *x = pop_stack(); - struct sock *sk; - - spin_lock(&x->sk_receive_queue.lock); - skb = skb_peek(&x->sk_receive_queue); - - /* - * Loop through all but first born - */ + /* Move cursor to after the current position. */ + list_move(&cursor, &u->link); - while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) { - /* - * Do we have file descriptors ? - */ - if(UNIXCB(skb).fp) - { - /* - * Process the descriptors of this socket - */ - int nfd=UNIXCB(skb).fp->count; - struct file **fp = UNIXCB(skb).fp->fp; - while(nfd--) - { - /* - * Get the socket the fd matches if - * it indeed does so - */ - if((sk=unix_get_socket(*fp++))!=NULL) - { - maybe_unmark_and_push(sk); - } - } - } - /* We have to scan not-yet-accepted ones too */ - if (x->sk_state == TCP_LISTEN) - maybe_unmark_and_push(skb->sk); - skb=skb->next; + if (atomic_read(&u->inflight) > 0) { + list_move_tail(&u->link, &gc_inflight_list); + u->gc_candidate = 0; + scan_children(&u->sk, inc_inflight_move_tail, NULL); } - spin_unlock(&x->sk_receive_queue.lock); - sock_put(x); } + list_del(&cursor); + /* + * Now gc_candidates contains only garbage. Restore original + * inflight counters for these as well, and remove the skbuffs + * which are creating the cycle(s). + */ skb_queue_head_init(&hitlist); + list_for_each_entry(u, &gc_candidates, link) + scan_children(&u->sk, inc_inflight, &hitlist); - forall_unix_sockets(i, s) - { - struct unix_sock *u = unix_sk(s); + spin_unlock(&unix_gc_lock); - if (u->gc_tree == GC_ORPHAN) { - struct sk_buff *nextsk; + /* Here we are. Hitlist is filled. Die. */ + __skb_queue_purge(&hitlist); - spin_lock(&s->sk_receive_queue.lock); - skb = skb_peek(&s->sk_receive_queue); - while (skb && - skb != (struct sk_buff *)&s->sk_receive_queue) { - nextsk = skb->next; - /* - * Do we have file descriptors ? - */ - if (UNIXCB(skb).fp) { - __skb_unlink(skb, - &s->sk_receive_queue); - __skb_queue_tail(&hitlist, skb); - } - skb = nextsk; - } - spin_unlock(&s->sk_receive_queue.lock); - } - u->gc_tree = GC_ORPHAN; - } - spin_unlock(&unix_table_lock); + spin_lock(&unix_gc_lock); - /* - * Here we are. Hitlist is filled. Die. - */ + /* All candidates should have been detached by now. */ + BUG_ON(!list_empty(&gc_candidates)); + gc_in_progress = false; - __skb_queue_purge(&hitlist); - mutex_unlock(&unix_gc_sem); + out: + spin_unlock(&unix_gc_lock); } -- cgit v1.2.3 From db3d99c090e0cdb34b1274767e062bfddbb384bc Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 11 Jul 2007 19:46:26 -0700 Subject: [NET_SCHED]: ematch: module autoloading Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/pkt_cls.h | 17 +++++++---------- include/net/pkt_cls.h | 2 ++ net/sched/em_cmp.c | 1 + net/sched/em_meta.c | 2 ++ net/sched/em_nbyte.c | 2 ++ net/sched/em_text.c | 2 ++ net/sched/em_u32.c | 2 ++ net/sched/ematch.c | 13 +++++++++++++ 8 files changed, 31 insertions(+), 10 deletions(-) (limited to 'include/net') diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index c3f01b3085a4..30b8571e6b34 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -403,16 +403,13 @@ enum * 1..32767 Reserved for ematches inside kernel tree * 32768..65535 Free to use, not reliable */ -enum -{ - TCF_EM_CONTAINER, - TCF_EM_CMP, - TCF_EM_NBYTE, - TCF_EM_U32, - TCF_EM_META, - TCF_EM_TEXT, - __TCF_EM_MAX -}; +#define TCF_EM_CONTAINER 0 +#define TCF_EM_CMP 1 +#define TCF_EM_NBYTE 2 +#define TCF_EM_U32 3 +#define TCF_EM_META 4 +#define TCF_EM_TEXT 5 +#define TCF_EM_MAX 5 enum { diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 4129df708079..6c29920cbe29 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -306,6 +306,8 @@ static inline int tcf_em_tree_match(struct sk_buff *skb, return 1; } +#define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind)) + #else /* CONFIG_NET_EMATCH */ struct tcf_ematch_tree diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c index 8d6dacd81900..cc49c932641d 100644 --- a/net/sched/em_cmp.c +++ b/net/sched/em_cmp.c @@ -98,3 +98,4 @@ MODULE_LICENSE("GPL"); module_init(init_em_cmp); module_exit(exit_em_cmp); +MODULE_ALIAS_TCF_EMATCH(TCF_EM_CMP); diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 60acf8cdb27b..650f09c8bd6a 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -848,3 +848,5 @@ MODULE_LICENSE("GPL"); module_init(init_em_meta); module_exit(exit_em_meta); + +MODULE_ALIAS_TCF_EMATCH(TCF_EM_META); diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c index b4b36efce292..370a1b2ea317 100644 --- a/net/sched/em_nbyte.c +++ b/net/sched/em_nbyte.c @@ -76,3 +76,5 @@ MODULE_LICENSE("GPL"); module_init(init_em_nbyte); module_exit(exit_em_nbyte); + +MODULE_ALIAS_TCF_EMATCH(TCF_EM_NBYTE); diff --git a/net/sched/em_text.c b/net/sched/em_text.c index e8f46169449d..d5cd86efb7d0 100644 --- a/net/sched/em_text.c +++ b/net/sched/em_text.c @@ -150,3 +150,5 @@ MODULE_LICENSE("GPL"); module_init(init_em_text); module_exit(exit_em_text); + +MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT); diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c index 0a2a7fe08de3..112796e4a7c4 100644 --- a/net/sched/em_u32.c +++ b/net/sched/em_u32.c @@ -60,3 +60,5 @@ MODULE_LICENSE("GPL"); module_init(init_em_u32); module_exit(exit_em_u32); + +MODULE_ALIAS_TCF_EMATCH(TCF_EM_U32); diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 24837391640d..f3a104e323bd 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -222,6 +222,19 @@ static int tcf_em_validate(struct tcf_proto *tp, if (em->ops == NULL) { err = -ENOENT; +#ifdef CONFIG_KMOD + __rtnl_unlock(); + request_module("ematch-kind-%u", em_hdr->kind); + rtnl_lock(); + em->ops = tcf_em_lookup(em_hdr->kind); + if (em->ops) { + /* We dropped the RTNL mutex in order to + * perform the module load. Tell the caller + * to replay the request. */ + module_put(em->ops->owner); + err = -EAGAIN; + } +#endif goto errout; } -- cgit v1.2.3 From 179f831bc33104d14deb54a52b7a8b43433f8ccc Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Jul 2007 19:29:38 +0200 Subject: [PATCH] cfg80211: Radiotap parser Generic code to walk through the fields in a radiotap header, accounting for nasties like extended "field present" bitfields and alignment rules Signed-off-by: Andy Green Signed-off-by: Jiri Benc Signed-off-by: John W. Linville --- Documentation/networking/radiotap-headers.txt | 65 +++++++ include/net/cfg80211.h | 38 ++++ net/wireless/Makefile | 2 +- net/wireless/radiotap.c | 257 ++++++++++++++++++++++++++ 4 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 net/wireless/radiotap.c (limited to 'include/net') diff --git a/Documentation/networking/radiotap-headers.txt b/Documentation/networking/radiotap-headers.txt index e29e027d9be3..953331c7984f 100644 --- a/Documentation/networking/radiotap-headers.txt +++ b/Documentation/networking/radiotap-headers.txt @@ -84,4 +84,69 @@ Example valid radiotap header 0x01 //<-- antenna +Using the Radiotap Parser +------------------------- + +If you are having to parse a radiotap struct, you can radically simplify the +job by using the radiotap parser that lives in net/wireless/radiotap.c and has +its prototypes available in include/net/cfg80211.h. You use it like this: + +#include + +/* buf points to the start of the radiotap header part */ + +int MyFunction(u8 * buf, int buflen) +{ + int pkt_rate_100kHz = 0, antenna = 0, pwr = 0; + struct ieee80211_radiotap_iterator iterator; + int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen); + + while (!ret) { + + ret = ieee80211_radiotap_iterator_next(&iterator); + + if (ret) + continue; + + /* see if this argument is something we can use */ + + switch (iterator.this_arg_index) { + /* + * You must take care when dereferencing iterator.this_arg + * for multibyte types... the pointer is not aligned. Use + * get_unaligned((type *)iterator.this_arg) to dereference + * iterator.this_arg for type "type" safely on all arches. + */ + case IEEE80211_RADIOTAP_RATE: + /* radiotap "rate" u8 is in + * 500kbps units, eg, 0x02=1Mbps + */ + pkt_rate_100kHz = (*iterator.this_arg) * 5; + break; + + case IEEE80211_RADIOTAP_ANTENNA: + /* radiotap uses 0 for 1st ant */ + antenna = *iterator.this_arg); + break; + + case IEEE80211_RADIOTAP_DBM_TX_POWER: + pwr = *iterator.this_arg; + break; + + default: + break; + } + } /* while more rt headers */ + + if (ret != -ENOENT) + return TXRX_DROP; + + /* discard the radiotap header part */ + buf += iterator.max_length; + buflen -= iterator.max_length; + + ... + +} + Andy Green diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 88171f8ce58a..7edaef6b29d6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -11,6 +11,44 @@ * Copyright 2006 Johannes Berg */ + +/* Radiotap header iteration + * implemented in net/wireless/radiotap.c + * docs in Documentation/networking/radiotap-headers.txt + */ +/** + * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args + * @rtheader: pointer to the radiotap header we are walking through + * @max_length: length of radiotap header in cpu byte ordering + * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg + * @this_arg: pointer to current radiotap arg + * @arg_index: internal next argument index + * @arg: internal next argument pointer + * @next_bitmap: internal pointer to next present u32 + * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + */ + +struct ieee80211_radiotap_iterator { + struct ieee80211_radiotap_header *rtheader; + int max_length; + int this_arg_index; + u8 *this_arg; + + int arg_index; + u8 *arg; + __le32 *next_bitmap; + u32 bitmap_shifter; +}; + +extern int ieee80211_radiotap_iterator_init( + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length); + +extern int ieee80211_radiotap_iterator_next( + struct ieee80211_radiotap_iterator *iterator); + + /* from net/wireless.h */ struct wiphy; diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 3a96ae60271c..092116e390b6 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_WIRELESS_EXT) += wext.o obj-$(CONFIG_CFG80211) += cfg80211.o -cfg80211-y += core.o sysfs.o +cfg80211-y += core.o sysfs.o radiotap.o diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c new file mode 100644 index 000000000000..68c11d099917 --- /dev/null +++ b/net/wireless/radiotap.c @@ -0,0 +1,257 @@ +/* + * Radiotap parser + * + * Copyright 2007 Andy Green + */ + +#include +#include +#include + +/* function prototypes and related defs are in include/net/cfg80211.h */ + +/** + * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization + * @iterator: radiotap_iterator to initialize + * @radiotap_header: radiotap header to parse + * @max_length: total length we can parse into (eg, whole packet length) + * + * Returns: 0 or a negative error code if there is a problem. + * + * This function initializes an opaque iterator struct which can then + * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap + * argument which is present in the header. It knows about extended + * present headers and handles them. + * + * How to use: + * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator + * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) + * checking for a good 0 return code. Then loop calling + * __ieee80211_radiotap_iterator_next()... it returns either 0, + * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. + * The iterator's @this_arg member points to the start of the argument + * associated with the current argument index that is present, which can be + * found in the iterator's @this_arg_index member. This arg index corresponds + * to the IEEE80211_RADIOTAP_... defines. + * + * Radiotap header length: + * You can find the CPU-endian total radiotap header length in + * iterator->max_length after executing ieee80211_radiotap_iterator_init() + * successfully. + * + * Alignment Gotcha: + * You must take care when dereferencing iterator.this_arg + * for multibyte types... the pointer is not aligned. Use + * get_unaligned((type *)iterator.this_arg) to dereference + * iterator.this_arg for type "type" safely on all arches. + * + * Example code: + * See Documentation/networking/radiotap-headers.txt + */ + +int ieee80211_radiotap_iterator_init( + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length) +{ + /* Linux only supports version 0 radiotap format */ + if (radiotap_header->it_version) + return -EINVAL; + + /* sanity check for allowed length and radiotap length field */ + if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) + return -EINVAL; + + iterator->rtheader = radiotap_header; + iterator->max_length = le16_to_cpu(get_unaligned( + &radiotap_header->it_len)); + iterator->arg_index = 0; + iterator->bitmap_shifter = le32_to_cpu(get_unaligned( + &radiotap_header->it_present)); + iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); + iterator->this_arg = NULL; + + /* find payload start allowing for extended bitmap(s) */ + + if (unlikely(iterator->bitmap_shifter & (1<arg)) & + (1<arg += sizeof(u32); + + /* + * check for insanity where the present bitmaps + * keep claiming to extend up to or even beyond the + * stated radiotap header length + */ + + if (((ulong)iterator->arg - + (ulong)iterator->rtheader) > iterator->max_length) + return -EINVAL; + } + + iterator->arg += sizeof(u32); + + /* + * no need to check again for blowing past stated radiotap + * header length, because ieee80211_radiotap_iterator_next + * checks it before it is dereferenced + */ + } + + /* we are all initialized happily */ + + return 0; +} +EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); + + +/** + * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg + * @iterator: radiotap_iterator to move to next arg (if any) + * + * Returns: 0 if there is an argument to handle, + * -ENOENT if there are no more args or -EINVAL + * if there is something else wrong. + * + * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) + * in @this_arg_index and sets @this_arg to point to the + * payload for the field. It takes care of alignment handling and extended + * present fields. @this_arg can be changed by the caller (eg, + * incremented to move inside a compound argument like + * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in + * little-endian format whatever the endianess of your CPU. + * + * Alignment Gotcha: + * You must take care when dereferencing iterator.this_arg + * for multibyte types... the pointer is not aligned. Use + * get_unaligned((type *)iterator.this_arg) to dereference + * iterator.this_arg for type "type" safely on all arches. + */ + +int ieee80211_radiotap_iterator_next( + struct ieee80211_radiotap_iterator *iterator) +{ + + /* + * small length lookup table for all radiotap types we heard of + * starting from b0 in the bitmap, so we can walk the payload + * area of the radiotap header + * + * There is a requirement to pad args, so that args + * of a given length must begin at a boundary of that length + * -- but note that compound args are allowed (eg, 2 x u16 + * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not + * a reliable indicator of alignment requirement. + * + * upper nybble: content alignment for arg + * lower nybble: content length for arg + */ + + static const u8 rt_sizes[] = { + [IEEE80211_RADIOTAP_TSFT] = 0x88, + [IEEE80211_RADIOTAP_FLAGS] = 0x11, + [IEEE80211_RADIOTAP_RATE] = 0x11, + [IEEE80211_RADIOTAP_CHANNEL] = 0x24, + [IEEE80211_RADIOTAP_FHSS] = 0x22, + [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, + [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, + [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, + [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, + [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, + [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, + [IEEE80211_RADIOTAP_ANTENNA] = 0x11, + [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, + [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11 + /* + * add more here as they are defined in + * include/net/ieee80211_radiotap.h + */ + }; + + /* + * for every radiotap entry we can at + * least skip (by knowing the length)... + */ + + while (iterator->arg_index < sizeof(rt_sizes)) { + int hit = 0; + int pad; + + if (!(iterator->bitmap_shifter & 1)) + goto next_entry; /* arg not present */ + + /* + * arg is present, account for alignment padding + * 8-bit args can be at any alignment + * 16-bit args must start on 16-bit boundary + * 32-bit args must start on 32-bit boundary + * 64-bit args must start on 64-bit boundary + * + * note that total arg size can differ from alignment of + * elements inside arg, so we use upper nybble of length + * table to base alignment on + * + * also note: these alignments are ** relative to the + * start of the radiotap header **. There is no guarantee + * that the radiotap header itself is aligned on any + * kind of boundary. + * + * the above is why get_unaligned() is used to dereference + * multibyte elements from the radiotap area + */ + + pad = (((ulong)iterator->arg) - + ((ulong)iterator->rtheader)) & + ((rt_sizes[iterator->arg_index] >> 4) - 1); + + if (pad) + iterator->arg += + (rt_sizes[iterator->arg_index] >> 4) - pad; + + /* + * this is what we will return to user, but we need to + * move on first so next call has something fresh to test + */ + iterator->this_arg_index = iterator->arg_index; + iterator->this_arg = iterator->arg; + hit = 1; + + /* internally move on the size of this arg */ + iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; + + /* + * check for insanity where we are given a bitmap that + * claims to have more arg content than the length of the + * radiotap section. We will normally end up equalling this + * max_length on the last arg, never exceeding it. + */ + + if (((ulong)iterator->arg - (ulong)iterator->rtheader) > + iterator->max_length) + return -EINVAL; + + next_entry: + iterator->arg_index++; + if (unlikely((iterator->arg_index & 31) == 0)) { + /* completed current u32 bitmap */ + if (iterator->bitmap_shifter & 1) { + /* b31 was set, there is more */ + /* move to next u32 bitmap */ + iterator->bitmap_shifter = le32_to_cpu( + get_unaligned(iterator->next_bitmap)); + iterator->next_bitmap++; + } else + /* no more bitmaps: end */ + iterator->arg_index = sizeof(rt_sizes); + } else /* just try the next bit */ + iterator->bitmap_shifter >>= 1; + + /* if we found a valid arg earlier, return it now */ + if (hit) + return 0; + } + + /* we don't know how to handle any more args, we're done */ + return -ENOENT; +} +EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); -- cgit v1.2.3 From c59304b5e07128816347fe3996d7952561f60529 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Jul 2007 19:32:08 +0200 Subject: [PATCH] mac80211: remove ieee80211_set_aid_for_sta Remove ieee80211_set_aid_for_sta and associated code. Signed-off-by: Johannes Berg Signed-off-by: Jiri Benc Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ------ net/mac80211/ieee80211.c | 28 ---------------------------- net/mac80211/ieee80211_common.h | 7 +------ 3 files changed, 1 insertion(+), 40 deletions(-) (limited to 'include/net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a7f122b79948..627885765a36 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -921,12 +921,6 @@ struct sk_buff * ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, struct ieee80211_tx_control *control); -/* Low level drivers that have their own MLME and MAC indicate - * the aid for an associating station with this call */ -int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, - u8 *peer_address, u16 aid); - - /* Given an sk_buff with a raw 802.11 header at the data pointer this function * returns the 802.11 header length in bytes (not including encryption * headers). If the data in the sk_buff is too short to contain a valid 802.11 diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 85f23fd866ad..4bcf18097e53 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -3165,34 +3165,6 @@ int ieee80211_radar_status(struct ieee80211_hw *hw, int channel, } EXPORT_SYMBOL(ieee80211_radar_status); -int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address, - u16 aid) -{ - struct sk_buff *skb; - struct ieee80211_msg_set_aid_for_sta *msg; - struct ieee80211_local *local = hw_to_local(hw); - - /* unlikely because if this event only happens for APs, - * which require an open ap device. */ - if (unlikely(!local->apdev)) - return 0; - - skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + - sizeof(struct ieee80211_msg_set_aid_for_sta)); - - if (!skb) - return -ENOMEM; - skb_reserve(skb, sizeof(struct ieee80211_frame_info)); - - msg = (struct ieee80211_msg_set_aid_for_sta *) - skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta)); - memcpy(msg->sta_address, peer_address, ETH_ALEN); - msg->aid = aid; - - ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta); - return 0; -} -EXPORT_SYMBOL(ieee80211_set_aid_for_sta); static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) { diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h index 7af6710bf718..77c6afb7f6a8 100644 --- a/net/mac80211/ieee80211_common.h +++ b/net/mac80211/ieee80211_common.h @@ -52,16 +52,11 @@ enum ieee80211_msg_type { ieee80211_msg_michael_mic_failure = 5, /* hole at 6, was monitor but never sent to userspace */ ieee80211_msg_sta_not_assoc = 7, - ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */, + /* 8 was ieee80211_msg_set_aid_for_sta */ ieee80211_msg_key_threshold_notification = 9, ieee80211_msg_radar = 11, }; -struct ieee80211_msg_set_aid_for_sta { - char sta_address[ETH_ALEN]; - u16 aid; -}; - struct ieee80211_msg_key_notification { int tx_rx_count; char ifname[IFNAMSIZ]; -- cgit v1.2.3 From 4480f15ca62a595248d6d8e2b3e75052113cde59 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Jul 2007 19:32:10 +0200 Subject: [PATCH] mac80211: clarify some mac80211 things The semantics of not having an add_interface callback are not well defined, this callback is required because otherwise you cannot obtain the requested MAC address of the device. Change the documentation to reflect this, add a note about having no MAC address at all, add a warning that mac_addr in struct ieee80211_if_init_conf can be NULL and finally verify that a few callbacks are assigned by way of BUG_ON() Signed-off-by: Johannes Berg Signed-off-by: Jiri Benc Signed-off-by: John W. Linville --- include/net/mac80211.h | 16 ++++++++++++---- net/mac80211/ieee80211.c | 29 ++++++++++++----------------- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'include/net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 627885765a36..c34fd9a6160a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -347,9 +347,16 @@ enum ieee80211_if_types { * @mac_addr: pointer to MAC address of the interface. This pointer is valid * until the interface is removed (i.e. it cannot be used after * remove_interface() callback was called for this interface). + * This pointer will be %NULL for monitor interfaces, be careful. * * This structure is used in add_interface() and remove_interface() * callbacks of &struct ieee80211_hw. + * + * When you allow multiple interfaces to be added to your PHY, take care + * that the hardware can actually handle multiple MAC addresses. However, + * also take care that when there's no interface left with mac_addr != %NULL + * you remove the MAC address from the device to avoid acknowledging packets + * in pure monitor mode. */ struct ieee80211_if_init_conf { int if_id; @@ -574,10 +581,11 @@ struct ieee80211_ops { * to returning zero. By returning non-zero addition of the interface * is inhibited. Unless monitor_during_oper is set, it is guaranteed * that monitor interfaces and normal interfaces are mutually - * exclusive. The open() handler is called after add_interface() - * if this is the first device added. At least one of the open() - * open() and add_interface() callbacks has to be assigned. If - * add_interface() is NULL, one STA interface is permitted only. */ + * exclusive. If assigned, the open() handler is called after + * add_interface() if this is the first device added. The + * add_interface() callback has to be assigned because it is the only + * way to obtain the requested MAC address for any interface. + */ int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 773a103ee3a1..fe32a2d16053 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -2605,8 +2605,7 @@ static void ieee80211_start_hard_monitor(struct ieee80211_local *local) struct ieee80211_if_init_conf conf; if (local->open_count && local->open_count == local->monitors && - !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && - local->ops->add_interface) { + !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { conf.if_id = -1; conf.type = IEEE80211_IF_TYPE_MNTR; conf.mac_addr = NULL; @@ -2649,21 +2648,14 @@ static int ieee80211_open(struct net_device *dev) } ieee80211_start_soft_monitor(local); - if (local->ops->add_interface) { - conf.if_id = dev->ifindex; - conf.type = sdata->type; - conf.mac_addr = dev->dev_addr; - res = local->ops->add_interface(local_to_hw(local), &conf); - if (res) { - if (sdata->type == IEEE80211_IF_TYPE_MNTR) - ieee80211_start_hard_monitor(local); - return res; - } - } else { - if (sdata->type != IEEE80211_IF_TYPE_STA) - return -EOPNOTSUPP; - if (local->open_count > 0) - return -ENOBUFS; + conf.if_id = dev->ifindex; + conf.type = sdata->type; + conf.mac_addr = dev->dev_addr; + res = local->ops->add_interface(local_to_hw(local), &conf); + if (res) { + if (sdata->type == IEEE80211_IF_TYPE_MNTR) + ieee80211_start_hard_monitor(local); + return res; } if (local->open_count == 0) { @@ -4896,6 +4888,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ((sizeof(struct ieee80211_local) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); + BUG_ON(!ops->tx); + BUG_ON(!ops->config); + BUG_ON(!ops->add_interface); local->ops = ops; /* for now, mdev needs sub_if_data :/ */ -- cgit v1.2.3 From bd238fb431f31989898423c8b6496bc8c4204a86 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Tue, 10 Jul 2007 17:57:28 -0500 Subject: 9p: Reorganization of 9p file system code This patchset moves non-filesystem interfaces of v9fs from fs/9p to net/9p. It moves the transport, packet marshalling and connection layers to net/9p leaving only the VFS related files in fs/9p. This work is being done in preparation for in-kernel 9p servers as well as alternate 9p clients (other than VFS). Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen --- fs/9p/9p.h | 375 ---------------- fs/9p/Makefile | 6 - fs/9p/conv.c | 845 ----------------------------------- fs/9p/conv.h | 50 --- fs/9p/debug.h | 77 ---- fs/9p/error.c | 93 ---- fs/9p/error.h | 177 -------- fs/9p/fcall.c | 427 ------------------ fs/9p/fcprint.c | 345 --------------- fs/9p/fid.c | 168 +++---- fs/9p/fid.h | 43 +- fs/9p/mux.c | 1033 ------------------------------------------- fs/9p/mux.h | 55 --- fs/9p/trans_fd.c | 308 ------------- fs/9p/transport.h | 45 -- fs/9p/v9fs.c | 288 +++--------- fs/9p/v9fs.h | 32 +- fs/9p/v9fs_vfs.h | 6 +- fs/9p/vfs_addr.c | 57 +-- fs/9p/vfs_dentry.c | 37 +- fs/9p/vfs_dir.c | 155 ++----- fs/9p/vfs_file.c | 160 ++----- fs/9p/vfs_inode.c | 753 ++++++++++++------------------- fs/9p/vfs_super.c | 91 ++-- fs/Kconfig | 2 +- include/net/9p/9p.h | 417 ++++++++++++++++++ include/net/9p/client.h | 80 ++++ include/net/9p/conn.h | 57 +++ include/net/9p/transport.h | 49 +++ net/9p/Kconfig | 21 + net/9p/Makefile | 13 + net/9p/client.c | 965 ++++++++++++++++++++++++++++++++++++++++ net/9p/conv.c | 903 +++++++++++++++++++++++++++++++++++++ net/9p/error.c | 240 ++++++++++ net/9p/fcprint.c | 358 +++++++++++++++ net/9p/mod.c | 85 ++++ net/9p/mux.c | 1050 ++++++++++++++++++++++++++++++++++++++++++++ net/9p/sysctl.c | 86 ++++ net/9p/trans_fd.c | 363 +++++++++++++++ net/9p/util.c | 125 ++++++ net/Kconfig | 1 + net/Makefile | 1 + 42 files changed, 5367 insertions(+), 5075 deletions(-) delete mode 100644 fs/9p/9p.h delete mode 100644 fs/9p/conv.c delete mode 100644 fs/9p/conv.h delete mode 100644 fs/9p/debug.h delete mode 100644 fs/9p/error.c delete mode 100644 fs/9p/error.h delete mode 100644 fs/9p/fcall.c delete mode 100644 fs/9p/fcprint.c delete mode 100644 fs/9p/mux.c delete mode 100644 fs/9p/mux.h delete mode 100644 fs/9p/trans_fd.c delete mode 100644 fs/9p/transport.h create mode 100644 include/net/9p/9p.h create mode 100644 include/net/9p/client.h create mode 100644 include/net/9p/conn.h create mode 100644 include/net/9p/transport.h create mode 100644 net/9p/Kconfig create mode 100644 net/9p/Makefile create mode 100644 net/9p/client.c create mode 100644 net/9p/conv.c create mode 100644 net/9p/error.c create mode 100644 net/9p/fcprint.c create mode 100644 net/9p/mod.c create mode 100644 net/9p/mux.c create mode 100644 net/9p/sysctl.c create mode 100644 net/9p/trans_fd.c create mode 100644 net/9p/util.c (limited to 'include/net') diff --git a/fs/9p/9p.h b/fs/9p/9p.h deleted file mode 100644 index 94e2f92ab2e8..000000000000 --- a/fs/9p/9p.h +++ /dev/null @@ -1,375 +0,0 @@ -/* - * linux/fs/9p/9p.h - * - * 9P protocol definitions. - * - * Copyright (C) 2005 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -/* Message Types */ -enum { - TVERSION = 100, - RVERSION, - TAUTH = 102, - RAUTH, - TATTACH = 104, - RATTACH, - TERROR = 106, - RERROR, - TFLUSH = 108, - RFLUSH, - TWALK = 110, - RWALK, - TOPEN = 112, - ROPEN, - TCREATE = 114, - RCREATE, - TREAD = 116, - RREAD, - TWRITE = 118, - RWRITE, - TCLUNK = 120, - RCLUNK, - TREMOVE = 122, - RREMOVE, - TSTAT = 124, - RSTAT, - TWSTAT = 126, - RWSTAT, -}; - -/* modes */ -enum { - V9FS_OREAD = 0x00, - V9FS_OWRITE = 0x01, - V9FS_ORDWR = 0x02, - V9FS_OEXEC = 0x03, - V9FS_OEXCL = 0x04, - V9FS_OTRUNC = 0x10, - V9FS_OREXEC = 0x20, - V9FS_ORCLOSE = 0x40, - V9FS_OAPPEND = 0x80, -}; - -/* permissions */ -enum { - V9FS_DMDIR = 0x80000000, - V9FS_DMAPPEND = 0x40000000, - V9FS_DMEXCL = 0x20000000, - V9FS_DMMOUNT = 0x10000000, - V9FS_DMAUTH = 0x08000000, - V9FS_DMTMP = 0x04000000, - V9FS_DMSYMLINK = 0x02000000, - V9FS_DMLINK = 0x01000000, - /* 9P2000.u extensions */ - V9FS_DMDEVICE = 0x00800000, - V9FS_DMNAMEDPIPE = 0x00200000, - V9FS_DMSOCKET = 0x00100000, - V9FS_DMSETUID = 0x00080000, - V9FS_DMSETGID = 0x00040000, -}; - -/* qid.types */ -enum { - V9FS_QTDIR = 0x80, - V9FS_QTAPPEND = 0x40, - V9FS_QTEXCL = 0x20, - V9FS_QTMOUNT = 0x10, - V9FS_QTAUTH = 0x08, - V9FS_QTTMP = 0x04, - V9FS_QTSYMLINK = 0x02, - V9FS_QTLINK = 0x01, - V9FS_QTFILE = 0x00, -}; - -#define V9FS_NOTAG (u16)(~0) -#define V9FS_NOFID (u32)(~0) -#define V9FS_MAXWELEM 16 - -/* ample room for Twrite/Rread header (iounit) */ -#define V9FS_IOHDRSZ 24 - -struct v9fs_str { - u16 len; - char *str; -}; - -/* qids are the unique ID for a file (like an inode */ -struct v9fs_qid { - u8 type; - u32 version; - u64 path; -}; - -/* Plan 9 file metadata (stat) structure */ -struct v9fs_stat { - u16 size; - u16 type; - u32 dev; - struct v9fs_qid qid; - u32 mode; - u32 atime; - u32 mtime; - u64 length; - struct v9fs_str name; - struct v9fs_str uid; - struct v9fs_str gid; - struct v9fs_str muid; - struct v9fs_str extension; /* 9p2000.u extensions */ - u32 n_uid; /* 9p2000.u extensions */ - u32 n_gid; /* 9p2000.u extensions */ - u32 n_muid; /* 9p2000.u extensions */ -}; - -/* file metadata (stat) structure used to create Twstat message - The is similar to v9fs_stat, but the strings don't point to - the same memory block and should be freed separately -*/ -struct v9fs_wstat { - u16 size; - u16 type; - u32 dev; - struct v9fs_qid qid; - u32 mode; - u32 atime; - u32 mtime; - u64 length; - char *name; - char *uid; - char *gid; - char *muid; - char *extension; /* 9p2000.u extensions */ - u32 n_uid; /* 9p2000.u extensions */ - u32 n_gid; /* 9p2000.u extensions */ - u32 n_muid; /* 9p2000.u extensions */ -}; - -/* Structures for Protocol Operations */ - -struct Tversion { - u32 msize; - struct v9fs_str version; -}; - -struct Rversion { - u32 msize; - struct v9fs_str version; -}; - -struct Tauth { - u32 afid; - struct v9fs_str uname; - struct v9fs_str aname; -}; - -struct Rauth { - struct v9fs_qid qid; -}; - -struct Rerror { - struct v9fs_str error; - u32 errno; /* 9p2000.u extension */ -}; - -struct Tflush { - u16 oldtag; -}; - -struct Rflush { -}; - -struct Tattach { - u32 fid; - u32 afid; - struct v9fs_str uname; - struct v9fs_str aname; -}; - -struct Rattach { - struct v9fs_qid qid; -}; - -struct Twalk { - u32 fid; - u32 newfid; - u16 nwname; - struct v9fs_str wnames[16]; -}; - -struct Rwalk { - u16 nwqid; - struct v9fs_qid wqids[16]; -}; - -struct Topen { - u32 fid; - u8 mode; -}; - -struct Ropen { - struct v9fs_qid qid; - u32 iounit; -}; - -struct Tcreate { - u32 fid; - struct v9fs_str name; - u32 perm; - u8 mode; - struct v9fs_str extension; -}; - -struct Rcreate { - struct v9fs_qid qid; - u32 iounit; -}; - -struct Tread { - u32 fid; - u64 offset; - u32 count; -}; - -struct Rread { - u32 count; - u8 *data; -}; - -struct Twrite { - u32 fid; - u64 offset; - u32 count; - u8 *data; -}; - -struct Rwrite { - u32 count; -}; - -struct Tclunk { - u32 fid; -}; - -struct Rclunk { -}; - -struct Tremove { - u32 fid; -}; - -struct Rremove { -}; - -struct Tstat { - u32 fid; -}; - -struct Rstat { - struct v9fs_stat stat; -}; - -struct Twstat { - u32 fid; - struct v9fs_stat stat; -}; - -struct Rwstat { -}; - -/* - * fcall is the primary packet structure - * - */ - -struct v9fs_fcall { - u32 size; - u8 id; - u16 tag; - void *sdata; - - union { - struct Tversion tversion; - struct Rversion rversion; - struct Tauth tauth; - struct Rauth rauth; - struct Rerror rerror; - struct Tflush tflush; - struct Rflush rflush; - struct Tattach tattach; - struct Rattach rattach; - struct Twalk twalk; - struct Rwalk rwalk; - struct Topen topen; - struct Ropen ropen; - struct Tcreate tcreate; - struct Rcreate rcreate; - struct Tread tread; - struct Rread rread; - struct Twrite twrite; - struct Rwrite rwrite; - struct Tclunk tclunk; - struct Rclunk rclunk; - struct Tremove tremove; - struct Rremove rremove; - struct Tstat tstat; - struct Rstat rstat; - struct Twstat twstat; - struct Rwstat rwstat; - } params; -}; - -#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \ - fcall?fcall->params.rerror.error.len:0, \ - fcall?fcall->params.rerror.error.str:""); - -int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, - char *version, struct v9fs_fcall **rcall); - -int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, - u32 fid, u32 afid, struct v9fs_fcall **rcall); - -int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid); - -int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, - struct v9fs_fcall **rcall); - -int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, - struct v9fs_wstat *wstat, struct v9fs_fcall **rcall); - -int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, - char *name, struct v9fs_fcall **rcall); - -int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, - struct v9fs_fcall **rcall); - -int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, - struct v9fs_fcall **rcall); - -int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, - u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall); - -int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, - u64 offset, u32 count, struct v9fs_fcall **rcall); - -int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, - u32 count, const char __user * data, - struct v9fs_fcall **rcall); -int v9fs_printfcall(char *, int, struct v9fs_fcall *, int); diff --git a/fs/9p/Makefile b/fs/9p/Makefile index 87897f84dfb6..bc7f0d1551e6 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile @@ -1,18 +1,12 @@ obj-$(CONFIG_9P_FS) := 9p.o 9p-objs := \ - trans_fd.o \ - mux.o \ - fcall.o \ - conv.o \ vfs_super.o \ vfs_inode.o \ vfs_addr.o \ vfs_file.o \ vfs_dir.o \ vfs_dentry.o \ - error.o \ v9fs.o \ fid.o \ - fcprint.o diff --git a/fs/9p/conv.c b/fs/9p/conv.c deleted file mode 100644 index a3ed571eee31..000000000000 --- a/fs/9p/conv.c +++ /dev/null @@ -1,845 +0,0 @@ -/* - * linux/fs/9p/conv.c - * - * 9P protocol conversion functions - * - * Copyright (C) 2004, 2005 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include "debug.h" -#include "v9fs.h" -#include "9p.h" -#include "conv.h" - -/* - * Buffer to help with string parsing - */ -struct cbuf { - unsigned char *sp; - unsigned char *p; - unsigned char *ep; -}; - -static inline void buf_init(struct cbuf *buf, void *data, int datalen) -{ - buf->sp = buf->p = data; - buf->ep = data + datalen; -} - -static inline int buf_check_overflow(struct cbuf *buf) -{ - return buf->p > buf->ep; -} - -static int buf_check_size(struct cbuf *buf, int len) -{ - if (buf->p + len > buf->ep) { - if (buf->p < buf->ep) { - eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", - len, (int)(buf->ep - buf->p)); - dump_stack(); - buf->p = buf->ep + 1; - } - - return 0; - } - - return 1; -} - -static void *buf_alloc(struct cbuf *buf, int len) -{ - void *ret = NULL; - - if (buf_check_size(buf, len)) { - ret = buf->p; - buf->p += len; - } - - return ret; -} - -static void buf_put_int8(struct cbuf *buf, u8 val) -{ - if (buf_check_size(buf, 1)) { - buf->p[0] = val; - buf->p++; - } -} - -static void buf_put_int16(struct cbuf *buf, u16 val) -{ - if (buf_check_size(buf, 2)) { - *(__le16 *) buf->p = cpu_to_le16(val); - buf->p += 2; - } -} - -static void buf_put_int32(struct cbuf *buf, u32 val) -{ - if (buf_check_size(buf, 4)) { - *(__le32 *)buf->p = cpu_to_le32(val); - buf->p += 4; - } -} - -static void buf_put_int64(struct cbuf *buf, u64 val) -{ - if (buf_check_size(buf, 8)) { - *(__le64 *)buf->p = cpu_to_le64(val); - buf->p += 8; - } -} - -static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) -{ - char *ret; - - ret = NULL; - if (buf_check_size(buf, slen + 2)) { - buf_put_int16(buf, slen); - ret = buf->p; - memcpy(buf->p, s, slen); - buf->p += slen; - } - - return ret; -} - -static inline void buf_put_string(struct cbuf *buf, const char *s) -{ - buf_put_stringn(buf, s, strlen(s)); -} - -static u8 buf_get_int8(struct cbuf *buf) -{ - u8 ret = 0; - - if (buf_check_size(buf, 1)) { - ret = buf->p[0]; - buf->p++; - } - - return ret; -} - -static u16 buf_get_int16(struct cbuf *buf) -{ - u16 ret = 0; - - if (buf_check_size(buf, 2)) { - ret = le16_to_cpu(*(__le16 *)buf->p); - buf->p += 2; - } - - return ret; -} - -static u32 buf_get_int32(struct cbuf *buf) -{ - u32 ret = 0; - - if (buf_check_size(buf, 4)) { - ret = le32_to_cpu(*(__le32 *)buf->p); - buf->p += 4; - } - - return ret; -} - -static u64 buf_get_int64(struct cbuf *buf) -{ - u64 ret = 0; - - if (buf_check_size(buf, 8)) { - ret = le64_to_cpu(*(__le64 *)buf->p); - buf->p += 8; - } - - return ret; -} - -static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) -{ - vstr->len = buf_get_int16(buf); - if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { - vstr->str = buf->p; - buf->p += vstr->len; - } else { - vstr->len = 0; - vstr->str = NULL; - } -} - -static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) -{ - qid->type = buf_get_int8(bufp); - qid->version = buf_get_int32(bufp); - qid->path = buf_get_int64(bufp); -} - -/** - * v9fs_size_wstat - calculate the size of a variable length stat struct - * @stat: metadata (stat) structure - * @extended: non-zero if 9P2000.u - * - */ - -static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) -{ - int size = 0; - - if (wstat == NULL) { - eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n"); - return 0; - } - - size = /* 2 + *//* size[2] */ - 2 + /* type[2] */ - 4 + /* dev[4] */ - 1 + /* qid.type[1] */ - 4 + /* qid.vers[4] */ - 8 + /* qid.path[8] */ - 4 + /* mode[4] */ - 4 + /* atime[4] */ - 4 + /* mtime[4] */ - 8 + /* length[8] */ - 8; /* minimum sum of string lengths */ - - if (wstat->name) - size += strlen(wstat->name); - if (wstat->uid) - size += strlen(wstat->uid); - if (wstat->gid) - size += strlen(wstat->gid); - if (wstat->muid) - size += strlen(wstat->muid); - - if (extended) { - size += 4 + /* n_uid[4] */ - 4 + /* n_gid[4] */ - 4 + /* n_muid[4] */ - 2; /* string length of extension[4] */ - if (wstat->extension) - size += strlen(wstat->extension); - } - - return size; -} - -/** - * buf_get_stat - safely decode a recieved metadata (stat) structure - * @bufp: buffer to deserialize - * @stat: metadata (stat) structure - * @extended: non-zero if 9P2000.u - * - */ - -static void -buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) -{ - stat->size = buf_get_int16(bufp); - stat->type = buf_get_int16(bufp); - stat->dev = buf_get_int32(bufp); - stat->qid.type = buf_get_int8(bufp); - stat->qid.version = buf_get_int32(bufp); - stat->qid.path = buf_get_int64(bufp); - stat->mode = buf_get_int32(bufp); - stat->atime = buf_get_int32(bufp); - stat->mtime = buf_get_int32(bufp); - stat->length = buf_get_int64(bufp); - buf_get_str(bufp, &stat->name); - buf_get_str(bufp, &stat->uid); - buf_get_str(bufp, &stat->gid); - buf_get_str(bufp, &stat->muid); - - if (extended) { - buf_get_str(bufp, &stat->extension); - stat->n_uid = buf_get_int32(bufp); - stat->n_gid = buf_get_int32(bufp); - stat->n_muid = buf_get_int32(bufp); - } -} - -/** - * v9fs_deserialize_stat - decode a received metadata structure - * @buf: buffer to deserialize - * @buflen: length of received buffer - * @stat: metadata structure to decode into - * @extended: non-zero if 9P2000.u - * - * Note: stat will point to the buf region. - */ - -int -v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, - int extended) -{ - struct cbuf buffer; - struct cbuf *bufp = &buffer; - unsigned char *p; - - buf_init(bufp, buf, buflen); - p = bufp->p; - buf_get_stat(bufp, stat, extended); - - if (buf_check_overflow(bufp)) - return 0; - else - return bufp->p - p; -} - -/** - * deserialize_fcall - unmarshal a response - * @buf: recieved buffer - * @buflen: length of received buffer - * @rcall: fcall structure to populate - * @rcalllen: length of fcall structure to populate - * @extended: non-zero if 9P2000.u - * - */ - -int -v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, - int extended) -{ - - struct cbuf buffer; - struct cbuf *bufp = &buffer; - int i = 0; - - buf_init(bufp, buf, buflen); - - rcall->size = buf_get_int32(bufp); - rcall->id = buf_get_int8(bufp); - rcall->tag = buf_get_int16(bufp); - - dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, - rcall->tag); - - switch (rcall->id) { - default: - eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id); - return -EPROTO; - case RVERSION: - rcall->params.rversion.msize = buf_get_int32(bufp); - buf_get_str(bufp, &rcall->params.rversion.version); - break; - case RFLUSH: - break; - case RATTACH: - rcall->params.rattach.qid.type = buf_get_int8(bufp); - rcall->params.rattach.qid.version = buf_get_int32(bufp); - rcall->params.rattach.qid.path = buf_get_int64(bufp); - break; - case RWALK: - rcall->params.rwalk.nwqid = buf_get_int16(bufp); - if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) { - eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n", - V9FS_MAXWELEM, rcall->params.rwalk.nwqid); - return -EPROTO; - } - - for (i = 0; i < rcall->params.rwalk.nwqid; i++) - buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); - break; - case ROPEN: - buf_get_qid(bufp, &rcall->params.ropen.qid); - rcall->params.ropen.iounit = buf_get_int32(bufp); - break; - case RCREATE: - buf_get_qid(bufp, &rcall->params.rcreate.qid); - rcall->params.rcreate.iounit = buf_get_int32(bufp); - break; - case RREAD: - rcall->params.rread.count = buf_get_int32(bufp); - rcall->params.rread.data = bufp->p; - buf_check_size(bufp, rcall->params.rread.count); - break; - case RWRITE: - rcall->params.rwrite.count = buf_get_int32(bufp); - break; - case RCLUNK: - break; - case RREMOVE: - break; - case RSTAT: - buf_get_int16(bufp); - buf_get_stat(bufp, &rcall->params.rstat.stat, extended); - break; - case RWSTAT: - break; - case RERROR: - buf_get_str(bufp, &rcall->params.rerror.error); - if (extended) - rcall->params.rerror.errno = buf_get_int16(bufp); - break; - } - - if (buf_check_overflow(bufp)) { - dprintk(DEBUG_ERROR, "buffer overflow\n"); - return -EIO; - } - - return bufp->p - bufp->sp; -} - -static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p) -{ - *p = val; - buf_put_int8(bufp, val); -} - -static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p) -{ - *p = val; - buf_put_int16(bufp, val); -} - -static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p) -{ - *p = val; - buf_put_int32(bufp, val); -} - -static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) -{ - *p = val; - buf_put_int64(bufp, val); -} - -static void -v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) -{ - int len; - char *s; - - if (data) - len = strlen(data); - else - len = 0; - - s = buf_put_stringn(bufp, data, len); - if (str) { - str->len = len; - str->str = s; - } -} - -static int -v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, - unsigned char **pdata) -{ - *pdata = buf_alloc(bufp, count); - return copy_from_user(*pdata, data, count); -} - -static void -v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat, - struct v9fs_stat *stat, int statsz, int extended) -{ - v9fs_put_int16(bufp, statsz, &stat->size); - v9fs_put_int16(bufp, wstat->type, &stat->type); - v9fs_put_int32(bufp, wstat->dev, &stat->dev); - v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type); - v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version); - v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path); - v9fs_put_int32(bufp, wstat->mode, &stat->mode); - v9fs_put_int32(bufp, wstat->atime, &stat->atime); - v9fs_put_int32(bufp, wstat->mtime, &stat->mtime); - v9fs_put_int64(bufp, wstat->length, &stat->length); - - v9fs_put_str(bufp, wstat->name, &stat->name); - v9fs_put_str(bufp, wstat->uid, &stat->uid); - v9fs_put_str(bufp, wstat->gid, &stat->gid); - v9fs_put_str(bufp, wstat->muid, &stat->muid); - - if (extended) { - v9fs_put_str(bufp, wstat->extension, &stat->extension); - v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid); - v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid); - v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid); - } -} - -static struct v9fs_fcall * -v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) -{ - struct v9fs_fcall *fc; - - size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ - fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL); - if (!fc) - return ERR_PTR(-ENOMEM); - - fc->sdata = (char *)fc + sizeof(*fc); - - buf_init(bufp, (char *)fc->sdata, size); - v9fs_put_int32(bufp, size, &fc->size); - v9fs_put_int8(bufp, id, &fc->id); - v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag); - - return fc; -} - -void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) -{ - fc->tag = tag; - *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); -} - -struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 2 + strlen(version); /* msize[4] version[s] */ - fc = v9fs_create_common(bufp, size, TVERSION); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, msize, &fc->params.tversion.msize); - v9fs_put_str(bufp, version, &fc->params.tversion.version); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -#if 0 -struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */ - fc = v9fs_create_common(bufp, size, TAUTH); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, afid, &fc->params.tauth.afid); - v9fs_put_str(bufp, uname, &fc->params.tauth.uname); - v9fs_put_str(bufp, aname, &fc->params.tauth.aname); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} -#endif /* 0 */ - -struct v9fs_fcall * -v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */ - fc = v9fs_create_common(bufp, size, TATTACH); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tattach.fid); - v9fs_put_int32(bufp, afid, &fc->params.tattach.afid); - v9fs_put_str(bufp, uname, &fc->params.tattach.uname); - v9fs_put_str(bufp, aname, &fc->params.tattach.aname); - - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tflush(u16 oldtag) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 2; /* oldtag[2] */ - fc = v9fs_create_common(bufp, size, TFLUSH); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, - char **wnames) -{ - int i, size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - if (nwname > V9FS_MAXWELEM) { - dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM); - return NULL; - } - - size = 4 + 4 + 2; /* fid[4] newfid[4] nwname[2] ... */ - for (i = 0; i < nwname; i++) { - size += 2 + strlen(wnames[i]); /* wname[s] */ - } - - fc = v9fs_create_common(bufp, size, TWALK); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.twalk.fid); - v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid); - v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname); - for (i = 0; i < nwname; i++) { - v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); - } - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 1; /* fid[4] mode[1] */ - fc = v9fs_create_common(bufp, size, TOPEN); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.topen.fid); - v9fs_put_int8(bufp, mode, &fc->params.topen.mode); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, - char *extension, int extended) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ - if (extended) { - size += 2 + /* extension[s] */ - (extension == NULL ? 0 : strlen(extension)); - } - - fc = v9fs_create_common(bufp, size, TCREATE); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid); - v9fs_put_str(bufp, name, &fc->params.tcreate.name); - v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm); - v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode); - if (extended) - v9fs_put_str(bufp, extension, &fc->params.tcreate.extension); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ - fc = v9fs_create_common(bufp, size, TREAD); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tread.fid); - v9fs_put_int64(bufp, offset, &fc->params.tread.offset); - v9fs_put_int32(bufp, count, &fc->params.tread.count); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, - const char __user * data) -{ - int size, err; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */ - fc = v9fs_create_common(bufp, size, TWRITE); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.twrite.fid); - v9fs_put_int64(bufp, offset, &fc->params.twrite.offset); - v9fs_put_int32(bufp, count, &fc->params.twrite.count); - err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data); - if (err) { - kfree(fc); - fc = ERR_PTR(err); - } - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tclunk(u32 fid) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4; /* fid[4] */ - fc = v9fs_create_common(bufp, size, TCLUNK); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tremove(u32 fid) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4; /* fid[4] */ - fc = v9fs_create_common(bufp, size, TREMOVE); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tremove.fid); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_tstat(u32 fid) -{ - int size; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - size = 4; /* fid[4] */ - fc = v9fs_create_common(bufp, size, TSTAT); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.tstat.fid); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} - -struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, - int extended) -{ - int size, statsz; - struct v9fs_fcall *fc; - struct cbuf buffer; - struct cbuf *bufp = &buffer; - - statsz = v9fs_size_wstat(wstat, extended); - size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ - fc = v9fs_create_common(bufp, size, TWSTAT); - if (IS_ERR(fc)) - goto error; - - v9fs_put_int32(bufp, fid, &fc->params.twstat.fid); - buf_put_int16(bufp, statsz + 2); - v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended); - - if (buf_check_overflow(bufp)) { - kfree(fc); - fc = ERR_PTR(-ENOMEM); - } - error: - return fc; -} diff --git a/fs/9p/conv.h b/fs/9p/conv.h deleted file mode 100644 index dd5b6b1b610f..000000000000 --- a/fs/9p/conv.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * linux/fs/9p/conv.h - * - * 9P protocol conversion definitions. - * - * Copyright (C) 2005 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, - int extended); -int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, - int extended); - -void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag); - -struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version); -struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname, - char *aname); -struct v9fs_fcall *v9fs_create_tflush(u16 oldtag); -struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, - char **wnames); -struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode); -struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, - char *extension, int extended); -struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count); -struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, - const char __user *data); -struct v9fs_fcall *v9fs_create_tclunk(u32 fid); -struct v9fs_fcall *v9fs_create_tremove(u32 fid); -struct v9fs_fcall *v9fs_create_tstat(u32 fid); -struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, - int extended); diff --git a/fs/9p/debug.h b/fs/9p/debug.h deleted file mode 100644 index 4228c0bb3c32..000000000000 --- a/fs/9p/debug.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * linux/fs/9p/debug.h - V9FS Debug Definitions - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define DEBUG_ERROR (1<<0) -#define DEBUG_CURRENT (1<<1) -#define DEBUG_9P (1<<2) -#define DEBUG_VFS (1<<3) -#define DEBUG_CONV (1<<4) -#define DEBUG_MUX (1<<5) -#define DEBUG_TRANS (1<<6) -#define DEBUG_SLABS (1<<7) -#define DEBUG_FCALL (1<<8) - -#define DEBUG_DUMP_PKT 0 - -extern int v9fs_debug_level; - -#define dprintk(level, format, arg...) \ -do { \ - if((v9fs_debug_level & level)==level) \ - printk(KERN_NOTICE "-- %s (%d): " \ - format , __FUNCTION__, current->pid , ## arg); \ -} while(0) - -#define eprintk(level, format, arg...) \ -do { \ - printk(level "v9fs: %s (%d): " \ - format , __FUNCTION__, current->pid , ## arg); \ -} while(0) - -#if DEBUG_DUMP_PKT -static inline void dump_data(const unsigned char *data, unsigned int datalen) -{ - int i, n; - char buf[5*8]; - - n = 0; - i = 0; - while (i < datalen) { - n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]); - if (i%4 == 0) - n += snprintf(buf+n, sizeof(buf)-n, " "); - - if (i%16 == 0) { - dprintk(DEBUG_ERROR, "%s\n", buf); - n = 0; - } - } - - dprintk(DEBUG_ERROR, "%s\n", buf); -} -#else /* DEBUG_DUMP_PKT */ -static inline void dump_data(const unsigned char *data, unsigned int datalen) -{ - -} -#endif /* DEBUG_DUMP_PKT */ diff --git a/fs/9p/error.c b/fs/9p/error.c deleted file mode 100644 index 0d7fa4e08812..000000000000 --- a/fs/9p/error.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * linux/fs/9p/error.c - * - * Error string handling - * - * Plan 9 uses error strings, Unix uses error numbers. These functions - * try to help manage that and provide for dynamically adding error - * mappings. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include - -#include -#include - -#include "debug.h" -#include "error.h" - -/** - * v9fs_error_init - preload - * @errstr: error string - * - */ - -int v9fs_error_init(void) -{ - struct errormap *c; - int bucket; - - /* initialize hash table */ - for (bucket = 0; bucket < ERRHASHSZ; bucket++) - INIT_HLIST_HEAD(&hash_errmap[bucket]); - - /* load initial error map into hash table */ - for (c = errmap; c->name != NULL; c++) { - c->namelen = strlen(c->name); - bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; - INIT_HLIST_NODE(&c->list); - hlist_add_head(&c->list, &hash_errmap[bucket]); - } - - return 1; -} - -/** - * errstr2errno - convert error string to error number - * @errstr: error string - * - */ - -int v9fs_errstr2errno(char *errstr, int len) -{ - int errno = 0; - struct hlist_node *p = NULL; - struct errormap *c = NULL; - int bucket = jhash(errstr, len, 0) % ERRHASHSZ; - - hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { - if (c->namelen==len && !memcmp(c->name, errstr, len)) { - errno = c->val; - break; - } - } - - if (errno == 0) { - /* TODO: if error isn't found, add it dynamically */ - errstr[len] = 0; - printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, - errstr); - errno = 1; - } - - return -errno; -} diff --git a/fs/9p/error.h b/fs/9p/error.h deleted file mode 100644 index 5f3ca522b316..000000000000 --- a/fs/9p/error.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * linux/fs/9p/error.h - * - * Huge Nasty Error Table - * - * Plan 9 uses error strings, Unix uses error numbers. This table tries to - * match UNIX strings and Plan 9 strings to unix error numbers. It is used - * to preload the dynamic error table which can also track user-specific error - * strings. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include - -struct errormap { - char *name; - int val; - - int namelen; - struct hlist_node list; -}; - -#define ERRHASHSZ 32 -static struct hlist_head hash_errmap[ERRHASHSZ]; - -/* FixMe - reduce to a reasonable size */ -static struct errormap errmap[] = { - {"Operation not permitted", EPERM}, - {"wstat prohibited", EPERM}, - {"No such file or directory", ENOENT}, - {"directory entry not found", ENOENT}, - {"file not found", ENOENT}, - {"Interrupted system call", EINTR}, - {"Input/output error", EIO}, - {"No such device or address", ENXIO}, - {"Argument list too long", E2BIG}, - {"Bad file descriptor", EBADF}, - {"Resource temporarily unavailable", EAGAIN}, - {"Cannot allocate memory", ENOMEM}, - {"Permission denied", EACCES}, - {"Bad address", EFAULT}, - {"Block device required", ENOTBLK}, - {"Device or resource busy", EBUSY}, - {"File exists", EEXIST}, - {"Invalid cross-device link", EXDEV}, - {"No such device", ENODEV}, - {"Not a directory", ENOTDIR}, - {"Is a directory", EISDIR}, - {"Invalid argument", EINVAL}, - {"Too many open files in system", ENFILE}, - {"Too many open files", EMFILE}, - {"Text file busy", ETXTBSY}, - {"File too large", EFBIG}, - {"No space left on device", ENOSPC}, - {"Illegal seek", ESPIPE}, - {"Read-only file system", EROFS}, - {"Too many links", EMLINK}, - {"Broken pipe", EPIPE}, - {"Numerical argument out of domain", EDOM}, - {"Numerical result out of range", ERANGE}, - {"Resource deadlock avoided", EDEADLK}, - {"File name too long", ENAMETOOLONG}, - {"No locks available", ENOLCK}, - {"Function not implemented", ENOSYS}, - {"Directory not empty", ENOTEMPTY}, - {"Too many levels of symbolic links", ELOOP}, - {"No message of desired type", ENOMSG}, - {"Identifier removed", EIDRM}, - {"No data available", ENODATA}, - {"Machine is not on the network", ENONET}, - {"Package not installed", ENOPKG}, - {"Object is remote", EREMOTE}, - {"Link has been severed", ENOLINK}, - {"Communication error on send", ECOMM}, - {"Protocol error", EPROTO}, - {"Bad message", EBADMSG}, - {"File descriptor in bad state", EBADFD}, - {"Streams pipe error", ESTRPIPE}, - {"Too many users", EUSERS}, - {"Socket operation on non-socket", ENOTSOCK}, - {"Message too long", EMSGSIZE}, - {"Protocol not available", ENOPROTOOPT}, - {"Protocol not supported", EPROTONOSUPPORT}, - {"Socket type not supported", ESOCKTNOSUPPORT}, - {"Operation not supported", EOPNOTSUPP}, - {"Protocol family not supported", EPFNOSUPPORT}, - {"Network is down", ENETDOWN}, - {"Network is unreachable", ENETUNREACH}, - {"Network dropped connection on reset", ENETRESET}, - {"Software caused connection abort", ECONNABORTED}, - {"Connection reset by peer", ECONNRESET}, - {"No buffer space available", ENOBUFS}, - {"Transport endpoint is already connected", EISCONN}, - {"Transport endpoint is not connected", ENOTCONN}, - {"Cannot send after transport endpoint shutdown", ESHUTDOWN}, - {"Connection timed out", ETIMEDOUT}, - {"Connection refused", ECONNREFUSED}, - {"Host is down", EHOSTDOWN}, - {"No route to host", EHOSTUNREACH}, - {"Operation already in progress", EALREADY}, - {"Operation now in progress", EINPROGRESS}, - {"Is a named type file", EISNAM}, - {"Remote I/O error", EREMOTEIO}, - {"Disk quota exceeded", EDQUOT}, -/* errors from fossil, vacfs, and u9fs */ - {"fid unknown or out of range", EBADF}, - {"permission denied", EACCES}, - {"file does not exist", ENOENT}, - {"authentication failed", ECONNREFUSED}, - {"bad offset in directory read", ESPIPE}, - {"bad use of fid", EBADF}, - {"wstat can't convert between files and directories", EPERM}, - {"directory is not empty", ENOTEMPTY}, - {"file exists", EEXIST}, - {"file already exists", EEXIST}, - {"file or directory already exists", EEXIST}, - {"fid already in use", EBADF}, - {"file in use", ETXTBSY}, - {"i/o error", EIO}, - {"file already open for I/O", ETXTBSY}, - {"illegal mode", EINVAL}, - {"illegal name", ENAMETOOLONG}, - {"not a directory", ENOTDIR}, - {"not a member of proposed group", EPERM}, - {"not owner", EACCES}, - {"only owner can change group in wstat", EACCES}, - {"read only file system", EROFS}, - {"no access to special file", EPERM}, - {"i/o count too large", EIO}, - {"unknown group", EINVAL}, - {"unknown user", EINVAL}, - {"bogus wstat buffer", EPROTO}, - {"exclusive use file already open", EAGAIN}, - {"corrupted directory entry", EIO}, - {"corrupted file entry", EIO}, - {"corrupted block label", EIO}, - {"corrupted meta data", EIO}, - {"illegal offset", EINVAL}, - {"illegal path element", ENOENT}, - {"root of file system is corrupted", EIO}, - {"corrupted super block", EIO}, - {"protocol botch", EPROTO}, - {"file system is full", ENOSPC}, - {"file is in use", EAGAIN}, - {"directory entry is not allocated", ENOENT}, - {"file is read only", EROFS}, - {"file has been removed", EIDRM}, - {"only support truncation to zero length", EPERM}, - {"cannot remove root", EPERM}, - {"file too big", EFBIG}, - {"venti i/o error", EIO}, - /* these are not errors */ - {"u9fs rhostsauth: no authentication required", 0}, - {"u9fs authnone: no authentication required", 0}, - {NULL, -1} -}; - -extern int v9fs_error_init(void); diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c deleted file mode 100644 index dc336a67592f..000000000000 --- a/fs/9p/fcall.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * linux/fs/9p/fcall.c - * - * This file contains functions to perform synchronous 9P calls - * - * Copyright (C) 2004 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include - -#include "debug.h" -#include "v9fs.h" -#include "9p.h" -#include "conv.h" -#include "mux.h" - -/** - * v9fs_t_version - negotiate protocol parameters with sever - * @v9ses: 9P2000 session information - * @msize: requested max size packet - * @version: requested version.extension string - * @fcall: pointer to response fcall pointer - * - */ - -int -v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, - char *version, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version); - tc = v9fs_create_tversion(msize, version); - - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_attach - mount the server - * @v9ses: 9P2000 session information - * @uname: user name doing the attach - * @aname: remote name being attached to - * @fid: mount fid to attatch to root node - * @afid: authentication fid (in this case result key) - * @fcall: pointer to response fcall pointer - * - */ - -int -v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, - u32 fid, u32 afid, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall* tc; - - dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname, - aname, fid, afid); - - tc = v9fs_create_tattach(fid, afid, uname, aname); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, - struct v9fs_fcall *rc, int err) -{ - int fid, id; - struct v9fs_session_info *v9ses; - - id = 0; - fid = tc->params.tclunk.fid; - if (rc) - id = rc->id; - - kfree(tc); - kfree(rc); - if (id == RCLUNK) { - v9ses = a; - v9fs_put_idpool(fid, &v9ses->fidpool); - } -} - -/** - * v9fs_t_clunk - release a fid (finish a transaction) - * @v9ses: 9P2000 session information - * @fid: fid to release - * @fcall: pointer to response fcall pointer - * - */ - -int -v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) -{ - int ret; - struct v9fs_fcall *tc, *rc; - - dprintk(DEBUG_9P, "fid %d\n", fid); - - rc = NULL; - tc = v9fs_create_tclunk(fid); - if (!IS_ERR(tc)) - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); - else - ret = PTR_ERR(tc); - - if (ret) - dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret); - - v9fs_t_clunk_cb(v9ses, tc, rc, ret); - return ret; -} - -#if 0 -/** - * v9fs_v9fs_t_flush - flush a pending transaction - * @v9ses: 9P2000 session information - * @tag: tag to release - * - */ -int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "oldtag %d\n", oldtag); - - tc = v9fs_create_tflush(oldtag); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, NULL); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} -#endif - -/** - * v9fs_t_stat - read a file's meta-data - * @v9ses: 9P2000 session information - * @fid: fid pointing to file or directory to get info about - * @fcall: pointer to response fcall - * - */ - -int -v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "fid %d\n", fid); - - ret = -ENOMEM; - tc = v9fs_create_tstat(fid); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_wstat - write a file's meta-data - * @v9ses: 9P2000 session information - * @fid: fid pointing to file or directory to write info about - * @stat: metadata - * @fcall: pointer to response fcall - * - */ - -int -v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, - struct v9fs_wstat *wstat, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "fid %d\n", fid); - - tc = v9fs_create_twstat(fid, wstat, v9ses->extended); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_walk - walk a fid to a new file or directory - * @v9ses: 9P2000 session information - * @fid: fid to walk - * @newfid: new fid (for clone operations) - * @name: path to walk fid to - * @fcall: pointer to response fcall - * - */ - -/* TODO: support multiple walk */ - -int -v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, - char *name, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - int nwname; - - dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name); - - if (name) - nwname = 1; - else - nwname = 0; - - tc = v9fs_create_twalk(fid, newfid, nwname, &name); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_open - open a file - * - * @v9ses - 9P2000 session information - * @fid - fid to open - * @mode - mode to open file (R, RW, etc) - * @fcall - pointer to response fcall - * - */ - -int -v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, - struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode); - - tc = v9fs_create_topen(fid, mode); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_remove - remove a file or directory - * @v9ses: 9P2000 session information - * @fid: fid to remove - * @fcall: pointer to response fcall - * - */ - -int -v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, - struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "fid %d\n", fid); - - tc = v9fs_create_tremove(fid); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_create - create a file or directory - * @v9ses: 9P2000 session information - * @fid: fid to create - * @name: name of the file or directory to create - * @perm: permissions to create with - * @mode: mode to open file (R, RW, etc) - * @fcall: pointer to response fcall - * - */ - -int -v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm, - u8 mode, char *extension, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc; - - dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n", - fid, name, perm, mode); - - tc = v9fs_create_tcreate(fid, name, perm, mode, extension, - v9ses->extended); - - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_read - read data - * @v9ses: 9P2000 session information - * @fid: fid to read from - * @offset: offset to start read at - * @count: how many bytes to read - * @fcall: pointer to response fcall (with data) - * - */ - -int -v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, - u32 count, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc, *rc; - - dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, - (long long unsigned) offset, count); - - tc = v9fs_create_tread(fid, offset, count); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); - if (!ret) - ret = rc->params.rread.count; - if (rcp) - *rcp = rc; - else - kfree(rc); - - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - -/** - * v9fs_t_write - write data - * @v9ses: 9P2000 session information - * @fid: fid to write to - * @offset: offset to start write at - * @count: how many bytes to write - * @fcall: pointer to response fcall - * - */ - -int -v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count, - const char __user *data, struct v9fs_fcall **rcp) -{ - int ret; - struct v9fs_fcall *tc, *rc; - - dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, - (long long unsigned) offset, count); - - tc = v9fs_create_twrite(fid, offset, count, data); - if (!IS_ERR(tc)) { - ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); - - if (!ret) - ret = rc->params.rwrite.count; - if (rcp) - *rcp = rc; - else - kfree(rc); - - kfree(tc); - } else - ret = PTR_ERR(tc); - - return ret; -} - diff --git a/fs/9p/fcprint.c b/fs/9p/fcprint.c deleted file mode 100644 index 34b96114a28d..000000000000 --- a/fs/9p/fcprint.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * linux/fs/9p/fcprint.c - * - * Print 9P call. - * - * Copyright (C) 2005 by Latchesar Ionkov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#include -#include -#include -#include - -#include "debug.h" -#include "v9fs.h" -#include "9p.h" -#include "mux.h" - -static int -v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q) -{ - int n; - char b[10]; - - n = 0; - if (q->type & V9FS_QTDIR) - b[n++] = 'd'; - if (q->type & V9FS_QTAPPEND) - b[n++] = 'a'; - if (q->type & V9FS_QTAUTH) - b[n++] = 'A'; - if (q->type & V9FS_QTEXCL) - b[n++] = 'l'; - if (q->type & V9FS_QTTMP) - b[n++] = 't'; - if (q->type & V9FS_QTSYMLINK) - b[n++] = 'L'; - b[n] = '\0'; - - return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path, - q->version, b); -} - -static int -v9fs_printperm(char *buf, int buflen, int perm) -{ - int n; - char b[15]; - - n = 0; - if (perm & V9FS_DMDIR) - b[n++] = 'd'; - if (perm & V9FS_DMAPPEND) - b[n++] = 'a'; - if (perm & V9FS_DMAUTH) - b[n++] = 'A'; - if (perm & V9FS_DMEXCL) - b[n++] = 'l'; - if (perm & V9FS_DMTMP) - b[n++] = 't'; - if (perm & V9FS_DMDEVICE) - b[n++] = 'D'; - if (perm & V9FS_DMSOCKET) - b[n++] = 'S'; - if (perm & V9FS_DMNAMEDPIPE) - b[n++] = 'P'; - if (perm & V9FS_DMSYMLINK) - b[n++] = 'L'; - b[n] = '\0'; - - return scnprintf(buf, buflen, "%s%03o", b, perm&077); -} - -static int -v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended) -{ - int n; - - n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len, - st->name.str, st->uid.len, st->uid.str); - if (extended) - n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid); - - n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str); - if (extended) - n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid); - - n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str); - if (extended) - n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); - - n += scnprintf(buf+n, buflen-n, " q "); - n += v9fs_printqid(buf+n, buflen-n, &st->qid); - n += scnprintf(buf+n, buflen-n, " m "); - n += v9fs_printperm(buf+n, buflen-n, st->mode); - n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", - st->atime, st->mtime, (long long int) st->length); - - if (extended) - n += scnprintf(buf+n, buflen-n, " ext '%.*s'", - st->extension.len, st->extension.str); - - return n; -} - -static int -v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen) -{ - int i, n; - - i = n = 0; - while (i < datalen) { - n += scnprintf(buf + n, buflen - n, "%02x", data[i]); - if (i%4 == 3) - n += scnprintf(buf + n, buflen - n, " "); - if (i%32 == 31) - n += scnprintf(buf + n, buflen - n, "\n"); - - i++; - } - n += scnprintf(buf + n, buflen - n, "\n"); - - return n; -} - -static int -v9fs_printdata(char *buf, int buflen, u8 *data, int datalen) -{ - return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16); -} - -int -v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended) -{ - int i, ret, type, tag; - - if (!fc) - return scnprintf(buf, buflen, ""); - - type = fc->id; - tag = fc->tag; - - ret = 0; - switch (type) { - case TVERSION: - ret += scnprintf(buf+ret, buflen-ret, - "Tversion tag %u msize %u version '%.*s'", tag, - fc->params.tversion.msize, fc->params.tversion.version.len, - fc->params.tversion.version.str); - break; - - case RVERSION: - ret += scnprintf(buf+ret, buflen-ret, - "Rversion tag %u msize %u version '%.*s'", tag, - fc->params.rversion.msize, fc->params.rversion.version.len, - fc->params.rversion.version.str); - break; - - case TAUTH: - ret += scnprintf(buf+ret, buflen-ret, - "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, - fc->params.tauth.afid, fc->params.tauth.uname.len, - fc->params.tauth.uname.str, fc->params.tauth.aname.len, - fc->params.tauth.aname.str); - break; - - case RAUTH: - ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); - v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); - break; - - case TATTACH: - ret += scnprintf(buf+ret, buflen-ret, - "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", - tag, fc->params.tattach.fid, fc->params.tattach.afid, - fc->params.tattach.uname.len, fc->params.tattach.uname.str, - fc->params.tattach.aname.len, fc->params.tattach.aname.str); - break; - - case RATTACH: - ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag); - v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); - break; - - case RERROR: - ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'", - tag, fc->params.rerror.error.len, - fc->params.rerror.error.str); - if (extended) - ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", - fc->params.rerror.errno); - break; - - case TFLUSH: - ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", - tag, fc->params.tflush.oldtag); - break; - - case RFLUSH: - ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); - break; - - case TWALK: - ret += scnprintf(buf+ret, buflen-ret, - "Twalk tag %u fid %d newfid %d nwname %d", tag, - fc->params.twalk.fid, fc->params.twalk.newfid, - fc->params.twalk.nwname); - for(i = 0; i < fc->params.twalk.nwname; i++) - ret += scnprintf(buf+ret, buflen-ret," '%.*s'", - fc->params.twalk.wnames[i].len, - fc->params.twalk.wnames[i].str); - break; - - case RWALK: - ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", - tag, fc->params.rwalk.nwqid); - for(i = 0; i < fc->params.rwalk.nwqid; i++) - ret += v9fs_printqid(buf+ret, buflen-ret, - &fc->params.rwalk.wqids[i]); - break; - - case TOPEN: - ret += scnprintf(buf+ret, buflen-ret, - "Topen tag %u fid %d mode %d", tag, - fc->params.topen.fid, fc->params.topen.mode); - break; - - case ROPEN: - ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); - ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); - ret += scnprintf(buf+ret, buflen-ret," iounit %d", - fc->params.ropen.iounit); - break; - - case TCREATE: - ret += scnprintf(buf+ret, buflen-ret, - "Tcreate tag %u fid %d name '%.*s' perm ", tag, - fc->params.tcreate.fid, fc->params.tcreate.name.len, - fc->params.tcreate.name.str); - - ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm); - ret += scnprintf(buf+ret, buflen-ret, " mode %d", - fc->params.tcreate.mode); - break; - - case RCREATE: - ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); - ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid); - ret += scnprintf(buf+ret, buflen-ret, " iounit %d", - fc->params.rcreate.iounit); - break; - - case TREAD: - ret += scnprintf(buf+ret, buflen-ret, - "Tread tag %u fid %d offset %lld count %u", tag, - fc->params.tread.fid, - (long long int) fc->params.tread.offset, - fc->params.tread.count); - break; - - case RREAD: - ret += scnprintf(buf+ret, buflen-ret, - "Rread tag %u count %u data ", tag, - fc->params.rread.count); - ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data, - fc->params.rread.count); - break; - - case TWRITE: - ret += scnprintf(buf+ret, buflen-ret, - "Twrite tag %u fid %d offset %lld count %u data ", - tag, fc->params.twrite.fid, - (long long int) fc->params.twrite.offset, - fc->params.twrite.count); - ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data, - fc->params.twrite.count); - break; - - case RWRITE: - ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", - tag, fc->params.rwrite.count); - break; - - case TCLUNK: - ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", - tag, fc->params.tclunk.fid); - break; - - case RCLUNK: - ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); - break; - - case TREMOVE: - ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", - tag, fc->params.tremove.fid); - break; - - case RREMOVE: - ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); - break; - - case TSTAT: - ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", - tag, fc->params.tstat.fid); - break; - - case RSTAT: - ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); - ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, - extended); - break; - - case TWSTAT: - ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", - tag, fc->params.twstat.fid); - ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat, - extended); - break; - - case RWSTAT: - ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); - break; - - default: - ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type); - break; - } - - return ret; -} diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 90419715c7e9..08fa320b7e6d 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -26,10 +26,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -40,67 +40,29 @@ * */ -int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) +int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) { - struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; - dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, - dentry->d_iname, dentry); - if (dentry->d_fsdata == NULL) { - dentry->d_fsdata = - kmalloc(sizeof(struct list_head), GFP_KERNEL); - if (dentry->d_fsdata == NULL) { - dprintk(DEBUG_ERROR, "Out of memory\n"); - return -ENOMEM; - } - fid_list = (struct list_head *)dentry->d_fsdata; - INIT_LIST_HEAD(fid_list); /* Initialize list head */ - } + struct v9fs_dentry *dent; - fid->uid = current->uid; - list_add(&fid->list, fid_list); - return 0; -} + P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n", + fid->fid, dentry->d_iname); -/** - * v9fs_fid_create - allocate a FID structure - * @dentry - dentry to link newly created fid to - * - */ - -struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) -{ - struct v9fs_fid *new; + dent = dentry->d_fsdata; + if (!dent) { + dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL); + if (!dent) + return -ENOMEM; - dprintk(DEBUG_9P, "fid create fid %d\n", fid); - new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); - if (new == NULL) { - dprintk(DEBUG_ERROR, "Out of Memory\n"); - return ERR_PTR(-ENOMEM); + spin_lock_init(&dent->lock); + INIT_LIST_HEAD(&dent->fidlist); + dentry->d_fsdata = dent; } - new->fid = fid; - new->v9ses = v9ses; - new->fidopen = 0; - new->fidclunked = 0; - new->iounit = 0; - new->rdir_pos = 0; - new->rdir_fcall = NULL; - init_MUTEX(&new->lock); - INIT_LIST_HEAD(&new->list); - - return new; -} - -/** - * v9fs_fid_destroy - deallocate a FID structure - * @fid: fid to destroy - * - */ + spin_lock(&dent->lock); + list_add(&fid->dlist, &dent->fidlist); + spin_unlock(&dent->lock); -void v9fs_fid_destroy(struct v9fs_fid *fid) -{ - list_del(&fid->list); - kfree(fid); + return 0; } /** @@ -114,30 +76,42 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) * */ -struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) +struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) { - struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; - struct v9fs_fid *return_fid = NULL; - - dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); - - if (fid_list) - return_fid = list_entry(fid_list->next, struct v9fs_fid, list); + struct v9fs_dentry *dent; + struct p9_fid *fid; + + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + dent = dentry->d_fsdata; + if (dent) + fid = list_entry(dent->fidlist.next, struct p9_fid, dlist); + else + fid = ERR_PTR(-EBADF); + + P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid); + return fid; +} - if (!return_fid) { - dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); - return_fid = ERR_PTR(-EBADF); +struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry) +{ + struct p9_fid *fid; + struct v9fs_dentry *dent; + + dent = dentry->d_fsdata; + fid = v9fs_fid_lookup(dentry); + if (!IS_ERR(fid)) { + spin_lock(&dent->lock); + list_del(&fid->dlist); + spin_unlock(&dent->lock); } - if(down_interruptible(&return_fid->lock)) - return ERR_PTR(-EINTR); - - return return_fid; + return fid; } + /** * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and - * release it + * release it * @dentry: dentry to look for fid in * * find a fid in the dentry and then clone to a new private fid @@ -146,49 +120,15 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) * */ -struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry) +struct p9_fid *v9fs_fid_clone(struct dentry *dentry) { - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF); - struct v9fs_fcall *fcall = NULL; - int fid, err; - - base_fid = v9fs_fid_lookup(dentry); - - if(IS_ERR(base_fid)) - return base_fid; - - if(base_fid) { /* clone fid */ - fid = v9fs_get_idpool(&v9ses->fidpool); - if (fid < 0) { - eprintk(KERN_WARNING, "newfid fails!\n"); - new_fid = ERR_PTR(-ENOSPC); - goto Release_Fid; - } - - err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall); - if (err < 0) { - dprintk(DEBUG_ERROR, "clone walk didn't work\n"); - v9fs_put_idpool(fid, &v9ses->fidpool); - new_fid = ERR_PTR(err); - goto Free_Fcall; - } - new_fid = v9fs_fid_create(v9ses, fid); - if (new_fid == NULL) { - dprintk(DEBUG_ERROR, "out of memory\n"); - new_fid = ERR_PTR(-ENOMEM); - } -Free_Fcall: - kfree(fcall); - } + struct p9_fid *ofid, *fid; -Release_Fid: - up(&base_fid->lock); - return new_fid; -} + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + ofid = v9fs_fid_lookup(dentry); + if (IS_ERR(ofid)) + return ofid; -void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid) -{ - v9fs_t_clunk(v9ses, fid->fid); - v9fs_fid_destroy(fid); + fid = p9_client_walk(ofid, 0, NULL, 1); + return fid; } diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 48fc170c26c8..47a0ba742872 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h @@ -22,41 +22,12 @@ #include -#define FID_OP 0 -#define FID_WALK 1 -#define FID_CREATE 2 - -struct v9fs_fid { - struct list_head list; /* list of fids associated with a dentry */ - struct list_head active; /* XXX - debug */ - - struct semaphore lock; - - u32 fid; - unsigned char fidopen; /* set when fid is opened */ - unsigned char fidclunked; /* set when fid has already been clunked */ - - struct v9fs_qid qid; - u32 iounit; - - /* readdir stuff */ - int rdir_fpos; - loff_t rdir_pos; - struct v9fs_fcall *rdir_fcall; - - /* management stuff */ - uid_t uid; /* user associated with this fid */ - - /* private data */ - struct file *filp; /* backpointer to File struct for open files */ - struct v9fs_session_info *v9ses; /* session info for this FID */ +struct v9fs_dentry { + spinlock_t lock; /* protect fidlist */ + struct list_head fidlist; }; -struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); -struct v9fs_fid *v9fs_fid_get_created(struct dentry *); -void v9fs_fid_destroy(struct v9fs_fid *fid); -struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); -int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); -struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry); -void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid); - +struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); +struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry); +struct p9_fid *v9fs_fid_clone(struct dentry *dentry); +int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); diff --git a/fs/9p/mux.c b/fs/9p/mux.c deleted file mode 100644 index c783874a9caf..000000000000 --- a/fs/9p/mux.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* - * linux/fs/9p/mux.c - * - * Protocol Multiplexer - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2004-2005 by Latchesar Ionkov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "v9fs.h" -#include "9p.h" -#include "conv.h" -#include "transport.h" -#include "mux.h" - -#define ERREQFLUSH 1 -#define SCHED_TIMEOUT 10 -#define MAXPOLLWADDR 2 - -enum { - Rworksched = 1, /* read work scheduled or running */ - Rpending = 2, /* can read */ - Wworksched = 4, /* write work scheduled or running */ - Wpending = 8, /* can write */ -}; - -enum { - None, - Flushing, - Flushed, -}; - -struct v9fs_mux_poll_task; - -struct v9fs_req { - spinlock_t lock; - int tag; - struct v9fs_fcall *tcall; - struct v9fs_fcall *rcall; - int err; - v9fs_mux_req_callback cb; - void *cba; - int flush; - struct list_head req_list; -}; - -struct v9fs_mux_data { - spinlock_t lock; - struct list_head mux_list; - struct v9fs_mux_poll_task *poll_task; - int msize; - unsigned char *extended; - struct v9fs_transport *trans; - struct v9fs_idpool tagpool; - int err; - wait_queue_head_t equeue; - struct list_head req_list; - struct list_head unsent_req_list; - struct v9fs_fcall *rcall; - int rpos; - char *rbuf; - int wpos; - int wsize; - char *wbuf; - wait_queue_t poll_wait[MAXPOLLWADDR]; - wait_queue_head_t *poll_waddr[MAXPOLLWADDR]; - poll_table pt; - struct work_struct rq; - struct work_struct wq; - unsigned long wsched; -}; - -struct v9fs_mux_poll_task { - struct task_struct *task; - struct list_head mux_list; - int muxnum; -}; - -struct v9fs_mux_rpc { - struct v9fs_mux_data *m; - int err; - struct v9fs_fcall *tcall; - struct v9fs_fcall *rcall; - wait_queue_head_t wqueue; -}; - -static int v9fs_poll_proc(void *); -static void v9fs_read_work(struct work_struct *work); -static void v9fs_write_work(struct work_struct *work); -static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, - poll_table * p); -static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); -static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16); - -static DEFINE_MUTEX(v9fs_mux_task_lock); -static struct workqueue_struct *v9fs_mux_wq; - -static int v9fs_mux_num; -static int v9fs_mux_poll_task_num; -static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100]; - -int v9fs_mux_global_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) - v9fs_mux_poll_tasks[i].task = NULL; - - v9fs_mux_wq = create_workqueue("v9fs"); - if (!v9fs_mux_wq) { - printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); - return -ENOMEM; - } - - return 0; -} - -void v9fs_mux_global_exit(void) -{ - destroy_workqueue(v9fs_mux_wq); -} - -/** - * v9fs_mux_calc_poll_procs - calculates the number of polling procs - * based on the number of mounted v9fs filesystems. - * - * The current implementation returns sqrt of the number of mounts. - */ -static int v9fs_mux_calc_poll_procs(int muxnum) -{ - int n; - - if (v9fs_mux_poll_task_num) - n = muxnum / v9fs_mux_poll_task_num + - (muxnum % v9fs_mux_poll_task_num ? 1 : 0); - else - n = 1; - - if (n > ARRAY_SIZE(v9fs_mux_poll_tasks)) - n = ARRAY_SIZE(v9fs_mux_poll_tasks); - - return n; -} - -static int v9fs_mux_poll_start(struct v9fs_mux_data *m) -{ - int i, n; - struct v9fs_mux_poll_task *vpt, *vptlast; - struct task_struct *pproc; - - dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num, - v9fs_mux_poll_task_num); - mutex_lock(&v9fs_mux_task_lock); - - n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1); - if (n > v9fs_mux_poll_task_num) { - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { - if (v9fs_mux_poll_tasks[i].task == NULL) { - vpt = &v9fs_mux_poll_tasks[i]; - dprintk(DEBUG_MUX, "create proc %p\n", vpt); - pproc = kthread_create(v9fs_poll_proc, vpt, - "v9fs-poll"); - - if (!IS_ERR(pproc)) { - vpt->task = pproc; - INIT_LIST_HEAD(&vpt->mux_list); - vpt->muxnum = 0; - v9fs_mux_poll_task_num++; - wake_up_process(vpt->task); - } - break; - } - } - - if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) - dprintk(DEBUG_ERROR, "warning: no free poll slots\n"); - } - - n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num + - ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0); - - vptlast = NULL; - for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { - vpt = &v9fs_mux_poll_tasks[i]; - if (vpt->task != NULL) { - vptlast = vpt; - if (vpt->muxnum < n) { - dprintk(DEBUG_MUX, "put in proc %d\n", i); - list_add(&m->mux_list, &vpt->mux_list); - vpt->muxnum++; - m->poll_task = vpt; - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); - init_poll_funcptr(&m->pt, v9fs_pollwait); - break; - } - } - } - - if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) { - if (vptlast == NULL) - return -ENOMEM; - - dprintk(DEBUG_MUX, "put in proc %d\n", i); - list_add(&m->mux_list, &vptlast->mux_list); - vptlast->muxnum++; - m->poll_task = vptlast; - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); - init_poll_funcptr(&m->pt, v9fs_pollwait); - } - - v9fs_mux_num++; - mutex_unlock(&v9fs_mux_task_lock); - - return 0; -} - -static void v9fs_mux_poll_stop(struct v9fs_mux_data *m) -{ - int i; - struct v9fs_mux_poll_task *vpt; - - mutex_lock(&v9fs_mux_task_lock); - vpt = m->poll_task; - list_del(&m->mux_list); - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { - if (m->poll_waddr[i] != NULL) { - remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); - m->poll_waddr[i] = NULL; - } - } - vpt->muxnum--; - if (!vpt->muxnum) { - dprintk(DEBUG_MUX, "destroy proc %p\n", vpt); - kthread_stop(vpt->task); - vpt->task = NULL; - v9fs_mux_poll_task_num--; - } - v9fs_mux_num--; - mutex_unlock(&v9fs_mux_task_lock); -} - -/** - * v9fs_mux_init - allocate and initialize the per-session mux data - * Creates the polling task if this is the first session. - * - * @trans - transport structure - * @msize - maximum message size - * @extended - pointer to the extended flag - */ -struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, - unsigned char *extended) -{ - int i, n; - struct v9fs_mux_data *m, *mtmp; - - dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize); - m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL); - if (!m) - return ERR_PTR(-ENOMEM); - - spin_lock_init(&m->lock); - INIT_LIST_HEAD(&m->mux_list); - m->msize = msize; - m->extended = extended; - m->trans = trans; - idr_init(&m->tagpool.pool); - init_MUTEX(&m->tagpool.lock); - m->err = 0; - init_waitqueue_head(&m->equeue); - INIT_LIST_HEAD(&m->req_list); - INIT_LIST_HEAD(&m->unsent_req_list); - m->rcall = NULL; - m->rpos = 0; - m->rbuf = NULL; - m->wpos = m->wsize = 0; - m->wbuf = NULL; - INIT_WORK(&m->rq, v9fs_read_work); - INIT_WORK(&m->wq, v9fs_write_work); - m->wsched = 0; - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); - m->poll_task = NULL; - n = v9fs_mux_poll_start(m); - if (n) - return ERR_PTR(n); - - n = trans->poll(trans, &m->pt); - if (n & POLLIN) { - dprintk(DEBUG_MUX, "mux %p can read\n", m); - set_bit(Rpending, &m->wsched); - } - - if (n & POLLOUT) { - dprintk(DEBUG_MUX, "mux %p can write\n", m); - set_bit(Wpending, &m->wsched); - } - - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { - if (IS_ERR(m->poll_waddr[i])) { - v9fs_mux_poll_stop(m); - mtmp = (void *)m->poll_waddr; /* the error code */ - kfree(m); - m = mtmp; - break; - } - } - - return m; -} - -/** - * v9fs_mux_destroy - cancels all pending requests and frees mux resources - */ -void v9fs_mux_destroy(struct v9fs_mux_data *m) -{ - dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m, - m->mux_list.prev, m->mux_list.next); - v9fs_mux_cancel(m, -ECONNRESET); - - if (!list_empty(&m->req_list)) { - /* wait until all processes waiting on this session exit */ - dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n", - m); - wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); - dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m, - list_empty(&m->req_list)); - } - - v9fs_mux_poll_stop(m); - m->trans = NULL; - - kfree(m); -} - -/** - * v9fs_pollwait - called by files poll operation to add v9fs-poll task - * to files wait queue - */ -static void -v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, - poll_table * p) -{ - int i; - struct v9fs_mux_data *m; - - m = container_of(p, struct v9fs_mux_data, pt); - for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) - if (m->poll_waddr[i] == NULL) - break; - - if (i >= ARRAY_SIZE(m->poll_waddr)) { - dprintk(DEBUG_ERROR, "not enough wait_address slots\n"); - return; - } - - m->poll_waddr[i] = wait_address; - - if (!wait_address) { - dprintk(DEBUG_ERROR, "no wait_address\n"); - m->poll_waddr[i] = ERR_PTR(-EIO); - return; - } - - init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task); - add_wait_queue(wait_address, &m->poll_wait[i]); -} - -/** - * v9fs_poll_mux - polls a mux and schedules read or write works if necessary - */ -static void v9fs_poll_mux(struct v9fs_mux_data *m) -{ - int n; - - if (m->err < 0) - return; - - n = m->trans->poll(m->trans, NULL); - if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { - dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n); - if (n >= 0) - n = -ECONNRESET; - v9fs_mux_cancel(m, n); - } - - if (n & POLLIN) { - set_bit(Rpending, &m->wsched); - dprintk(DEBUG_MUX, "mux %p can read\n", m); - if (!test_and_set_bit(Rworksched, &m->wsched)) { - dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); - queue_work(v9fs_mux_wq, &m->rq); - } - } - - if (n & POLLOUT) { - set_bit(Wpending, &m->wsched); - dprintk(DEBUG_MUX, "mux %p can write\n", m); - if ((m->wsize || !list_empty(&m->unsent_req_list)) - && !test_and_set_bit(Wworksched, &m->wsched)) { - dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); - queue_work(v9fs_mux_wq, &m->wq); - } - } -} - -/** - * v9fs_poll_proc - polls all v9fs transports for new events and queues - * the appropriate work to the work queue - */ -static int v9fs_poll_proc(void *a) -{ - struct v9fs_mux_data *m, *mtmp; - struct v9fs_mux_poll_task *vpt; - - vpt = a; - dprintk(DEBUG_MUX, "start %p %p\n", current, vpt); - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - - list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { - v9fs_poll_mux(m); - } - - dprintk(DEBUG_MUX, "sleeping...\n"); - schedule_timeout(SCHED_TIMEOUT * HZ); - } - - __set_current_state(TASK_RUNNING); - dprintk(DEBUG_MUX, "finish\n"); - return 0; -} - -/** - * v9fs_write_work - called when a transport can send some data - */ -static void v9fs_write_work(struct work_struct *work) -{ - int n, err; - struct v9fs_mux_data *m; - struct v9fs_req *req; - - m = container_of(work, struct v9fs_mux_data, wq); - - if (m->err < 0) { - clear_bit(Wworksched, &m->wsched); - return; - } - - if (!m->wsize) { - if (list_empty(&m->unsent_req_list)) { - clear_bit(Wworksched, &m->wsched); - return; - } - - spin_lock(&m->lock); -again: - req = list_entry(m->unsent_req_list.next, struct v9fs_req, - req_list); - list_move_tail(&req->req_list, &m->req_list); - if (req->err == ERREQFLUSH) - goto again; - - m->wbuf = req->tcall->sdata; - m->wsize = req->tcall->size; - m->wpos = 0; - dump_data(m->wbuf, m->wsize); - spin_unlock(&m->lock); - } - - dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize); - clear_bit(Wpending, &m->wsched); - err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); - dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err); - if (err == -EAGAIN) { - clear_bit(Wworksched, &m->wsched); - return; - } - - if (err <= 0) - goto error; - - m->wpos += err; - if (m->wpos == m->wsize) - m->wpos = m->wsize = 0; - - if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) { - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = m->trans->poll(m->trans, NULL); - - if (n & POLLOUT) { - dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); - queue_work(v9fs_mux_wq, &m->wq); - } else - clear_bit(Wworksched, &m->wsched); - } else - clear_bit(Wworksched, &m->wsched); - - return; - - error: - v9fs_mux_cancel(m, err); - clear_bit(Wworksched, &m->wsched); -} - -static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) -{ - int ecode; - struct v9fs_str *ename; - - if (!req->err && req->rcall->id == RERROR) { - ecode = req->rcall->params.rerror.errno; - ename = &req->rcall->params.rerror.error; - - dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str); - - if (*m->extended) - req->err = -ecode; - - if (!req->err) { - req->err = v9fs_errstr2errno(ename->str, ename->len); - - if (!req->err) { /* string match failed */ - PRINT_FCALL_ERROR("unknown error", req->rcall); - } - - if (!req->err) - req->err = -ESERVERFAULT; - } - } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { - dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n", - req->tcall->id + 1, req->rcall->id); - if (!req->err) - req->err = -EIO; - } -} - -/** - * v9fs_read_work - called when there is some data to be read from a transport - */ -static void v9fs_read_work(struct work_struct *work) -{ - int n, err; - struct v9fs_mux_data *m; - struct v9fs_req *req, *rptr, *rreq; - struct v9fs_fcall *rcall; - char *rbuf; - - m = container_of(work, struct v9fs_mux_data, rq); - - if (m->err < 0) - return; - - rcall = NULL; - dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); - - if (!m->rcall) { - m->rcall = - kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL); - if (!m->rcall) { - err = -ENOMEM; - goto error; - } - - m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); - m->rpos = 0; - } - - clear_bit(Rpending, &m->wsched); - err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); - dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err); - if (err == -EAGAIN) { - clear_bit(Rworksched, &m->wsched); - return; - } - - if (err <= 0) - goto error; - - m->rpos += err; - while (m->rpos > 4) { - n = le32_to_cpu(*(__le32 *) m->rbuf); - if (n >= m->msize) { - dprintk(DEBUG_ERROR, - "requested packet size too big: %d\n", n); - err = -EIO; - goto error; - } - - if (m->rpos < n) - break; - - dump_data(m->rbuf, n); - err = - v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); - if (err < 0) { - goto error; - } - - if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { - char buf[150]; - - v9fs_printfcall(buf, sizeof(buf), m->rcall, - *m->extended); - printk(KERN_NOTICE ">>> %p %s\n", m, buf); - } - - rcall = m->rcall; - rbuf = m->rbuf; - if (m->rpos > n) { - m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize, - GFP_KERNEL); - if (!m->rcall) { - err = -ENOMEM; - goto error; - } - - m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); - memmove(m->rbuf, rbuf + n, m->rpos - n); - m->rpos -= n; - } else { - m->rcall = NULL; - m->rbuf = NULL; - m->rpos = 0; - } - - dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id, - rcall->tag); - - req = NULL; - spin_lock(&m->lock); - list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { - if (rreq->tag == rcall->tag) { - req = rreq; - if (req->flush != Flushing) - list_del(&req->req_list); - break; - } - } - spin_unlock(&m->lock); - - if (req) { - req->rcall = rcall; - process_request(m, req); - - if (req->flush != Flushing) { - if (req->cb) - (*req->cb) (req, req->cba); - else - kfree(req->rcall); - - wake_up(&m->equeue); - } - } else { - if (err >= 0 && rcall->id != RFLUSH) - dprintk(DEBUG_ERROR, - "unexpected response mux %p id %d tag %d\n", - m, rcall->id, rcall->tag); - kfree(rcall); - } - } - - if (!list_empty(&m->req_list)) { - if (test_and_clear_bit(Rpending, &m->wsched)) - n = POLLIN; - else - n = m->trans->poll(m->trans, NULL); - - if (n & POLLIN) { - dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); - queue_work(v9fs_mux_wq, &m->rq); - } else - clear_bit(Rworksched, &m->wsched); - } else - clear_bit(Rworksched, &m->wsched); - - return; - - error: - v9fs_mux_cancel(m, err); - clear_bit(Rworksched, &m->wsched); -} - -/** - * v9fs_send_request - send 9P request - * The function can sleep until the request is scheduled for sending. - * The function can be interrupted. Return from the function is not - * a guarantee that the request is sent successfully. Can return errors - * that can be retrieved by PTR_ERR macros. - * - * @m: mux data - * @tc: request to be sent - * @cb: callback function to call when response is received - * @cba: parameter to pass to the callback function - */ -static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m, - struct v9fs_fcall *tc, - v9fs_mux_req_callback cb, void *cba) -{ - int n; - struct v9fs_req *req; - - dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, - tc, tc->id); - if (m->err < 0) - return ERR_PTR(m->err); - - req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL); - if (!req) - return ERR_PTR(-ENOMEM); - - if (tc->id == TVERSION) - n = V9FS_NOTAG; - else - n = v9fs_mux_get_tag(m); - - if (n < 0) - return ERR_PTR(-ENOMEM); - - v9fs_set_tag(tc, n); - if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { - char buf[150]; - - v9fs_printfcall(buf, sizeof(buf), tc, *m->extended); - printk(KERN_NOTICE "<<< %p %s\n", m, buf); - } - - spin_lock_init(&req->lock); - req->tag = n; - req->tcall = tc; - req->rcall = NULL; - req->err = 0; - req->cb = cb; - req->cba = cba; - req->flush = None; - - spin_lock(&m->lock); - list_add_tail(&req->req_list, &m->unsent_req_list); - spin_unlock(&m->lock); - - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = m->trans->poll(m->trans, NULL); - - if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) - queue_work(v9fs_mux_wq, &m->wq); - - return req; -} - -static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req) -{ - v9fs_mux_put_tag(m, req->tag); - kfree(req); -} - -static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a) -{ - v9fs_mux_req_callback cb; - int tag; - struct v9fs_mux_data *m; - struct v9fs_req *req, *rreq, *rptr; - - m = a; - dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, - freq->tcall, freq->rcall, freq->err, - freq->tcall->params.tflush.oldtag); - - spin_lock(&m->lock); - cb = NULL; - tag = freq->tcall->params.tflush.oldtag; - req = NULL; - list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { - if (rreq->tag == tag) { - req = rreq; - list_del(&req->req_list); - break; - } - } - spin_unlock(&m->lock); - - if (req) { - spin_lock(&req->lock); - req->flush = Flushed; - spin_unlock(&req->lock); - - if (req->cb) - (*req->cb) (req, req->cba); - else - kfree(req->rcall); - - wake_up(&m->equeue); - } - - kfree(freq->tcall); - kfree(freq->rcall); - v9fs_mux_free_request(m, freq); -} - -static int -v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req) -{ - struct v9fs_fcall *fc; - struct v9fs_req *rreq, *rptr; - - dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); - - /* if a response was received for a request, do nothing */ - spin_lock(&req->lock); - if (req->rcall || req->err) { - spin_unlock(&req->lock); - dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req); - return 0; - } - - req->flush = Flushing; - spin_unlock(&req->lock); - - spin_lock(&m->lock); - /* if the request is not sent yet, just remove it from the list */ - list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { - if (rreq->tag == req->tag) { - dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req); - list_del(&rreq->req_list); - req->flush = Flushed; - spin_unlock(&m->lock); - if (req->cb) - (*req->cb) (req, req->cba); - return 0; - } - } - spin_unlock(&m->lock); - - clear_thread_flag(TIF_SIGPENDING); - fc = v9fs_create_tflush(req->tag); - v9fs_send_request(m, fc, v9fs_mux_flush_cb, m); - return 1; -} - -static void -v9fs_mux_rpc_cb(struct v9fs_req *req, void *a) -{ - struct v9fs_mux_rpc *r; - - dprintk(DEBUG_MUX, "req %p r %p\n", req, a); - r = a; - r->rcall = req->rcall; - r->err = req->err; - - if (req->flush!=None && !req->err) - r->err = -ERESTARTSYS; - - wake_up(&r->wqueue); -} - -/** - * v9fs_mux_rpc - sends 9P request and waits until a response is available. - * The function can be interrupted. - * @m: mux data - * @tc: request to be sent - * @rc: pointer where a pointer to the response is stored - */ -int -v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, - struct v9fs_fcall **rc) -{ - int err, sigpending; - unsigned long flags; - struct v9fs_req *req; - struct v9fs_mux_rpc r; - - r.err = 0; - r.tcall = tc; - r.rcall = NULL; - r.m = m; - init_waitqueue_head(&r.wqueue); - - if (rc) - *rc = NULL; - - sigpending = 0; - if (signal_pending(current)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - } - - req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r); - if (IS_ERR(req)) { - err = PTR_ERR(req); - dprintk(DEBUG_MUX, "error %d\n", err); - return err; - } - - err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0); - if (r.err < 0) - err = r.err; - - if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) { - if (v9fs_mux_flush_request(m, req)) { - /* wait until we get response of the flush message */ - do { - clear_thread_flag(TIF_SIGPENDING); - err = wait_event_interruptible(r.wqueue, - r.rcall || r.err); - } while (!r.rcall && !r.err && err==-ERESTARTSYS && - m->trans->status==Connected && !m->err); - - err = -ERESTARTSYS; - } - sigpending = 1; - } - - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - - if (rc) - *rc = r.rcall; - else - kfree(r.rcall); - - v9fs_mux_free_request(m, req); - if (err > 0) - err = -EIO; - - return err; -} - -#if 0 -/** - * v9fs_mux_rpcnb - sends 9P request without waiting for response. - * @m: mux data - * @tc: request to be sent - * @cb: callback function to be called when response arrives - * @cba: value to pass to the callback function - */ -int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc, - v9fs_mux_req_callback cb, void *a) -{ - int err; - struct v9fs_req *req; - - req = v9fs_send_request(m, tc, cb, a); - if (IS_ERR(req)) { - err = PTR_ERR(req); - dprintk(DEBUG_MUX, "error %d\n", err); - return PTR_ERR(req); - } - - dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); - return 0; -} -#endif /* 0 */ - -/** - * v9fs_mux_cancel - cancel all pending requests with error - * @m: mux data - * @err: error code - */ -void v9fs_mux_cancel(struct v9fs_mux_data *m, int err) -{ - struct v9fs_req *req, *rtmp; - LIST_HEAD(cancel_list); - - dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err); - m->err = err; - spin_lock(&m->lock); - list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { - list_move(&req->req_list, &cancel_list); - } - list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { - list_move(&req->req_list, &cancel_list); - } - spin_unlock(&m->lock); - - list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { - list_del(&req->req_list); - if (!req->err) - req->err = err; - - if (req->cb) - (*req->cb) (req, req->cba); - else - kfree(req->rcall); - } - - wake_up(&m->equeue); -} - -static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m) -{ - int tag; - - tag = v9fs_get_idpool(&m->tagpool); - if (tag < 0) - return V9FS_NOTAG; - else - return (u16) tag; -} - -static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag) -{ - if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool)) - v9fs_put_idpool(tag, &m->tagpool); -} diff --git a/fs/9p/mux.h b/fs/9p/mux.h deleted file mode 100644 index fb10c50186a1..000000000000 --- a/fs/9p/mux.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * linux/fs/9p/mux.h - * - * Multiplexer Definitions - * - * Copyright (C) 2005 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -struct v9fs_mux_data; -struct v9fs_req; - -/** - * v9fs_mux_req_callback - callback function that is called when the - * response of a request is received. The callback is called from - * a workqueue and shouldn't block. - * - * @a - the pointer that was specified when the request was send to be - * passed to the callback - * @tc - request call - * @rc - response call - * @err - error code (non-zero if error occured) - */ -typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a); - -int v9fs_mux_global_init(void); -void v9fs_mux_global_exit(void); - -struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, - unsigned char *extended); -void v9fs_mux_destroy(struct v9fs_mux_data *); - -int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc); -struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m); -int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc); - -void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush); -void v9fs_mux_cancel(struct v9fs_mux_data *m, int err); -int v9fs_errstr2errno(char *errstr, int len); diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c deleted file mode 100644 index 34d43355beb7..000000000000 --- a/fs/9p/trans_fd.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * linux/fs/9p/trans_fd.c - * - * Fd transport layer. Includes deprecated socket layer. - * - * Copyright (C) 2006 by Russ Cox - * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2005 by Eric Van Hensbergen - * Copyright (C) 1997-2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "v9fs.h" -#include "transport.h" - -#define V9FS_PORT 564 - -struct v9fs_trans_fd { - struct file *rd; - struct file *wr; -}; - -/** - * v9fs_fd_read- read from a fd - * @v9ses: session information - * @v: buffer to receive data into - * @len: size of receive buffer - * - */ -static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len) -{ - int ret; - struct v9fs_trans_fd *ts; - - if (!trans || trans->status == Disconnected || !(ts = trans->priv)) - return -EREMOTEIO; - - if (!(ts->rd->f_flags & O_NONBLOCK)) - dprintk(DEBUG_ERROR, "blocking read ...\n"); - - ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - trans->status = Disconnected; - return ret; -} - -/** - * v9fs_fd_write - write to a socket - * @v9ses: session information - * @v: buffer to send data from - * @len: size of send buffer - * - */ -static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len) -{ - int ret; - mm_segment_t oldfs; - struct v9fs_trans_fd *ts; - - if (!trans || trans->status == Disconnected || !(ts = trans->priv)) - return -EREMOTEIO; - - if (!(ts->wr->f_flags & O_NONBLOCK)) - dprintk(DEBUG_ERROR, "blocking write ...\n"); - - oldfs = get_fs(); - set_fs(get_ds()); - /* The cast to a user pointer is valid due to the set_fs() */ - ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos); - set_fs(oldfs); - - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - trans->status = Disconnected; - return ret; -} - -static unsigned int -v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt) -{ - int ret, n; - struct v9fs_trans_fd *ts; - mm_segment_t oldfs; - - if (!trans || trans->status != Connected || !(ts = trans->priv)) - return -EREMOTEIO; - - if (!ts->rd->f_op || !ts->rd->f_op->poll) - return -EIO; - - if (!ts->wr->f_op || !ts->wr->f_op->poll) - return -EIO; - - oldfs = get_fs(); - set_fs(get_ds()); - - ret = ts->rd->f_op->poll(ts->rd, pt); - if (ret < 0) - goto end; - - if (ts->rd != ts->wr) { - n = ts->wr->f_op->poll(ts->wr, pt); - if (n < 0) { - ret = n; - goto end; - } - ret = (ret & ~POLLOUT) | (n & ~POLLIN); - } - - end: - set_fs(oldfs); - return ret; -} - -static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd) -{ - struct v9fs_transport *trans = v9ses->transport; - struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd), - GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->rd = fget(rfd); - ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } - - trans->priv = ts; - trans->status = Connected; - - return 0; -} - -static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, - char *data) -{ - if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) { - printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); - return -ENOPROTOOPT; - } - - return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno); -} - -static int v9fs_socket_open(struct v9fs_session_info *v9ses, - struct socket *csocket) -{ - int fd, ret; - - csocket->sk->sk_allocation = GFP_NOIO; - if ((fd = sock_map_fd(csocket)) < 0) { - eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n"); - ret = fd; - release_csocket: - sock_release(csocket); - return ret; - } - - if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) { - sockfd_put(csocket); - eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n"); - goto release_csocket; - } - - ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |= - O_NONBLOCK; - return 0; -} - -static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, - char *data) -{ - int ret; - struct socket *csocket = NULL; - struct sockaddr_in sin_server; - - sin_server.sin_family = AF_INET; - sin_server.sin_addr.s_addr = in_aton(addr); - sin_server.sin_port = htons(v9ses->port); - sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); - - if (!csocket) { - eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n"); - return -1; - } - - ret = csocket->ops->connect(csocket, - (struct sockaddr *)&sin_server, - sizeof(struct sockaddr_in), 0); - if (ret < 0) { - eprintk(KERN_ERR, - "v9fs_trans_tcp: problem connecting socket to %s\n", - addr); - return ret; - } - - return v9fs_socket_open(v9ses, csocket); -} - -static int -v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data) -{ - int ret; - struct socket *csocket; - struct sockaddr_un sun_server; - - if (strlen(addr) > UNIX_PATH_MAX) { - eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n", - addr); - return -ENAMETOOLONG; - } - - sun_server.sun_family = PF_UNIX; - strcpy(sun_server.sun_path, addr); - sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); - ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, - sizeof(struct sockaddr_un) - 1, 0); - if (ret < 0) { - eprintk(KERN_ERR, - "v9fs_trans_unix: problem connecting socket: %s: %d\n", - addr, ret); - return ret; - } - - return v9fs_socket_open(v9ses, csocket); -} - -/** - * v9fs_sock_close - shutdown socket - * @trans: private socket structure - * - */ -static void v9fs_fd_close(struct v9fs_transport *trans) -{ - struct v9fs_trans_fd *ts; - - if (!trans) - return; - - ts = xchg(&trans->priv, NULL); - - if (!ts) - return; - - trans->status = Disconnected; - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); -} - -struct v9fs_transport v9fs_trans_fd = { - .init = v9fs_fd_init, - .write = v9fs_fd_write, - .read = v9fs_fd_read, - .close = v9fs_fd_close, - .poll = v9fs_fd_poll, -}; - -struct v9fs_transport v9fs_trans_tcp = { - .init = v9fs_tcp_init, - .write = v9fs_fd_write, - .read = v9fs_fd_read, - .close = v9fs_fd_close, - .poll = v9fs_fd_poll, -}; - -struct v9fs_transport v9fs_trans_unix = { - .init = v9fs_unix_init, - .write = v9fs_fd_write, - .read = v9fs_fd_read, - .close = v9fs_fd_close, - .poll = v9fs_fd_poll, -}; diff --git a/fs/9p/transport.h b/fs/9p/transport.h deleted file mode 100644 index b38a4b8a41ce..000000000000 --- a/fs/9p/transport.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/fs/9p/transport.h - * - * Transport Definition - * - * Copyright (C) 2005 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -enum v9fs_transport_status { - Connected, - Disconnected, - Hung, -}; - -struct v9fs_transport { - enum v9fs_transport_status status; - void *priv; - - int (*init) (struct v9fs_session_info *, const char *, char *); - int (*write) (struct v9fs_transport *, void *, int); - int (*read) (struct v9fs_transport *, void *, int); - void (*close) (struct v9fs_transport *); - unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *); -}; - -extern struct v9fs_transport v9fs_trans_tcp; -extern struct v9fs_transport v9fs_trans_unix; -extern struct v9fs_transport v9fs_trans_fd; diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 6ad6f192b6e4..4feb5ae63ecf 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -29,16 +29,12 @@ #include #include #include - -#include "debug.h" +#include +#include +#include +#include #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" -#include "transport.h" -#include "mux.h" - -/* TODO: sysfs or debugfs interface */ -int v9fs_debug_level = 0; /* feature-rific global debug level */ /* * Option Parsing (code inspired by NFS code) @@ -47,12 +43,12 @@ int v9fs_debug_level = 0; /* feature-rific global debug level */ enum { /* Options that take integer arguments */ - Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug, + Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_rfdno, Opt_wfdno, /* String options */ Opt_uname, Opt_remotename, /* Options that take no arguments */ - Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, + Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci, /* Cache options */ Opt_cache_loose, /* Error token */ @@ -67,12 +63,14 @@ static match_table_t tokens = { {Opt_afid, "afid=%u"}, {Opt_rfdno, "rfdno=%u"}, {Opt_wfdno, "wfdno=%u"}, - {Opt_debug, "debug=%x"}, {Opt_uname, "uname=%s"}, {Opt_remotename, "aname=%s"}, {Opt_unix, "proto=unix"}, {Opt_tcp, "proto=tcp"}, {Opt_fd, "proto=fd"}, +#ifdef CONFIG_PCI_9P + {Opt_pci, "proto=pci"}, +#endif {Opt_tcp, "tcp"}, {Opt_unix, "unix"}, {Opt_fd, "fd"}, @@ -83,6 +81,8 @@ static match_table_t tokens = { {Opt_err, NULL} }; +extern struct p9_transport *p9pci_trans_create(void); + /* * Parse option string. */ @@ -122,7 +122,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) token = match_token(p, tokens, args); if (token < Opt_uname) { if ((ret = match_int(&args[0], &option)) < 0) { - dprintk(DEBUG_ERROR, + P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); continue; } @@ -149,15 +149,15 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) case Opt_wfdno: v9ses->wfdno = option; break; - case Opt_debug: - v9ses->debug = option; - break; case Opt_tcp: v9ses->proto = PROTO_TCP; break; case Opt_unix: v9ses->proto = PROTO_UNIX; break; + case Opt_pci: + v9ses->proto = PROTO_PCI; + break; case Opt_fd: v9ses->proto = PROTO_FD; break; @@ -182,82 +182,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) } } -/** - * v9fs_inode2v9ses - safely extract v9fs session info from super block - * @inode: inode to extract information from - * - * Paranoid function to extract v9ses information from superblock, - * if anything is missing it will report an error. - * - */ - -struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) -{ - return (inode->i_sb->s_fs_info); -} - -/** - * v9fs_get_idpool - allocate numeric id from pool - * @p - pool to allocate from - * - * XXX - This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -int v9fs_get_idpool(struct v9fs_idpool *p) -{ - int i = 0; - int error; - -retry: - if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) - return 0; - - if (down_interruptible(&p->lock) == -EINTR) { - eprintk(KERN_WARNING, "Interrupted while locking\n"); - return -1; - } - - /* no need to store exactly p, we just need something non-null */ - error = idr_get_new(&p->pool, p, &i); - up(&p->lock); - - if (error == -EAGAIN) - goto retry; - else if (error) - return -1; - - return i; -} - -/** - * v9fs_put_idpool - release numeric id from pool - * @p - pool to allocate from - * - * XXX - This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -void v9fs_put_idpool(int id, struct v9fs_idpool *p) -{ - if (down_interruptible(&p->lock) == -EINTR) { - eprintk(KERN_WARNING, "Interrupted while locking\n"); - return; - } - idr_remove(&p->pool, id); - up(&p->lock); -} - -/** - * v9fs_check_idpool - check if the specified id is available - * @id - id to check - * @p - pool - */ -int v9fs_check_idpool(int id, struct v9fs_idpool *p) -{ - return idr_find(&p->pool, id) != NULL; -} - /** * v9fs_session_init - initialize session * @v9ses: session information structure @@ -266,25 +190,21 @@ int v9fs_check_idpool(int id, struct v9fs_idpool *p) * */ -int -v9fs_session_init(struct v9fs_session_info *v9ses, +struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, const char *dev_name, char *data) { - struct v9fs_fcall *fcall = NULL; - struct v9fs_transport *trans_proto; - int n = 0; - int newfid = -1; int retval = -EINVAL; - struct v9fs_str *version; + struct p9_transport *trans; + struct p9_fid *fid; v9ses->name = __getname(); if (!v9ses->name) - return -ENOMEM; + return ERR_PTR(-ENOMEM); v9ses->remotename = __getname(); if (!v9ses->remotename) { __putname(v9ses->name); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } strcpy(v9ses->name, V9FS_DEFUSER); @@ -292,130 +212,60 @@ v9fs_session_init(struct v9fs_session_info *v9ses, v9fs_parse_options(data, v9ses); - /* set global debug level */ - v9fs_debug_level = v9ses->debug; - - /* id pools that are session-dependent: fids and tags */ - idr_init(&v9ses->fidpool.pool); - init_MUTEX(&v9ses->fidpool.lock); - switch (v9ses->proto) { case PROTO_TCP: - trans_proto = &v9fs_trans_tcp; + trans = p9_trans_create_tcp(dev_name, v9ses->port); break; case PROTO_UNIX: - trans_proto = &v9fs_trans_unix; + trans = p9_trans_create_unix(dev_name); *v9ses->remotename = 0; break; case PROTO_FD: - trans_proto = &v9fs_trans_fd; + trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno); + *v9ses->remotename = 0; + break; +#ifdef CONFIG_PCI_9P + case PROTO_PCI: + trans = p9pci_trans_create(); *v9ses->remotename = 0; break; +#endif default: printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); retval = -ENOPROTOOPT; - goto SessCleanUp; + goto error; }; - v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); - if (!v9ses->transport) { - retval = -ENOMEM; - goto SessCleanUp; + if (IS_ERR(trans)) { + retval = PTR_ERR(trans); + trans = NULL; + goto error; } - memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); + v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ, + v9ses->extended); - if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { - eprintk(KERN_ERR, "problem initializing transport\n"); - goto SessCleanUp; + if (IS_ERR(v9ses->clnt)) { + retval = PTR_ERR(v9ses->clnt); + v9ses->clnt = NULL; + P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n"); + goto error; } - v9ses->inprogress = 0; - v9ses->shutdown = 0; - v9ses->session_hung = 0; - - v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, - &v9ses->extended); - - if (IS_ERR(v9ses->mux)) { - retval = PTR_ERR(v9ses->mux); - v9ses->mux = NULL; - dprintk(DEBUG_ERROR, "problem initializing mux\n"); - goto SessCleanUp; + fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name, + v9ses->remotename); + if (IS_ERR(fid)) { + retval = PTR_ERR(fid); + fid = NULL; + P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n"); + goto error; } - if (v9ses->afid == ~0) { - if (v9ses->extended) - retval = - v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u", - &fcall); - else - retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000", - &fcall); - - if (retval < 0) { - dprintk(DEBUG_ERROR, "v9fs_t_version failed\n"); - goto FreeFcall; - } - - version = &fcall->params.rversion.version; - if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { - dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); - v9ses->extended = 1; - } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { - dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); - v9ses->extended = 0; - } else { - retval = -EREMOTEIO; - goto FreeFcall; - } + return fid; - n = fcall->params.rversion.msize; - kfree(fcall); - - if (n < v9ses->maxdata) - v9ses->maxdata = n; - } - - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { - eprintk(KERN_WARNING, "couldn't allocate FID\n"); - retval = -ENOMEM; - goto SessCleanUp; - } - /* it is a little bit ugly, but we have to prevent newfid */ - /* being the same as afid, so if it is, get a new fid */ - if (v9ses->afid != ~0 && newfid == v9ses->afid) { - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { - eprintk(KERN_WARNING, "couldn't allocate FID\n"); - retval = -ENOMEM; - goto SessCleanUp; - } - } - - if ((retval = - v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid, - v9ses->afid, NULL)) - < 0) { - dprintk(DEBUG_ERROR, "cannot attach\n"); - goto SessCleanUp; - } - - if (v9ses->afid != ~0) { - dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); - if (v9fs_t_clunk(v9ses, v9ses->afid)) - dprintk(DEBUG_ERROR, "clunk failed\n"); - } - - return newfid; - - FreeFcall: - kfree(fcall); - - SessCleanUp: +error: v9fs_session_close(v9ses); - return retval; + return ERR_PTR(retval); } /** @@ -426,15 +276,9 @@ v9fs_session_init(struct v9fs_session_info *v9ses, void v9fs_session_close(struct v9fs_session_info *v9ses) { - if (v9ses->mux) { - v9fs_mux_destroy(v9ses->mux); - v9ses->mux = NULL; - } - - if (v9ses->transport) { - v9ses->transport->close(v9ses->transport); - kfree(v9ses->transport); - v9ses->transport = NULL; + if (v9ses->clnt) { + p9_client_destroy(v9ses->clnt); + v9ses->clnt = NULL; } __putname(v9ses->name); @@ -446,9 +290,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) * and cancel all pending requests. */ void v9fs_session_cancel(struct v9fs_session_info *v9ses) { - dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses); - v9ses->transport->status = Disconnected; - v9fs_mux_cancel(v9ses->mux, -EIO); + P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); + p9_client_disconnect(v9ses->clnt); } extern int v9fs_error_init(void); @@ -460,24 +303,9 @@ extern int v9fs_error_init(void); static int __init init_v9fs(void) { - int ret; - - v9fs_error_init(); - printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); - ret = v9fs_mux_global_init(); - if (ret) { - printk(KERN_WARNING "v9fs: starting mux failed\n"); - return ret; - } - ret = register_filesystem(&v9fs_fs_type); - if (ret) { - printk(KERN_WARNING "v9fs: registering file system failed\n"); - v9fs_mux_global_exit(); - } - - return ret; + return register_filesystem(&v9fs_fs_type); } /** @@ -487,13 +315,13 @@ static int __init init_v9fs(void) static void __exit exit_v9fs(void) { - v9fs_mux_global_exit(); unregister_filesystem(&v9fs_fs_type); } module_init(init_v9fs) module_exit(exit_v9fs) +MODULE_AUTHOR("Latchesar Ionkov "); MODULE_AUTHOR("Eric Van Hensbergen "); MODULE_AUTHOR("Ron Minnich "); MODULE_LICENSE("GPL"); diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 820bf5ca35d8..abc4b1668ace 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -21,16 +21,6 @@ * */ -/* - * Idpool structure provides lock and id management - * - */ - -struct v9fs_idpool { - struct semaphore lock; - struct idr pool; -}; - /* * Session structure provides information for an opened session * @@ -54,15 +44,7 @@ struct v9fs_session_info { unsigned int uid; /* default uid/muid for legacy support */ unsigned int gid; /* default gid for legacy support */ - /* book keeping */ - struct v9fs_idpool fidpool; /* The FID pool for file descriptors */ - - struct v9fs_transport *transport; - struct v9fs_mux_data *mux; - - int inprogress; /* session in progress => true */ - int shutdown; /* session shutting down. no more attaches. */ - unsigned char session_hung; + struct p9_client *clnt; /* 9p client */ struct dentry *debugfs_dir; }; @@ -71,6 +53,7 @@ enum { PROTO_TCP, PROTO_UNIX, PROTO_FD, + PROTO_PCI, }; /* possible values of ->cache */ @@ -82,12 +65,9 @@ enum { extern struct dentry *v9fs_debugfs_root; -int v9fs_session_init(struct v9fs_session_info *, const char *, char *); -struct v9fs_session_info *v9fs_inode2v9ses(struct inode *); +struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, + char *); void v9fs_session_close(struct v9fs_session_info *v9ses); -int v9fs_get_idpool(struct v9fs_idpool *p); -void v9fs_put_idpool(int id, struct v9fs_idpool *p); -int v9fs_check_idpool(int id, struct v9fs_idpool *p); void v9fs_session_cancel(struct v9fs_session_info *v9ses); #define V9FS_MAGIC 0x01021997 @@ -97,3 +77,7 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses); #define V9FS_DEFUSER "nobody" #define V9FS_DEFANAME "" +static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) +{ + return (inode->i_sb->s_fs_info); +} diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 6a82d39dc498..fd01d90cada5 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -45,10 +45,10 @@ extern struct dentry_operations v9fs_dentry_operations; extern struct dentry_operations v9fs_cached_dentry_operations; struct inode *v9fs_get_inode(struct super_block *sb, int mode); -ino_t v9fs_qid2ino(struct v9fs_qid *qid); -void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *); +ino_t v9fs_qid2ino(struct p9_qid *qid); +void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *); int v9fs_dir_release(struct inode *inode, struct file *filp); int v9fs_file_open(struct inode *inode, struct file *file); -void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); +void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat); void v9fs_dentry_release(struct dentry *); int v9fs_uflags2omode(int uflags); diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 9ac4ffe9ac7d..6248f0e727a3 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -33,10 +33,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -50,55 +50,26 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) { - char *buffer = NULL; - int retval = -EIO; - loff_t offset = page_offset(page); - int count = PAGE_CACHE_SIZE; - struct inode *inode = filp->f_path.dentry->d_inode; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - int rsize = v9ses->maxdata - V9FS_IOHDRSZ; - struct v9fs_fid *v9f = filp->private_data; - struct v9fs_fcall *fcall = NULL; - int fid = v9f->fid; - int total = 0; - int result = 0; - - dprintk(DEBUG_VFS, "\n"); + int retval; + loff_t offset; + char *buffer; + struct p9_fid *fid; + P9_DPRINTK(P9_DEBUG_VFS, "\n"); + fid = filp->private_data; buffer = kmap(page); - do { - if (count < rsize) - rsize = count; - - result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall); - - if (result < 0) { - printk(KERN_ERR "v9fs_t_read returned %d\n", - result); - - kfree(fcall); - goto UnmapAndUnlock; - } else - offset += result; - - memcpy(buffer, fcall->params.rread.data, result); - - count -= result; - buffer += result; - total += result; - - kfree(fcall); + offset = page_offset(page); - if (result < rsize) - break; - } while (count); + retval = p9_client_readn(fid, buffer, offset, PAGE_CACHE_SIZE); + if (retval < 0) + goto done; - memset(buffer, 0, count); + memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); retval = 0; -UnmapAndUnlock: +done: kunmap(page); unlock_page(page); return retval; diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index d93960429c09..f9534f18df0a 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -34,10 +34,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -52,7 +52,7 @@ static int v9fs_dentry_delete(struct dentry *dentry) { - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); return 1; } @@ -69,7 +69,7 @@ static int v9fs_dentry_delete(struct dentry *dentry) static int v9fs_cached_dentry_delete(struct dentry *dentry) { struct inode *inode = dentry->d_inode; - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); if(!inode) return 1; @@ -85,26 +85,19 @@ static int v9fs_cached_dentry_delete(struct dentry *dentry) void v9fs_dentry_release(struct dentry *dentry) { - int err; - - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); - - if (dentry->d_fsdata != NULL) { - struct list_head *fid_list = dentry->d_fsdata; - struct v9fs_fid *temp = NULL; - struct v9fs_fid *current_fid = NULL; - - list_for_each_entry_safe(current_fid, temp, fid_list, list) { - err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid); - - if (err < 0) - dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n", - err, dentry->d_iname); - - v9fs_fid_destroy(current_fid); + struct v9fs_dentry *dent; + struct p9_fid *temp, *current_fid; + + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + dent = dentry->d_fsdata; + if (dent) { + list_for_each_entry_safe(current_fid, temp, &dent->fidlist, + dlist) { + p9_client_clunk(current_fid); } - kfree(dentry->d_fsdata); /* free the list_head */ + kfree(dent); + dentry->d_fsdata = NULL; } } diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 1dd86ee90bc5..0924d4477da3 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -32,11 +32,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" -#include "conv.h" #include "v9fs_vfs.h" #include "fid.h" @@ -46,14 +45,14 @@ * */ -static inline int dt_type(struct v9fs_stat *mistat) +static inline int dt_type(struct p9_stat *mistat) { unsigned long perm = mistat->mode; int rettype = DT_REG; - if (perm & V9FS_DMDIR) + if (perm & P9_DMDIR) rettype = DT_DIR; - if (perm & V9FS_DMSYMLINK) + if (perm & P9_DMSYMLINK) rettype = DT_LNK; return rettype; @@ -69,106 +68,36 @@ static inline int dt_type(struct v9fs_stat *mistat) static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) { - struct v9fs_fcall *fcall = NULL; - struct inode *inode = filp->f_path.dentry->d_inode; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *file = filp->private_data; - unsigned int i, n, s; - int fid = -1; - int ret = 0; - struct v9fs_stat stat; - int over = 0; - - dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); - - fid = file->fid; - - if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { - kfree(file->rdir_fcall); - file->rdir_fcall = NULL; - } - - if (file->rdir_fcall) { - n = file->rdir_fcall->params.rread.count; - i = file->rdir_fpos; - while (i < n) { - s = v9fs_deserialize_stat( - file->rdir_fcall->params.rread.data + i, - n - i, &stat, v9ses->extended); - - if (s == 0) { - dprintk(DEBUG_ERROR, - "error while deserializing stat\n"); - ret = -EIO; - goto FreeStructs; - } - - over = filldir(dirent, stat.name.str, stat.name.len, - filp->f_pos, v9fs_qid2ino(&stat.qid), - dt_type(&stat)); - - if (over) { - file->rdir_fpos = i; - file->rdir_pos = filp->f_pos; - break; - } - - i += s; - filp->f_pos += s; - } - - if (!over) { - kfree(file->rdir_fcall); - file->rdir_fcall = NULL; - } - } - - while (!over) { - ret = v9fs_t_read(v9ses, fid, filp->f_pos, - v9ses->maxdata-V9FS_IOHDRSZ, &fcall); - if (ret < 0) { - dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", - ret, fcall); - goto FreeStructs; - } else if (ret == 0) + int over; + struct p9_fid *fid; + struct v9fs_session_info *v9ses; + struct inode *inode; + struct p9_stat *st; + + P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); + inode = filp->f_path.dentry->d_inode; + v9ses = v9fs_inode2v9ses(inode); + fid = filp->private_data; + while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) { + if (IS_ERR(st)) + return PTR_ERR(st); + + over = filldir(dirent, st->name.str, st->name.len, filp->f_pos, + v9fs_qid2ino(&st->qid), dt_type(st)); + + if (over) break; - n = ret; - i = 0; - while (i < n) { - s = v9fs_deserialize_stat(fcall->params.rread.data + i, - n - i, &stat, v9ses->extended); - - if (s == 0) { - dprintk(DEBUG_ERROR, - "error while deserializing stat\n"); - return -EIO; - } - - over = filldir(dirent, stat.name.str, stat.name.len, - filp->f_pos, v9fs_qid2ino(&stat.qid), - dt_type(&stat)); - - if (over) { - file->rdir_fcall = fcall; - file->rdir_fpos = i; - file->rdir_pos = filp->f_pos; - fcall = NULL; - break; - } - - i += s; - filp->f_pos += s; - } - - kfree(fcall); + filp->f_pos += st->size; + kfree(st); + st = NULL; } - FreeStructs: - kfree(fcall); - return ret; + kfree(st); + return 0; } + /** * v9fs_dir_release - close a directory * @inode: inode of the directory @@ -178,29 +107,13 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) int v9fs_dir_release(struct inode *inode, struct file *filp) { - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *fid = filp->private_data; - int fidnum = -1; - - dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp, - fid->fid); - fidnum = fid->fid; + struct p9_fid *fid; + fid = filp->private_data; + P9_DPRINTK(P9_DEBUG_VFS, + "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); filemap_write_and_wait(inode->i_mapping); - - if (fidnum >= 0) { - dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, - fid->fid); - - if (v9fs_t_clunk(v9ses, fidnum)) - dprintk(DEBUG_ERROR, "clunk failed\n"); - - kfree(fid->rdir_fcall); - kfree(fid); - - filp->private_data = NULL; - } - + p9_client_clunk(fid); return 0; } diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 6e7678e4852f..c1f7c027cfeb 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -34,10 +34,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -52,48 +52,36 @@ static const struct file_operations v9fs_cached_file_operations; int v9fs_file_open(struct inode *inode, struct file *file) { - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *vfid; - struct v9fs_fcall *fcall = NULL; - int omode; int err; + struct v9fs_session_info *v9ses; + struct p9_fid *fid; + int omode; - dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); - - vfid = v9fs_fid_clone(file->f_path.dentry); - if (IS_ERR(vfid)) - return PTR_ERR(vfid); - + P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); + v9ses = v9fs_inode2v9ses(inode); omode = v9fs_uflags2omode(file->f_flags); - err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall); + fid = file->private_data; + if (!fid) { + fid = v9fs_fid_clone(file->f_path.dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + + err = p9_client_open(fid, omode); if (err < 0) { - PRINT_FCALL_ERROR("open failed", fcall); - goto Clunk_Fid; + p9_client_clunk(fid); + return err; + } } - file->private_data = vfid; - vfid->fidopen = 1; - vfid->fidclunked = 0; - vfid->iounit = fcall->params.ropen.iounit; - vfid->rdir_pos = 0; - vfid->rdir_fcall = NULL; - vfid->filp = file; - kfree(fcall); - - if((vfid->qid.version) && (v9ses->cache)) { - dprintk(DEBUG_VFS, "cached"); + file->private_data = fid; + if ((fid->qid.version) && (v9ses->cache)) { + P9_DPRINTK(P9_DEBUG_VFS, "cached"); /* enable cached file options */ if(file->f_op == &v9fs_file_operations) file->f_op = &v9fs_cached_file_operations; } return 0; - -Clunk_Fid: - v9fs_fid_clunk(v9ses, vfid); - kfree(fcall); - - return err; } /** @@ -110,7 +98,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) int res = 0; struct inode *inode = filp->f_path.dentry->d_inode; - dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); + P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); /* No mandatory locks */ if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) @@ -136,55 +124,16 @@ static ssize_t v9fs_file_read(struct file *filp, char __user * data, size_t count, loff_t * offset) { - struct inode *inode = filp->f_path.dentry->d_inode; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *v9f = filp->private_data; - struct v9fs_fcall *fcall = NULL; - int fid = v9f->fid; - int rsize = 0; - int result = 0; - int total = 0; - int n; - - dprintk(DEBUG_VFS, "\n"); - - rsize = v9ses->maxdata - V9FS_IOHDRSZ; - if (v9f->iounit != 0 && rsize > v9f->iounit) - rsize = v9f->iounit; - - do { - if (count < rsize) - rsize = count; + int ret; + struct p9_fid *fid; - result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall); + P9_DPRINTK(P9_DEBUG_VFS, "\n"); + fid = filp->private_data; + ret = p9_client_uread(fid, data, *offset, count); + if (ret > 0) + *offset += ret; - if (result < 0) { - printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n", - result); - - kfree(fcall); - return total; - } else - *offset += result; - - n = copy_to_user(data, fcall->params.rread.data, result); - if (n) { - dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); - kfree(fcall); - return -EFAULT; - } - - count -= result; - data += result; - total += result; - - kfree(fcall); - - if (result < rsize) - break; - } while (count); - - return total; + return ret; } /** @@ -200,50 +149,19 @@ static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t * offset) { - struct inode *inode = filp->f_path.dentry->d_inode; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *v9fid = filp->private_data; - struct v9fs_fcall *fcall; - int fid = v9fid->fid; - int result = -EIO; - int rsize = 0; - int total = 0; - - dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, - (int)*offset); - rsize = v9ses->maxdata - V9FS_IOHDRSZ; - if (v9fid->iounit != 0 && rsize > v9fid->iounit) - rsize = v9fid->iounit; - - do { - if (count < rsize) - rsize = count; + int ret; + struct p9_fid *fid; - result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall); - if (result < 0) { - PRINT_FCALL_ERROR("error while writing", fcall); - kfree(fcall); - return result; - } else - *offset += result; - - kfree(fcall); - fcall = NULL; - - if (result != rsize) { - eprintk(KERN_ERR, - "short write: v9fs_t_write returned %d\n", - result); - break; - } + P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, + (int)count, (int)*offset); - count -= result; - data += result; - total += result; - } while (count); + fid = filp->private_data; + ret = p9_client_uwrite(fid, data, *offset, count); + if (ret > 0) + *offset += ret; - invalidate_inode_pages2(inode->i_mapping); - return total; + invalidate_inode_pages2(filp->f_path.dentry->d_inode->i_mapping); + return ret; } static const struct file_operations v9fs_cached_file_operations = { diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c76cd8fa3f6c..c602c0e054a2 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -34,10 +34,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -58,27 +58,27 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode) int res; res = mode & 0777; if (S_ISDIR(mode)) - res |= V9FS_DMDIR; + res |= P9_DMDIR; if (v9ses->extended) { if (S_ISLNK(mode)) - res |= V9FS_DMSYMLINK; + res |= P9_DMSYMLINK; if (v9ses->nodev == 0) { if (S_ISSOCK(mode)) - res |= V9FS_DMSOCKET; + res |= P9_DMSOCKET; if (S_ISFIFO(mode)) - res |= V9FS_DMNAMEDPIPE; + res |= P9_DMNAMEDPIPE; if (S_ISBLK(mode)) - res |= V9FS_DMDEVICE; + res |= P9_DMDEVICE; if (S_ISCHR(mode)) - res |= V9FS_DMDEVICE; + res |= P9_DMDEVICE; } if ((mode & S_ISUID) == S_ISUID) - res |= V9FS_DMSETUID; + res |= P9_DMSETUID; if ((mode & S_ISGID) == S_ISGID) - res |= V9FS_DMSETGID; - if ((mode & V9FS_DMLINK)) - res |= V9FS_DMLINK; + res |= P9_DMSETGID; + if ((mode & P9_DMLINK)) + res |= P9_DMLINK; } return res; @@ -97,27 +97,27 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) res = mode & 0777; - if ((mode & V9FS_DMDIR) == V9FS_DMDIR) + if ((mode & P9_DMDIR) == P9_DMDIR) res |= S_IFDIR; - else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended)) + else if ((mode & P9_DMSYMLINK) && (v9ses->extended)) res |= S_IFLNK; - else if ((mode & V9FS_DMSOCKET) && (v9ses->extended) + else if ((mode & P9_DMSOCKET) && (v9ses->extended) && (v9ses->nodev == 0)) res |= S_IFSOCK; - else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended) + else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended) && (v9ses->nodev == 0)) res |= S_IFIFO; - else if ((mode & V9FS_DMDEVICE) && (v9ses->extended) + else if ((mode & P9_DMDEVICE) && (v9ses->extended) && (v9ses->nodev == 0)) res |= S_IFBLK; else res |= S_IFREG; if (v9ses->extended) { - if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID) + if ((mode & P9_DMSETUID) == P9_DMSETUID) res |= S_ISUID; - if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID) + if ((mode & P9_DMSETGID) == P9_DMSETGID) res |= S_ISGID; } @@ -132,26 +132,26 @@ int v9fs_uflags2omode(int uflags) switch (uflags&3) { default: case O_RDONLY: - ret = V9FS_OREAD; + ret = P9_OREAD; break; case O_WRONLY: - ret = V9FS_OWRITE; + ret = P9_OWRITE; break; case O_RDWR: - ret = V9FS_ORDWR; + ret = P9_ORDWR; break; } if (uflags & O_EXCL) - ret |= V9FS_OEXCL; + ret |= P9_OEXCL; if (uflags & O_TRUNC) - ret |= V9FS_OTRUNC; + ret |= P9_OTRUNC; if (uflags & O_APPEND) - ret |= V9FS_OAPPEND; + ret |= P9_OAPPEND; return ret; } @@ -164,7 +164,7 @@ int v9fs_uflags2omode(int uflags) */ static void -v9fs_blank_wstat(struct v9fs_wstat *wstat) +v9fs_blank_wstat(struct p9_wstat *wstat) { wstat->type = ~0; wstat->dev = ~0; @@ -197,7 +197,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) struct inode *inode; struct v9fs_session_info *v9ses = sb->s_fs_info; - dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); + P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); inode = new_inode(sb); if (inode) { @@ -215,7 +215,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) case S_IFCHR: case S_IFSOCK: if(!v9ses->extended) { - dprintk(DEBUG_ERROR, "special files without extended mode\n"); + P9_DPRINTK(P9_DEBUG_ERROR, + "special files without extended mode\n"); return ERR_PTR(-EINVAL); } init_special_inode(inode, inode->i_mode, @@ -227,7 +228,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) break; case S_IFLNK: if(!v9ses->extended) { - dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n"); + P9_DPRINTK(P9_DEBUG_ERROR, + "extended modes used w/o 9P2000.u\n"); return ERR_PTR(-EINVAL); } inode->i_op = &v9fs_symlink_inode_operations; @@ -241,71 +243,19 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) inode->i_fop = &v9fs_dir_operations; break; default: - dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", + P9_DPRINTK(P9_DEBUG_ERROR, + "BAD mode 0x%x S_IFMT 0x%x\n", mode, mode & S_IFMT); return ERR_PTR(-EINVAL); } } else { - eprintk(KERN_WARNING, "Problem allocating inode\n"); + P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); return ERR_PTR(-ENOMEM); } return inode; } -static int -v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm, - u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit) -{ - int fid; - int err; - struct v9fs_fcall *fcall; - - fid = v9fs_get_idpool(&v9ses->fidpool); - if (fid < 0) { - eprintk(KERN_WARNING, "no free fids available\n"); - return -ENOSPC; - } - - err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall); - if (err < 0) { - PRINT_FCALL_ERROR("clone error", fcall); - if (fcall && fcall->id == RWALK) - goto clunk_fid; - else - goto put_fid; - } - kfree(fcall); - - err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall); - if (err < 0) { - PRINT_FCALL_ERROR("create fails", fcall); - goto clunk_fid; - } - - if (iounit) - *iounit = fcall->params.rcreate.iounit; - - if (qid) - *qid = fcall->params.rcreate.qid; - - if (fidp) - *fidp = fid; - - kfree(fcall); - return 0; - -clunk_fid: - v9fs_t_clunk(v9ses, fid); - fid = V9FS_NOFID; - -put_fid: - if (fid != V9FS_NOFID) - v9fs_put_idpool(fid, &v9ses->fidpool); - - kfree(fcall); - return err; -} - +/* static struct v9fs_fid* v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) { @@ -355,23 +305,25 @@ error: kfree(fcall); return ERR_PTR(err); } +*/ static struct inode * -v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, +v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, struct super_block *sb) { int err, umode; struct inode *ret; - struct v9fs_fcall *fcall; + struct p9_stat *st; ret = NULL; - err = v9fs_t_stat(v9ses, fid, &fcall); - if (err) { - PRINT_FCALL_ERROR("stat error", fcall); + st = p9_client_stat(fid); + if (IS_ERR(st)) { + err = PTR_ERR(st); + st = NULL; goto error; } - umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); + umode = p9mode2unixmode(v9ses, st->mode); ret = v9fs_get_inode(sb, umode); if (IS_ERR(ret)) { err = PTR_ERR(ret); @@ -379,12 +331,13 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, goto error; } - v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); - kfree(fcall); + v9fs_stat2inode(st, ret, sb); + ret->i_ino = v9fs_qid2ino(&st->qid); + kfree(st); return ret; error: - kfree(fcall); + kfree(st); if (ret) iput(ret); @@ -401,43 +354,20 @@ error: static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) { - struct v9fs_fcall *fcall = NULL; - struct super_block *sb = NULL; - struct v9fs_session_info *v9ses = NULL; - struct v9fs_fid *v9fid = NULL; - struct inode *file_inode = NULL; - int fid = -1; - int result = 0; + struct inode *file_inode; + struct v9fs_session_info *v9ses; + struct p9_fid *v9fid; - dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, + P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, rmdir); file_inode = file->d_inode; - sb = file_inode->i_sb; v9ses = v9fs_inode2v9ses(file_inode); v9fid = v9fs_fid_clone(file); if(IS_ERR(v9fid)) return PTR_ERR(v9fid); - fid = v9fid->fid; - if (fid < 0) { - dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n", - file_inode->i_ino); - return -EBADF; - } - - result = v9fs_t_remove(v9ses, fid, &fcall); - if (result < 0) { - PRINT_FCALL_ERROR("remove fails", fcall); - goto Error; - } - - v9fs_put_idpool(fid, &v9ses->fidpool); - v9fs_fid_destroy(v9fid); - -Error: - kfree(fcall); - return result; + return p9_client_remove(v9fid); } static int @@ -446,61 +376,59 @@ v9fs_open_created(struct inode *inode, struct file *file) return 0; } + /** - * v9fs_vfs_create - VFS hook to create files - * @inode: directory inode that is being deleted - * @dentry: dentry that is being deleted - * @mode: create permissions - * @nd: path information + * v9fs_create - Create a file + * @dentry: dentry that is being created + * @perm: create permissions + * @mode: open mode * */ - -static int -v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) +static struct p9_fid * +v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, + struct dentry *dentry, char *extension, u32 perm, u8 mode) { int err; - u32 fid, perm, iounit; - int flags; - struct v9fs_session_info *v9ses; - struct v9fs_fid *dfid, *vfid, *ffid; + char *name; + struct p9_fid *dfid, *ofid, *fid; struct inode *inode; - struct v9fs_qid qid; - struct file *filp; - inode = NULL; - vfid = NULL; - v9ses = v9fs_inode2v9ses(dir); + err = 0; + ofid = NULL; + fid = NULL; + name = (char *) dentry->d_name.name; dfid = v9fs_fid_clone(dentry->d_parent); if(IS_ERR(dfid)) { err = PTR_ERR(dfid); + dfid = NULL; goto error; } - perm = unixmode2p9mode(v9ses, mode); - if (nd && nd->flags & LOOKUP_OPEN) - flags = nd->intent.open.flags - 1; - else - flags = O_RDWR; - - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, - perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); + /* clone a fid to use for creation */ + ofid = p9_client_walk(dfid, 0, NULL, 1); + if (IS_ERR(ofid)) { + err = PTR_ERR(ofid); + ofid = NULL; + goto error; + } - if (err) - goto clunk_dfid; + err = p9_client_fcreate(ofid, name, perm, mode, extension); + if (err < 0) + goto error; - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); - v9fs_fid_clunk(v9ses, dfid); - if (IS_ERR(vfid)) { - err = PTR_ERR(vfid); - vfid = NULL; + /* now walk from the parent so we can get unopened fid */ + fid = p9_client_walk(dfid, 1, &name, 0); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; goto error; - } + } else + dfid = NULL; - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); + /* instantiate inode and assign the unopened fid to the dentry */ + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); if (IS_ERR(inode)) { err = PTR_ERR(inode); - inode = NULL; goto error; } @@ -508,35 +436,78 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, dentry->d_op = &v9fs_cached_dentry_operations; else dentry->d_op = &v9fs_dentry_operations; + d_instantiate(dentry, inode); + v9fs_fid_add(dentry, fid); + return ofid; - if (nd && nd->flags & LOOKUP_OPEN) { - ffid = v9fs_fid_create(v9ses, fid); - if (!ffid) - return -ENOMEM; +error: + if (dfid) + p9_client_clunk(dfid); + + if (ofid) + p9_client_clunk(ofid); + + if (fid) + p9_client_clunk(fid); + + return ERR_PTR(err); +} + +/** + * v9fs_vfs_create - VFS hook to create files + * @inode: directory inode that is being created + * @dentry: dentry that is being deleted + * @mode: create permissions + * @nd: path information + * + */ +static int +v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + int err; + u32 perm; + int flags; + struct v9fs_session_info *v9ses; + struct p9_fid *fid; + struct file *filp; + + err = 0; + fid = NULL; + v9ses = v9fs_inode2v9ses(dir); + perm = unixmode2p9mode(v9ses, mode); + if (nd && nd->flags & LOOKUP_OPEN) + flags = nd->intent.open.flags - 1; + else + flags = O_RDWR; + + fid = v9fs_create(v9ses, dir, dentry, NULL, perm, + v9fs_uflags2omode(flags)); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; + goto error; + } + + /* if we are opening a file, assign the open fid to the file */ + if (nd && nd->flags & LOOKUP_OPEN) { filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); if (IS_ERR(filp)) { - v9fs_fid_destroy(ffid); - return PTR_ERR(filp); + err = PTR_ERR(filp); + goto error; } - ffid->rdir_pos = 0; - ffid->rdir_fcall = NULL; - ffid->fidopen = 1; - ffid->iounit = iounit; - ffid->filp = filp; - filp->private_data = ffid; - } + filp->private_data = fid; + } else + p9_client_clunk(fid); return 0; -clunk_dfid: - v9fs_fid_clunk(v9ses, dfid); - error: - if (vfid) - v9fs_fid_destroy(vfid); + if (fid) + p9_client_clunk(fid); return err; } @@ -552,57 +523,23 @@ error: static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int err; - u32 fid, perm; + u32 perm; struct v9fs_session_info *v9ses; - struct v9fs_fid *dfid, *vfid; - struct inode *inode; + struct p9_fid *fid; - inode = NULL; - vfid = NULL; + P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); + err = 0; v9ses = v9fs_inode2v9ses(dir); - dfid = v9fs_fid_clone(dentry->d_parent); - if(IS_ERR(dfid)) { - err = PTR_ERR(dfid); - goto error; - } - perm = unixmode2p9mode(v9ses, mode | S_IFDIR); - - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, - perm, V9FS_OREAD, NULL, &fid, NULL, NULL); - - if (err) { - dprintk(DEBUG_ERROR, "create error %d\n", err); - goto clean_up_dfid; + fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; } - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); - if (IS_ERR(vfid)) { - err = PTR_ERR(vfid); - vfid = NULL; - goto clean_up_dfid; - } + if (fid) + p9_client_clunk(fid); - v9fs_fid_clunk(v9ses, dfid); - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - inode = NULL; - v9fs_fid_destroy(vfid); - goto error; - } - - if(v9ses->cache) - dentry->d_op = &v9fs_cached_dentry_operations; - else - dentry->d_op = &v9fs_dentry_operations; - d_instantiate(dentry, inode); - return 0; - -clean_up_dfid: - v9fs_fid_clunk(v9ses, dfid); - -error: return err; } @@ -619,104 +556,54 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, { struct super_block *sb; struct v9fs_session_info *v9ses; - struct v9fs_fid *dirfid; - struct v9fs_fid *fid; + struct p9_fid *dfid, *fid; struct inode *inode; - struct v9fs_fcall *fcall = NULL; - int dirfidnum = -1; - int newfid = -1; + char *name; int result = 0; - dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", + P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", dir, dentry->d_name.name, dentry, nameidata); sb = dir->i_sb; v9ses = v9fs_inode2v9ses(dir); - dirfid = v9fs_fid_lookup(dentry->d_parent); - - if(IS_ERR(dirfid)) - return ERR_PTR(PTR_ERR(dirfid)); - - dirfidnum = dirfid->fid; - - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { - eprintk(KERN_WARNING, "newfid fails!\n"); - result = -ENOSPC; - goto Release_Dirfid; - } - - result = v9fs_t_walk(v9ses, dirfidnum, newfid, - (char *)dentry->d_name.name, &fcall); - - up(&dirfid->lock); - - if (result < 0) { - if (fcall && fcall->id == RWALK) - v9fs_t_clunk(v9ses, newfid); - else - v9fs_put_idpool(newfid, &v9ses->fidpool); - + dfid = v9fs_fid_lookup(dentry->d_parent); + if (IS_ERR(dfid)) + return ERR_PTR(PTR_ERR(dfid)); + + name = (char *) dentry->d_name.name; + fid = p9_client_walk(dfid, 1, &name, 1); + if (IS_ERR(fid)) { + result = PTR_ERR(fid); if (result == -ENOENT) { d_add(dentry, NULL); - dprintk(DEBUG_VFS, - "Return negative dentry %p count %d\n", - dentry, atomic_read(&dentry->d_count)); - kfree(fcall); return NULL; } - dprintk(DEBUG_ERROR, "walk error:%d\n", result); - goto FreeFcall; - } - kfree(fcall); - - result = v9fs_t_stat(v9ses, newfid, &fcall); - if (result < 0) { - dprintk(DEBUG_ERROR, "stat error\n"); - goto FreeFcall; - } - - inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses, - fcall->params.rstat.stat.mode)); - if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { - eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n", - PTR_ERR(inode)); - - result = -ENOSPC; - goto FreeFcall; + return ERR_PTR(result); } - inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); - - fid = v9fs_fid_create(v9ses, newfid); - if (fid == NULL) { - dprintk(DEBUG_ERROR, "couldn't insert\n"); - result = -ENOMEM; - goto FreeFcall; + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + result = PTR_ERR(inode); + inode = NULL; + goto error; } - result = v9fs_fid_insert(fid, dentry); + result = v9fs_fid_add(dentry, fid); if (result < 0) - goto FreeFcall; + goto error; - fid->qid = fcall->params.rstat.stat.qid; - v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); if((fid->qid.version)&&(v9ses->cache)) dentry->d_op = &v9fs_cached_dentry_operations; else dentry->d_op = &v9fs_dentry_operations; d_add(dentry, inode); - kfree(fcall); - return NULL; -Release_Dirfid: - up(&dirfid->lock); - -FreeFcall: - kfree(fcall); +error: + if (fid) + p9_client_clunk(fid); return ERR_PTR(result); } @@ -758,73 +645,54 @@ static int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { - struct inode *old_inode = old_dentry->d_inode; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); - struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); - struct v9fs_fid *olddirfid; - struct v9fs_fid *newdirfid; - struct v9fs_wstat wstat; - struct v9fs_fcall *fcall = NULL; - int fid = -1; - int olddirfidnum = -1; - int newdirfidnum = -1; - int retval = 0; - - dprintk(DEBUG_VFS, "\n"); + struct inode *old_inode; + struct v9fs_session_info *v9ses; + struct p9_fid *oldfid; + struct p9_fid *olddirfid; + struct p9_fid *newdirfid; + struct p9_wstat wstat; + int retval; + P9_DPRINTK(P9_DEBUG_VFS, "\n"); + retval = 0; + old_inode = old_dentry->d_inode; + v9ses = v9fs_inode2v9ses(old_inode); + oldfid = v9fs_fid_lookup(old_dentry); if(IS_ERR(oldfid)) return PTR_ERR(oldfid); olddirfid = v9fs_fid_clone(old_dentry->d_parent); if(IS_ERR(olddirfid)) { retval = PTR_ERR(olddirfid); - goto Release_lock; + goto done; } newdirfid = v9fs_fid_clone(new_dentry->d_parent); if(IS_ERR(newdirfid)) { retval = PTR_ERR(newdirfid); - goto Clunk_olddir; + goto clunk_olddir; } /* 9P can only handle file rename in the same directory */ if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { - dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); + P9_DPRINTK(P9_DEBUG_ERROR, + "old dir and new dir are different\n"); retval = -EXDEV; - goto Clunk_newdir; - } - - fid = oldfid->fid; - olddirfidnum = olddirfid->fid; - newdirfidnum = newdirfid->fid; - - if (fid < 0) { - dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", - old_inode->i_ino); - retval = -EBADF; - goto Clunk_newdir; + goto clunk_newdir; } v9fs_blank_wstat(&wstat); wstat.muid = v9ses->name; wstat.name = (char *) new_dentry->d_name.name; + retval = p9_client_wstat(oldfid, &wstat); - retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); +clunk_newdir: + p9_client_clunk(olddirfid); - if (retval < 0) - PRINT_FCALL_ERROR("wstat error", fcall); - - kfree(fcall); - -Clunk_newdir: - v9fs_fid_clunk(v9ses, newdirfid); - -Clunk_olddir: - v9fs_fid_clunk(v9ses, olddirfid); - -Release_lock: - up(&oldfid->lock); +clunk_olddir: + p9_client_clunk(newdirfid); +done: return retval; } @@ -840,28 +708,27 @@ static int v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - struct v9fs_fcall *fcall = NULL; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_clone(dentry); - int err = -EPERM; - - dprintk(DEBUG_VFS, "dentry: %p\n", dentry); - if(IS_ERR(fid)) + int err; + struct v9fs_session_info *v9ses; + struct p9_fid *fid; + struct p9_stat *st; + + P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); + err = -EPERM; + v9ses = v9fs_inode2v9ses(dentry->d_inode); + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) return PTR_ERR(fid); - err = v9fs_t_stat(v9ses, fid->fid, &fcall); + st = p9_client_stat(fid); + if (IS_ERR(st)) + return PTR_ERR(st); - if (err < 0) - dprintk(DEBUG_ERROR, "stat error\n"); - else { - v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode, - dentry->d_inode->i_sb); + v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); generic_fillattr(dentry->d_inode, stat); - } - kfree(fcall); - v9fs_fid_clunk(v9ses, fid); - return err; + kfree(st); + return 0; } /** @@ -873,13 +740,15 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) { - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_clone(dentry); - struct v9fs_fcall *fcall = NULL; - struct v9fs_wstat wstat; - int res = -EPERM; + int retval; + struct v9fs_session_info *v9ses; + struct p9_fid *fid; + struct p9_wstat wstat; - dprintk(DEBUG_VFS, "\n"); + P9_DPRINTK(P9_DEBUG_VFS, "\n"); + retval = -EPERM; + v9ses = v9fs_inode2v9ses(dentry->d_inode); + fid = v9fs_fid_lookup(dentry); if(IS_ERR(fid)) return PTR_ERR(fid); @@ -904,17 +773,11 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) wstat.n_gid = iattr->ia_gid; } - res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); + retval = p9_client_wstat(fid, &wstat); + if (retval >= 0) + retval = inode_setattr(dentry->d_inode, iattr); - if (res < 0) - PRINT_FCALL_ERROR("wstat error", fcall); - - kfree(fcall); - if (res >= 0) - res = inode_setattr(dentry->d_inode, iattr); - - v9fs_fid_clunk(v9ses, fid); - return res; + return retval; } /** @@ -926,7 +789,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) */ void -v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, +v9fs_stat2inode(struct p9_stat *stat, struct inode *inode, struct super_block *sb) { int n; @@ -967,8 +830,9 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, case 'b': break; default: - dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n", - type, stat->extension.len, stat->extension.str); + P9_DPRINTK(P9_DEBUG_ERROR, + "Unknown special type %c (%.*s)\n", type, + stat->extension.len, stat->extension.str); }; inode->i_rdev = MKDEV(major, minor); } else @@ -976,8 +840,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, inode->i_size = stat->length; - inode->i_blocks = - (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + /* not real number of blocks, but 512 byte ones ... */ + inode->i_blocks = (inode->i_size + 512 - 1) >> 9; } /** @@ -987,7 +851,7 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, * BUG: potential for inode number collisions? */ -ino_t v9fs_qid2ino(struct v9fs_qid *qid) +ino_t v9fs_qid2ino(struct p9_qid *qid) { u64 path = qid->path + 2; ino_t i = 0; @@ -1010,56 +874,46 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid) static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) { - int retval = -EPERM; + int retval; - struct v9fs_fcall *fcall = NULL; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_clone(dentry); + struct v9fs_session_info *v9ses; + struct p9_fid *fid; + struct p9_stat *st; + P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); + retval = -EPERM; + v9ses = v9fs_inode2v9ses(dentry->d_inode); + fid = v9fs_fid_lookup(dentry); if(IS_ERR(fid)) return PTR_ERR(fid); - if (!v9ses->extended) { - retval = -EBADF; - dprintk(DEBUG_ERROR, "not extended\n"); - goto ClunkFid; - } - - dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); - retval = v9fs_t_stat(v9ses, fid->fid, &fcall); - - if (retval < 0) { - dprintk(DEBUG_ERROR, "stat error\n"); - goto FreeFcall; - } + if (!v9ses->extended) + return -EBADF; - if (!fcall) { - retval = -EIO; - goto ClunkFid; - } + st = p9_client_stat(fid); + if (IS_ERR(st)) + return PTR_ERR(st); - if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { + if (!(st->mode & P9_DMSYMLINK)) { retval = -EINVAL; - goto FreeFcall; + goto done; } /* copy extension buffer into buffer */ - if (fcall->params.rstat.stat.extension.len < buflen) - buflen = fcall->params.rstat.stat.extension.len + 1; + if (st->extension.len < buflen) + buflen = st->extension.len + 1; - memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); + memmove(buffer, st->extension.str, buflen - 1); buffer[buflen-1] = 0; - dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len, - fcall->params.rstat.stat.extension.str, buffer); - retval = buflen; + P9_DPRINTK(P9_DEBUG_VFS, + "%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len, + st->extension.str, buffer); -FreeFcall: - kfree(fcall); - -ClunkFid: - v9fs_fid_clunk(v9ses, fid); + retval = buflen; +done: + kfree(st); return retval; } @@ -1084,14 +938,14 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, if (buflen > PATH_MAX) buflen = PATH_MAX; - dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); retval = v9fs_readlink(dentry, link, buflen); if (retval > 0) { if ((ret = copy_to_user(buffer, link, retval)) != 0) { - dprintk(DEBUG_ERROR, "problem copying to user: %d\n", - ret); + P9_DPRINTK(P9_DEBUG_ERROR, + "problem copying to user: %d\n", ret); retval = ret; } } @@ -1112,7 +966,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) int len = 0; char *link = __getname(); - dprintk(DEBUG_VFS, "%s n", dentry->d_name.name); + P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); if (!link) link = ERR_PTR(-ENOMEM); @@ -1141,7 +995,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void { char *s = nd_get_link(nd); - dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); + P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); if (!IS_ERR(s)) __putname(s); } @@ -1149,66 +1003,24 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, int mode, const char *extension) { - int err; - u32 fid, perm; + u32 perm; struct v9fs_session_info *v9ses; - struct v9fs_fid *dfid, *vfid = NULL; - struct inode *inode = NULL; + struct p9_fid *fid; v9ses = v9fs_inode2v9ses(dir); if (!v9ses->extended) { - dprintk(DEBUG_ERROR, "not extended\n"); + P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); return -EPERM; } - dfid = v9fs_fid_clone(dentry->d_parent); - if(IS_ERR(dfid)) { - err = PTR_ERR(dfid); - goto error; - } - perm = unixmode2p9mode(v9ses, mode); + fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, + P9_OREAD); + if (IS_ERR(fid)) + return PTR_ERR(fid); - err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, - perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); - - if (err) - goto clunk_dfid; - - err = v9fs_t_clunk(v9ses, fid); - if (err) - goto clunk_dfid; - - vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); - if (IS_ERR(vfid)) { - err = PTR_ERR(vfid); - vfid = NULL; - goto clunk_dfid; - } - - inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - inode = NULL; - goto free_vfid; - } - - if(v9ses->cache) - dentry->d_op = &v9fs_cached_dentry_operations; - else - dentry->d_op = &v9fs_dentry_operations; - d_instantiate(dentry, inode); + p9_client_clunk(fid); return 0; - -free_vfid: - v9fs_fid_destroy(vfid); - -clunk_dfid: - v9fs_fid_clunk(v9ses, dfid); - -error: - return err; - } /** @@ -1224,8 +1036,8 @@ error: static int v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { - dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, - symname); + P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, + dentry->d_name.name, symname); return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); } @@ -1247,11 +1059,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { int retval; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - struct v9fs_fid *oldfid; + struct p9_fid *oldfid; char *name; - dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, + P9_DPRINTK(P9_DEBUG_VFS, + " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, old_dentry->d_name.name); oldfid = v9fs_fid_clone(old_dentry); @@ -1265,11 +1077,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, } sprintf(name, "%d\n", oldfid->fid); - retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); + retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); __putname(name); clunk_fid: - v9fs_fid_clunk(v9ses, oldfid); + p9_client_clunk(oldfid); return retval; } @@ -1288,7 +1100,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) int retval; char *name; - dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, + P9_DPRINTK(P9_DEBUG_VFS, + " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); if (!new_valid_dev(rdev)) diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 7bdf8b326841..f6a0519ade8c 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -37,10 +37,10 @@ #include #include #include +#include +#include -#include "debug.h" #include "v9fs.h" -#include "9p.h" #include "v9fs_vfs.h" #include "fid.h" @@ -107,41 +107,48 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, struct vfsmount *mnt) { struct super_block *sb = NULL; - struct v9fs_fcall *fcall = NULL; struct inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; - struct v9fs_fid *root_fid = NULL; + struct p9_stat *st = NULL; int mode = S_IRWXUGO | S_ISVTX; uid_t uid = current->fsuid; gid_t gid = current->fsgid; - int stat_result = 0; - int newfid = 0; + struct p9_fid *fid; int retval = 0; - dprintk(DEBUG_VFS, " \n"); + P9_DPRINTK(P9_DEBUG_VFS, " \n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; - if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { - dprintk(DEBUG_ERROR, "problem initiating session\n"); - retval = newfid; - goto out_free_session; + fid = v9fs_session_init(v9ses, dev_name, data); + if (IS_ERR(fid)) { + retval = PTR_ERR(fid); + fid = NULL; + kfree(v9ses); + v9ses = NULL; + goto error; + } + + st = p9_client_stat(fid); + if (IS_ERR(st)) { + retval = PTR_ERR(st); + goto error; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); - goto out_close_session; + goto error; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); - goto put_back_sb; + goto error; } inode->i_uid = uid; @@ -150,54 +157,30 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; - goto put_back_sb; + goto error; } sb->s_root = root; + root->d_inode->i_ino = v9fs_qid2ino(&st->qid); + v9fs_stat2inode(st, root->d_inode, sb); + v9fs_fid_add(root, fid); - stat_result = v9fs_t_stat(v9ses, newfid, &fcall); - if (stat_result < 0) { - dprintk(DEBUG_ERROR, "stat error\n"); - v9fs_t_clunk(v9ses, newfid); - } else { - /* Setup the Root Inode */ - root_fid = v9fs_fid_create(v9ses, newfid); - if (root_fid == NULL) { - retval = -ENOMEM; - goto put_back_sb; - } - - retval = v9fs_fid_insert(root_fid, root); - if (retval < 0) { - kfree(fcall); - goto put_back_sb; - } - - root_fid->qid = fcall->params.rstat.stat.qid; - root->d_inode->i_ino = - v9fs_qid2ino(&fcall->params.rstat.stat.qid); - v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); - } + return simple_set_mnt(mnt, sb); - kfree(fcall); +error: + if (fid) + p9_client_clunk(fid); - if (stat_result < 0) { - retval = stat_result; - goto put_back_sb; + if (v9ses) { + v9fs_session_close(v9ses); + kfree(v9ses); } - return simple_set_mnt(mnt, sb); - -out_close_session: - v9fs_session_close(v9ses); -out_free_session: - kfree(v9ses); - return retval; + if (sb) { + up_write(&sb->s_umount); + deactivate_super(sb); + } -put_back_sb: - /* deactivate_super calls v9fs_kill_super which will frees the rest */ - up_write(&sb->s_umount); - deactivate_super(sb); return retval; } @@ -211,7 +194,7 @@ static void v9fs_kill_super(struct super_block *s) { struct v9fs_session_info *v9ses = s->s_fs_info; - dprintk(DEBUG_VFS, " %p\n", s); + P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); v9fs_dentry_release(s->s_root); /* clunk root */ @@ -219,7 +202,7 @@ static void v9fs_kill_super(struct super_block *s) v9fs_session_close(v9ses); kfree(v9ses); - dprintk(DEBUG_VFS, "exiting kill_super\n"); + P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); } /** diff --git a/fs/Kconfig b/fs/Kconfig index 0fa0c1193e81..94b9d861bf9b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -2048,7 +2048,7 @@ config AFS_DEBUG config 9P_FS tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" - depends on INET && EXPERIMENTAL + depends on INET && NET_9P && EXPERIMENTAL help If you say Y here, you will get experimental support for Plan 9 resource sharing via the 9P2000 protocol. diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h new file mode 100644 index 000000000000..88884d39f28f --- /dev/null +++ b/include/net/9p/9p.h @@ -0,0 +1,417 @@ +/* + * include/net/9p/9p.h + * + * 9P protocol definitions. + * + * Copyright (C) 2005 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#ifndef NET_9P_H +#define NET_9P_H + +#ifdef CONFIG_NET_9P_DEBUG + +#define P9_DEBUG_ERROR (1<<0) +#define P9_DEBUG_9P (1<<2) +#define P9_DEBUG_VFS (1<<3) +#define P9_DEBUG_CONV (1<<4) +#define P9_DEBUG_MUX (1<<5) +#define P9_DEBUG_TRANS (1<<6) +#define P9_DEBUG_SLABS (1<<7) +#define P9_DEBUG_FCALL (1<<8) + +extern unsigned int p9_debug_level; + +#define P9_DPRINTK(level, format, arg...) \ +do { \ + if ((p9_debug_level & level) == level) \ + printk(KERN_NOTICE "-- %s (%d): " \ + format , __FUNCTION__, current->pid , ## arg); \ +} while (0) + +#define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR, \ + "%s: %.*s\n", s, fcall?fcall->params.rerror.error.len:0, \ + fcall?fcall->params.rerror.error.str:""); + +#else +#define P9_DPRINTK(level, format, arg...) do { } while (0) +#define PRINT_FCALL_ERROR(s, fcall) do { } while (0) +#endif + +#define P9_EPRINTK(level, format, arg...) \ +do { \ + printk(level "9p: %s (%d): " \ + format , __FUNCTION__, current->pid , ## arg); \ +} while (0) + + +/* Message Types */ +enum { + P9_TVERSION = 100, + P9_RVERSION, + P9_TAUTH = 102, + P9_RAUTH, + P9_TATTACH = 104, + P9_RATTACH, + P9_TERROR = 106, + P9_RERROR, + P9_TFLUSH = 108, + P9_RFLUSH, + P9_TWALK = 110, + P9_RWALK, + P9_TOPEN = 112, + P9_ROPEN, + P9_TCREATE = 114, + P9_RCREATE, + P9_TREAD = 116, + P9_RREAD, + P9_TWRITE = 118, + P9_RWRITE, + P9_TCLUNK = 120, + P9_RCLUNK, + P9_TREMOVE = 122, + P9_RREMOVE, + P9_TSTAT = 124, + P9_RSTAT, + P9_TWSTAT = 126, + P9_RWSTAT, +}; + +/* open modes */ +enum { + P9_OREAD = 0x00, + P9_OWRITE = 0x01, + P9_ORDWR = 0x02, + P9_OEXEC = 0x03, + P9_OEXCL = 0x04, + P9_OTRUNC = 0x10, + P9_OREXEC = 0x20, + P9_ORCLOSE = 0x40, + P9_OAPPEND = 0x80, +}; + +/* permissions */ +enum { + P9_DMDIR = 0x80000000, + P9_DMAPPEND = 0x40000000, + P9_DMEXCL = 0x20000000, + P9_DMMOUNT = 0x10000000, + P9_DMAUTH = 0x08000000, + P9_DMTMP = 0x04000000, + P9_DMSYMLINK = 0x02000000, + P9_DMLINK = 0x01000000, + /* 9P2000.u extensions */ + P9_DMDEVICE = 0x00800000, + P9_DMNAMEDPIPE = 0x00200000, + P9_DMSOCKET = 0x00100000, + P9_DMSETUID = 0x00080000, + P9_DMSETGID = 0x00040000, +}; + +/* qid.types */ +enum { + P9_QTDIR = 0x80, + P9_QTAPPEND = 0x40, + P9_QTEXCL = 0x20, + P9_QTMOUNT = 0x10, + P9_QTAUTH = 0x08, + P9_QTTMP = 0x04, + P9_QTSYMLINK = 0x02, + P9_QTLINK = 0x01, + P9_QTFILE = 0x00, +}; + +#define P9_NOTAG (u16)(~0) +#define P9_NOFID (u32)(~0) +#define P9_MAXWELEM 16 + +/* ample room for Twrite/Rread header */ +#define P9_IOHDRSZ 24 + +struct p9_str { + u16 len; + char *str; +}; + +/* qids are the unique ID for a file (like an inode */ +struct p9_qid { + u8 type; + u32 version; + u64 path; +}; + +/* Plan 9 file metadata (stat) structure */ +struct p9_stat { + u16 size; + u16 type; + u32 dev; + struct p9_qid qid; + u32 mode; + u32 atime; + u32 mtime; + u64 length; + struct p9_str name; + struct p9_str uid; + struct p9_str gid; + struct p9_str muid; + struct p9_str extension; /* 9p2000.u extensions */ + u32 n_uid; /* 9p2000.u extensions */ + u32 n_gid; /* 9p2000.u extensions */ + u32 n_muid; /* 9p2000.u extensions */ +}; + +/* file metadata (stat) structure used to create Twstat message + The is similar to p9_stat, but the strings don't point to + the same memory block and should be freed separately +*/ +struct p9_wstat { + u16 size; + u16 type; + u32 dev; + struct p9_qid qid; + u32 mode; + u32 atime; + u32 mtime; + u64 length; + char *name; + char *uid; + char *gid; + char *muid; + char *extension; /* 9p2000.u extensions */ + u32 n_uid; /* 9p2000.u extensions */ + u32 n_gid; /* 9p2000.u extensions */ + u32 n_muid; /* 9p2000.u extensions */ +}; + +/* Structures for Protocol Operations */ +struct p9_tversion { + u32 msize; + struct p9_str version; +}; + +struct p9_rversion { + u32 msize; + struct p9_str version; +}; + +struct p9_tauth { + u32 afid; + struct p9_str uname; + struct p9_str aname; +}; + +struct p9_rauth { + struct p9_qid qid; +}; + +struct p9_rerror { + struct p9_str error; + u32 errno; /* 9p2000.u extension */ +}; + +struct p9_tflush { + u16 oldtag; +}; + +struct p9_rflush { +}; + +struct p9_tattach { + u32 fid; + u32 afid; + struct p9_str uname; + struct p9_str aname; +}; + +struct p9_rattach { + struct p9_qid qid; +}; + +struct p9_twalk { + u32 fid; + u32 newfid; + u16 nwname; + struct p9_str wnames[16]; +}; + +struct p9_rwalk { + u16 nwqid; + struct p9_qid wqids[16]; +}; + +struct p9_topen { + u32 fid; + u8 mode; +}; + +struct p9_ropen { + struct p9_qid qid; + u32 iounit; +}; + +struct p9_tcreate { + u32 fid; + struct p9_str name; + u32 perm; + u8 mode; + struct p9_str extension; +}; + +struct p9_rcreate { + struct p9_qid qid; + u32 iounit; +}; + +struct p9_tread { + u32 fid; + u64 offset; + u32 count; +}; + +struct p9_rread { + u32 count; + u8 *data; +}; + +struct p9_twrite { + u32 fid; + u64 offset; + u32 count; + u8 *data; +}; + +struct p9_rwrite { + u32 count; +}; + +struct p9_tclunk { + u32 fid; +}; + +struct p9_rclunk { +}; + +struct p9_tremove { + u32 fid; +}; + +struct p9_rremove { +}; + +struct p9_tstat { + u32 fid; +}; + +struct p9_rstat { + struct p9_stat stat; +}; + +struct p9_twstat { + u32 fid; + struct p9_stat stat; +}; + +struct p9_rwstat { +}; + +/* + * fcall is the primary packet structure + * + */ + +struct p9_fcall { + u32 size; + u8 id; + u16 tag; + void *sdata; + + union { + struct p9_tversion tversion; + struct p9_rversion rversion; + struct p9_tauth tauth; + struct p9_rauth rauth; + struct p9_rerror rerror; + struct p9_tflush tflush; + struct p9_rflush rflush; + struct p9_tattach tattach; + struct p9_rattach rattach; + struct p9_twalk twalk; + struct p9_rwalk rwalk; + struct p9_topen topen; + struct p9_ropen ropen; + struct p9_tcreate tcreate; + struct p9_rcreate rcreate; + struct p9_tread tread; + struct p9_rread rread; + struct p9_twrite twrite; + struct p9_rwrite rwrite; + struct p9_tclunk tclunk; + struct p9_rclunk rclunk; + struct p9_tremove tremove; + struct p9_rremove rremove; + struct p9_tstat tstat; + struct p9_rstat rstat; + struct p9_twstat twstat; + struct p9_rwstat rwstat; + } params; +}; + +struct p9_idpool; + +int p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat, + int dotu); +int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu); +void p9_set_tag(struct p9_fcall *fc, u16 tag); +struct p9_fcall *p9_create_tversion(u32 msize, char *version); +struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname, + char *aname); +struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname); +struct p9_fcall *p9_create_tflush(u16 oldtag); +struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, + char **wnames); +struct p9_fcall *p9_create_topen(u32 fid, u8 mode); +struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, + char *extension, int dotu); +struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count); +struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, + const char *data); +struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, + const char __user *data); +struct p9_fcall *p9_create_tclunk(u32 fid); +struct p9_fcall *p9_create_tremove(u32 fid); +struct p9_fcall *p9_create_tstat(u32 fid); +struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, + int dotu); + +int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int dotu); +int p9_errstr2errno(char *errstr, int len); + +struct p9_idpool *p9_idpool_create(void); +void p9_idpool_destroy(struct p9_idpool *); +int p9_idpool_get(struct p9_idpool *p); +void p9_idpool_put(int id, struct p9_idpool *p); +int p9_idpool_check(int id, struct p9_idpool *p); + +int p9_error_init(void); +int p9_errstr2errno(char *, int); +int __init p9_sysctl_register(void); +void __exit p9_sysctl_unregister(void); +#endif /* NET_9P_H */ diff --git a/include/net/9p/client.h b/include/net/9p/client.h new file mode 100644 index 000000000000..d65ed7c69063 --- /dev/null +++ b/include/net/9p/client.h @@ -0,0 +1,80 @@ +/* + * include/net/9p/client.h + * + * 9P Client Definitions + * + * Copyright (C) 2007 by Latchesar Ionkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#ifndef NET_9P_CLIENT_H +#define NET_9P_CLIENT_H + +struct p9_client { + spinlock_t lock; /* protect client structure */ + int msize; + unsigned char dotu; + struct p9_transport *trans; + struct p9_conn *conn; + + struct p9_idpool *fidpool; + struct list_head fidlist; +}; + +struct p9_fid { + struct p9_client *clnt; + u32 fid; + int mode; + struct p9_qid qid; + u32 iounit; + uid_t uid; + void *aux; + + int rdir_fpos; + int rdir_pos; + struct p9_fcall *rdir_fcall; + struct list_head flist; + struct list_head dlist; /* list of all fids attached to a dentry */ +}; + +struct p9_client *p9_client_create(struct p9_transport *trans, int msize, + int dotu); +void p9_client_destroy(struct p9_client *clnt); +void p9_client_disconnect(struct p9_client *clnt); +struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, + char *uname, char *aname); +struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname); +struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, + int clone); +int p9_client_open(struct p9_fid *fid, int mode); +int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, + char *extension); +int p9_client_clunk(struct p9_fid *fid); +int p9_client_remove(struct p9_fid *fid); +int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count); +int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count); +int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count); +int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, + u32 count); +int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, + u32 count); +struct p9_stat *p9_client_stat(struct p9_fid *fid); +int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); +struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset); + +#endif /* NET_9P_CLIENT_H */ diff --git a/include/net/9p/conn.h b/include/net/9p/conn.h new file mode 100644 index 000000000000..583b6a2cb3df --- /dev/null +++ b/include/net/9p/conn.h @@ -0,0 +1,57 @@ +/* + * include/net/9p/conn.h + * + * Connection Definitions + * + * Copyright (C) 2005 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#ifndef NET_9P_CONN_H +#define NET_9P_CONN_H + +#undef P9_NONBLOCK + +struct p9_conn; +struct p9_req; + +/** + * p9_mux_req_callback - callback function that is called when the + * response of a request is received. The callback is called from + * a workqueue and shouldn't block. + * + * @req - request + * @a - the pointer that was specified when the request was send to be + * passed to the callback + */ +typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); + +struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, + unsigned char *dotu); +void p9_conn_destroy(struct p9_conn *); +int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc); + +#ifdef P9_NONBLOCK +int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, + p9_conn_req_callback cb, void *a); +#endif /* P9_NONBLOCK */ + +void p9_conn_cancel(struct p9_conn *m, int err); + +#endif /* NET_9P_CONN_H */ diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h new file mode 100644 index 000000000000..462d42279fb0 --- /dev/null +++ b/include/net/9p/transport.h @@ -0,0 +1,49 @@ +/* + * include/net/9p/transport.h + * + * Transport Definition + * + * Copyright (C) 2005 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#ifndef NET_9P_TRANSPORT_H +#define NET_9P_TRANSPORT_H + +enum p9_transport_status { + Connected, + Disconnected, + Hung, +}; + +struct p9_transport { + enum p9_transport_status status; + void *priv; + + int (*write) (struct p9_transport *, void *, int); + int (*read) (struct p9_transport *, void *, int); + void (*close) (struct p9_transport *); + unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *); +}; + +struct p9_transport *p9_trans_create_tcp(const char *addr, int port); +struct p9_transport *p9_trans_create_unix(const char *addr); +struct p9_transport *p9_trans_create_fd(int rfd, int wfd); + +#endif /* NET_9P_TRANSPORT_H */ diff --git a/net/9p/Kconfig b/net/9p/Kconfig new file mode 100644 index 000000000000..66821cd64a76 --- /dev/null +++ b/net/9p/Kconfig @@ -0,0 +1,21 @@ +# +# 9P protocol configuration +# + +menuconfig NET_9P + depends on NET && EXPERIMENTAL + tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" + help + If you say Y here, you will get experimental support for + Plan 9 resource sharing via the 9P2000 protocol. + + See for more information. + + If unsure, say N. + +config NET_9P_DEBUG + bool "Debug information" + depends on NET_9P + help + Say Y if you want the 9P subsistem to log debug information. + diff --git a/net/9p/Makefile b/net/9p/Makefile new file mode 100644 index 000000000000..ac46cb91900d --- /dev/null +++ b/net/9p/Makefile @@ -0,0 +1,13 @@ +obj-$(CONFIG_NET_9P) := 9p.o + +9p-objs := \ + mod.o \ + trans_fd.o \ + mux.o \ + client.o \ + conv.o \ + error.o \ + fcprint.o \ + util.o \ + +9p-$(CONFIG_SYSCTL) += sysctl.o diff --git a/net/9p/client.c b/net/9p/client.c new file mode 100644 index 000000000000..bb2b8a3af196 --- /dev/null +++ b/net/9p/client.c @@ -0,0 +1,965 @@ +/* + * net/9p/clnt.c + * + * 9P Client + * + * Copyright (C) 2007 by Latchesar Ionkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct p9_fid *p9_fid_create(struct p9_client *clnt); +static void p9_fid_destroy(struct p9_fid *fid); +static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); + +struct p9_client *p9_client_create(struct p9_transport *trans, int msize, + int dotu) +{ + int err, n; + struct p9_client *clnt; + struct p9_fcall *tc, *rc; + struct p9_str *version; + + err = 0; + tc = NULL; + rc = NULL; + clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); + if (!clnt) + return ERR_PTR(-ENOMEM); + + P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", + clnt, trans, msize, dotu); + spin_lock_init(&clnt->lock); + clnt->trans = trans; + clnt->msize = msize; + clnt->dotu = dotu; + INIT_LIST_HEAD(&clnt->fidlist); + clnt->fidpool = p9_idpool_create(); + if (!clnt->fidpool) { + err = PTR_ERR(clnt->fidpool); + clnt->fidpool = NULL; + goto error; + } + + clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); + if (IS_ERR(clnt->conn)) { + err = PTR_ERR(clnt->conn); + clnt->conn = NULL; + goto error; + } + + tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + version = &rc->params.rversion.version; + if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) + clnt->dotu = 1; + else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) + clnt->dotu = 0; + else { + err = -EREMOTEIO; + goto error; + } + + n = rc->params.rversion.msize; + if (n < clnt->msize) + clnt->msize = n; + + kfree(tc); + kfree(rc); + return clnt; + +error: + kfree(tc); + kfree(rc); + p9_client_destroy(clnt); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_create); + +void p9_client_destroy(struct p9_client *clnt) +{ + struct p9_fid *fid, *fidptr; + + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); + if (clnt->conn) { + p9_conn_destroy(clnt->conn); + clnt->conn = NULL; + } + + if (clnt->trans) { + clnt->trans->close(clnt->trans); + kfree(clnt->trans); + clnt->trans = NULL; + } + + if (clnt->fidpool) + p9_idpool_destroy(clnt->fidpool); + + list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) + p9_fid_destroy(fid); + + kfree(clnt); +} +EXPORT_SYMBOL(p9_client_destroy); + +void p9_client_disconnect(struct p9_client *clnt) +{ + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); + clnt->trans->status = Disconnected; + p9_conn_cancel(clnt->conn, -EIO); +} +EXPORT_SYMBOL(p9_client_disconnect); + +struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, + char *uname, char *aname) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_fid *fid; + + P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", + clnt, afid?afid->fid:-1, uname, aname); + err = 0; + tc = NULL; + rc = NULL; + + fid = p9_fid_create(clnt); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; + goto error; + } + + tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); + kfree(tc); + kfree(rc); + return fid; + +error: + kfree(tc); + kfree(rc); + if (fid) + p9_fid_destroy(fid); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_attach); + +struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_fid *fid; + + P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, + aname); + err = 0; + tc = NULL; + rc = NULL; + + fid = p9_fid_create(clnt); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; + goto error; + } + + tc = p9_create_tauth(fid->fid, uname, aname); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); + kfree(tc); + kfree(rc); + return fid; + +error: + kfree(tc); + kfree(rc); + if (fid) + p9_fid_destroy(fid); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_auth); + +struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, + int clone) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + struct p9_fid *fid; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n", + oldfid->fid, nwname, wnames?wnames[0]:NULL); + err = 0; + tc = NULL; + rc = NULL; + clnt = oldfid->clnt; + if (clone) { + fid = p9_fid_create(clnt); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + fid = NULL; + goto error; + } + + fid->uid = oldfid->uid; + } else + fid = oldfid; + + tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) { + if (rc && rc->id == P9_RWALK) + goto clunk_fid; + else + goto error; + } + + if (rc->params.rwalk.nwqid != nwname) { + err = -ENOENT; + goto clunk_fid; + } + + if (nwname) + memmove(&fid->qid, + &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1], + sizeof(struct p9_qid)); + else + fid->qid = oldfid->qid; + + kfree(tc); + kfree(rc); + return fid; + +clunk_fid: + kfree(tc); + kfree(rc); + rc = NULL; + tc = p9_create_tclunk(fid->fid); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + p9_conn_rpc(clnt->conn, tc, &rc); + +error: + kfree(tc); + kfree(rc); + if (fid && (fid != oldfid)) + p9_fid_destroy(fid); + + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_walk); + +int p9_client_open(struct p9_fid *fid, int mode) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + + if (fid->mode != -1) + return -EINVAL; + + tc = p9_create_topen(fid->fid, mode); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto done; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto done; + + fid->mode = mode; + fid->iounit = rc->params.ropen.iounit; + +done: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_open); + +int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, + char *extension) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, + name, perm, mode); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + + if (fid->mode != -1) + return -EINVAL; + + tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, + clnt->dotu); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto done; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto done; + + fid->mode = mode; + fid->iounit = rc->params.ropen.iounit; + +done: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_fcreate); + +int p9_client_clunk(struct p9_fid *fid) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + + tc = p9_create_tclunk(fid->fid); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto done; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto done; + + p9_fid_destroy(fid); + +done: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_clunk); + +int p9_client_remove(struct p9_fid *fid) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + + tc = p9_create_tremove(fid->fid); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto done; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto done; + + p9_fid_destroy(fid); + +done: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_remove); + +int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) +{ + int err, n, rsize, total; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, + (long long unsigned) offset, count); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + total = 0; + + rsize = fid->iounit; + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) + rsize = clnt->msize - P9_IOHDRSZ; + + do { + if (count < rsize) + rsize = count; + + tc = p9_create_tread(fid->fid, offset, rsize); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + n = rc->params.rread.count; + if (n > count) + n = count; + + memmove(data, rc->params.rread.data, n); + count -= n; + data += n; + offset += n; + total += n; + kfree(tc); + tc = NULL; + kfree(rc); + rc = NULL; + } while (count > 0 && n == rsize); + + return total; + +error: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_read); + +int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count) +{ + int err, n, rsize, total; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, + (long long unsigned) offset, count); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + total = 0; + + rsize = fid->iounit; + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) + rsize = clnt->msize - P9_IOHDRSZ; + + do { + if (count < rsize) + rsize = count; + + tc = p9_create_twrite(fid->fid, offset, rsize, data); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + n = rc->params.rread.count; + count -= n; + data += n; + offset += n; + total += n; + kfree(tc); + tc = NULL; + kfree(rc); + rc = NULL; + } while (count > 0); + + return total; + +error: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_write); + +int +p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count) +{ + int err, n, rsize, total; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, + (long long unsigned) offset, count); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + total = 0; + + rsize = fid->iounit; + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) + rsize = clnt->msize - P9_IOHDRSZ; + + do { + if (count < rsize) + rsize = count; + + tc = p9_create_tread(fid->fid, offset, rsize); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + n = rc->params.rread.count; + if (n > count) + n = count; + + err = copy_to_user(data, rc->params.rread.data, n); + if (err) { + err = -EFAULT; + goto error; + } + + count -= n; + data += n; + offset += n; + total += n; + kfree(tc); + tc = NULL; + kfree(rc); + rc = NULL; + } while (count > 0 && n == rsize); + + return total; + +error: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_uread); + +int +p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, + u32 count) +{ + int err, n, rsize, total; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, + (long long unsigned) offset, count); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + total = 0; + + rsize = fid->iounit; + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) + rsize = clnt->msize - P9_IOHDRSZ; + + do { + if (count < rsize) + rsize = count; + + tc = p9_create_twrite_u(fid->fid, offset, rsize, data); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + n = rc->params.rread.count; + count -= n; + data += n; + offset += n; + total += n; + kfree(tc); + tc = NULL; + kfree(rc); + rc = NULL; + } while (count > 0); + + return total; + +error: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_uwrite); + +int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count) +{ + int n, total; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, + (long long unsigned) offset, count); + n = 0; + total = 0; + while (count) { + n = p9_client_read(fid, data, offset, count); + if (n <= 0) + break; + + data += n; + offset += n; + count -= n; + total += n; + } + + if (n < 0) + total = n; + + return total; +} +EXPORT_SYMBOL(p9_client_readn); + +struct p9_stat *p9_client_stat(struct p9_fid *fid) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + struct p9_stat *ret; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); + err = 0; + tc = NULL; + rc = NULL; + ret = NULL; + clnt = fid->clnt; + + tc = p9_create_tstat(fid->fid); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu); + if (IS_ERR(ret)) { + err = PTR_ERR(ret); + ret = NULL; + goto error; + } + + kfree(tc); + kfree(rc); + return ret; + +error: + kfree(tc); + kfree(rc); + kfree(ret); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_stat); + +int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) +{ + int err; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); + err = 0; + tc = NULL; + rc = NULL; + clnt = fid->clnt; + + tc = p9_create_twstat(fid->fid, wst, clnt->dotu); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto done; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + +done: + kfree(tc); + kfree(rc); + return err; +} +EXPORT_SYMBOL(p9_client_wstat); + +struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset) +{ + int err, n, m; + struct p9_fcall *tc, *rc; + struct p9_client *clnt; + struct p9_stat st, *ret; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid, + (long long unsigned) offset); + err = 0; + tc = NULL; + rc = NULL; + ret = NULL; + clnt = fid->clnt; + + /* if the offset is below or above the current response, free it */ + if (offset < fid->rdir_fpos || (fid->rdir_fcall && + offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) { + fid->rdir_pos = 0; + if (fid->rdir_fcall) + fid->rdir_fpos += fid->rdir_fcall->params.rread.count; + + kfree(fid->rdir_fcall); + fid->rdir_fcall = NULL; + if (offset < fid->rdir_fpos) + fid->rdir_fpos = 0; + } + + if (!fid->rdir_fcall) { + n = fid->iounit; + if (!n || n > clnt->msize-P9_IOHDRSZ) + n = clnt->msize - P9_IOHDRSZ; + + while (1) { + if (fid->rdir_fcall) { + fid->rdir_fpos += + fid->rdir_fcall->params.rread.count; + kfree(fid->rdir_fcall); + fid->rdir_fcall = NULL; + } + + tc = p9_create_tread(fid->fid, fid->rdir_fpos, n); + if (IS_ERR(tc)) { + err = PTR_ERR(tc); + tc = NULL; + goto error; + } + + err = p9_conn_rpc(clnt->conn, tc, &rc); + if (err) + goto error; + + n = rc->params.rread.count; + if (n == 0) + goto done; + + fid->rdir_fcall = rc; + rc = NULL; + if (offset >= fid->rdir_fpos && + offset < fid->rdir_fpos+n) + break; + } + + fid->rdir_pos = 0; + } + + m = offset - fid->rdir_fpos; + if (m < 0) + goto done; + + n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m, + fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu); + + if (!n) { + err = -EIO; + goto error; + } + + fid->rdir_pos += n; + st.size = n; + ret = p9_clone_stat(&st, clnt->dotu); + if (IS_ERR(ret)) { + err = PTR_ERR(ret); + ret = NULL; + goto error; + } + +done: + kfree(tc); + kfree(rc); + return ret; + +error: + kfree(tc); + kfree(rc); + kfree(ret); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_client_dirread); + +static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) +{ + int n; + char *p; + struct p9_stat *ret; + + n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len + + st->muid.len; + + if (dotu) + n += st->extension.len; + + ret = kmalloc(n, GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + memmove(ret, st, sizeof(struct p9_stat)); + p = ((char *) ret) + sizeof(struct p9_stat); + memmove(p, st->name.str, st->name.len); + p += st->name.len; + memmove(p, st->uid.str, st->uid.len); + p += st->uid.len; + memmove(p, st->gid.str, st->gid.len); + p += st->gid.len; + memmove(p, st->muid.str, st->muid.len); + p += st->muid.len; + + if (dotu) { + memmove(p, st->extension.str, st->extension.len); + p += st->extension.len; + } + + return ret; +} + +static struct p9_fid *p9_fid_create(struct p9_client *clnt) +{ + int err; + struct p9_fid *fid; + + P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); + fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); + if (!fid) + return ERR_PTR(-ENOMEM); + + fid->fid = p9_idpool_get(clnt->fidpool); + if (fid->fid < 0) { + err = -ENOSPC; + goto error; + } + + memset(&fid->qid, 0, sizeof(struct p9_qid)); + fid->mode = -1; + fid->rdir_fpos = 0; + fid->rdir_pos = 0; + fid->rdir_fcall = NULL; + fid->uid = current->fsuid; + fid->clnt = clnt; + fid->aux = NULL; + + spin_lock(&clnt->lock); + list_add(&fid->flist, &clnt->fidlist); + spin_unlock(&clnt->lock); + + return fid; + +error: + kfree(fid); + return ERR_PTR(err); +} + +static void p9_fid_destroy(struct p9_fid *fid) +{ + struct p9_client *clnt; + + P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); + clnt = fid->clnt; + p9_idpool_put(fid->fid, clnt->fidpool); + spin_lock(&clnt->lock); + list_del(&fid->flist); + spin_unlock(&clnt->lock); + kfree(fid->rdir_fcall); + kfree(fid); +} diff --git a/net/9p/conv.c b/net/9p/conv.c new file mode 100644 index 000000000000..37451178e761 --- /dev/null +++ b/net/9p/conv.c @@ -0,0 +1,903 @@ +/* + * net/9p/conv.c + * + * 9P protocol conversion functions + * + * Copyright (C) 2004, 2005 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Buffer to help with string parsing + */ +struct cbuf { + unsigned char *sp; + unsigned char *p; + unsigned char *ep; +}; + +static inline void buf_init(struct cbuf *buf, void *data, int datalen) +{ + buf->sp = buf->p = data; + buf->ep = data + datalen; +} + +static inline int buf_check_overflow(struct cbuf *buf) +{ + return buf->p > buf->ep; +} + +static int buf_check_size(struct cbuf *buf, int len) +{ + if (buf->p + len > buf->ep) { + if (buf->p < buf->ep) { + P9_EPRINTK(KERN_ERR, + "buffer overflow: want %d has %d\n", len, + (int)(buf->ep - buf->p)); + dump_stack(); + buf->p = buf->ep + 1; + } + + return 0; + } + + return 1; +} + +static void *buf_alloc(struct cbuf *buf, int len) +{ + void *ret = NULL; + + if (buf_check_size(buf, len)) { + ret = buf->p; + buf->p += len; + } + + return ret; +} + +static void buf_put_int8(struct cbuf *buf, u8 val) +{ + if (buf_check_size(buf, 1)) { + buf->p[0] = val; + buf->p++; + } +} + +static void buf_put_int16(struct cbuf *buf, u16 val) +{ + if (buf_check_size(buf, 2)) { + *(__le16 *) buf->p = cpu_to_le16(val); + buf->p += 2; + } +} + +static void buf_put_int32(struct cbuf *buf, u32 val) +{ + if (buf_check_size(buf, 4)) { + *(__le32 *)buf->p = cpu_to_le32(val); + buf->p += 4; + } +} + +static void buf_put_int64(struct cbuf *buf, u64 val) +{ + if (buf_check_size(buf, 8)) { + *(__le64 *)buf->p = cpu_to_le64(val); + buf->p += 8; + } +} + +static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) +{ + char *ret; + + ret = NULL; + if (buf_check_size(buf, slen + 2)) { + buf_put_int16(buf, slen); + ret = buf->p; + memcpy(buf->p, s, slen); + buf->p += slen; + } + + return ret; +} + +static inline void buf_put_string(struct cbuf *buf, const char *s) +{ + buf_put_stringn(buf, s, strlen(s)); +} + +static u8 buf_get_int8(struct cbuf *buf) +{ + u8 ret = 0; + + if (buf_check_size(buf, 1)) { + ret = buf->p[0]; + buf->p++; + } + + return ret; +} + +static u16 buf_get_int16(struct cbuf *buf) +{ + u16 ret = 0; + + if (buf_check_size(buf, 2)) { + ret = le16_to_cpu(*(__le16 *)buf->p); + buf->p += 2; + } + + return ret; +} + +static u32 buf_get_int32(struct cbuf *buf) +{ + u32 ret = 0; + + if (buf_check_size(buf, 4)) { + ret = le32_to_cpu(*(__le32 *)buf->p); + buf->p += 4; + } + + return ret; +} + +static u64 buf_get_int64(struct cbuf *buf) +{ + u64 ret = 0; + + if (buf_check_size(buf, 8)) { + ret = le64_to_cpu(*(__le64 *)buf->p); + buf->p += 8; + } + + return ret; +} + +static void buf_get_str(struct cbuf *buf, struct p9_str *vstr) +{ + vstr->len = buf_get_int16(buf); + if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { + vstr->str = buf->p; + buf->p += vstr->len; + } else { + vstr->len = 0; + vstr->str = NULL; + } +} + +static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid) +{ + qid->type = buf_get_int8(bufp); + qid->version = buf_get_int32(bufp); + qid->path = buf_get_int64(bufp); +} + +/** + * p9_size_wstat - calculate the size of a variable length stat struct + * @stat: metadata (stat) structure + * @dotu: non-zero if 9P2000.u + * + */ + +static int p9_size_wstat(struct p9_wstat *wstat, int dotu) +{ + int size = 0; + + if (wstat == NULL) { + P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n"); + return 0; + } + + size = /* 2 + *//* size[2] */ + 2 + /* type[2] */ + 4 + /* dev[4] */ + 1 + /* qid.type[1] */ + 4 + /* qid.vers[4] */ + 8 + /* qid.path[8] */ + 4 + /* mode[4] */ + 4 + /* atime[4] */ + 4 + /* mtime[4] */ + 8 + /* length[8] */ + 8; /* minimum sum of string lengths */ + + if (wstat->name) + size += strlen(wstat->name); + if (wstat->uid) + size += strlen(wstat->uid); + if (wstat->gid) + size += strlen(wstat->gid); + if (wstat->muid) + size += strlen(wstat->muid); + + if (dotu) { + size += 4 + /* n_uid[4] */ + 4 + /* n_gid[4] */ + 4 + /* n_muid[4] */ + 2; /* string length of extension[4] */ + if (wstat->extension) + size += strlen(wstat->extension); + } + + return size; +} + +/** + * buf_get_stat - safely decode a recieved metadata (stat) structure + * @bufp: buffer to deserialize + * @stat: metadata (stat) structure + * @dotu: non-zero if 9P2000.u + * + */ + +static void +buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu) +{ + stat->size = buf_get_int16(bufp); + stat->type = buf_get_int16(bufp); + stat->dev = buf_get_int32(bufp); + stat->qid.type = buf_get_int8(bufp); + stat->qid.version = buf_get_int32(bufp); + stat->qid.path = buf_get_int64(bufp); + stat->mode = buf_get_int32(bufp); + stat->atime = buf_get_int32(bufp); + stat->mtime = buf_get_int32(bufp); + stat->length = buf_get_int64(bufp); + buf_get_str(bufp, &stat->name); + buf_get_str(bufp, &stat->uid); + buf_get_str(bufp, &stat->gid); + buf_get_str(bufp, &stat->muid); + + if (dotu) { + buf_get_str(bufp, &stat->extension); + stat->n_uid = buf_get_int32(bufp); + stat->n_gid = buf_get_int32(bufp); + stat->n_muid = buf_get_int32(bufp); + } +} + +/** + * p9_deserialize_stat - decode a received metadata structure + * @buf: buffer to deserialize + * @buflen: length of received buffer + * @stat: metadata structure to decode into + * @dotu: non-zero if 9P2000.u + * + * Note: stat will point to the buf region. + */ + +int +p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat, + int dotu) +{ + struct cbuf buffer; + struct cbuf *bufp = &buffer; + unsigned char *p; + + buf_init(bufp, buf, buflen); + p = bufp->p; + buf_get_stat(bufp, stat, dotu); + + if (buf_check_overflow(bufp)) + return 0; + else + return bufp->p - p; +} +EXPORT_SYMBOL(p9_deserialize_stat); + +/** + * deserialize_fcall - unmarshal a response + * @buf: recieved buffer + * @buflen: length of received buffer + * @rcall: fcall structure to populate + * @rcalllen: length of fcall structure to populate + * @dotu: non-zero if 9P2000.u + * + */ + +int +p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall, + int dotu) +{ + + struct cbuf buffer; + struct cbuf *bufp = &buffer; + int i = 0; + + buf_init(bufp, buf, buflen); + + rcall->size = buf_get_int32(bufp); + rcall->id = buf_get_int8(bufp); + rcall->tag = buf_get_int16(bufp); + + P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, + rcall->id, rcall->tag); + + switch (rcall->id) { + default: + P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id); + return -EPROTO; + case P9_RVERSION: + rcall->params.rversion.msize = buf_get_int32(bufp); + buf_get_str(bufp, &rcall->params.rversion.version); + break; + case P9_RFLUSH: + break; + case P9_RATTACH: + rcall->params.rattach.qid.type = buf_get_int8(bufp); + rcall->params.rattach.qid.version = buf_get_int32(bufp); + rcall->params.rattach.qid.path = buf_get_int64(bufp); + break; + case P9_RWALK: + rcall->params.rwalk.nwqid = buf_get_int16(bufp); + if (rcall->params.rwalk.nwqid > P9_MAXWELEM) { + P9_EPRINTK(KERN_ERR, + "Rwalk with more than %d qids: %d\n", + P9_MAXWELEM, rcall->params.rwalk.nwqid); + return -EPROTO; + } + + for (i = 0; i < rcall->params.rwalk.nwqid; i++) + buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); + break; + case P9_ROPEN: + buf_get_qid(bufp, &rcall->params.ropen.qid); + rcall->params.ropen.iounit = buf_get_int32(bufp); + break; + case P9_RCREATE: + buf_get_qid(bufp, &rcall->params.rcreate.qid); + rcall->params.rcreate.iounit = buf_get_int32(bufp); + break; + case P9_RREAD: + rcall->params.rread.count = buf_get_int32(bufp); + rcall->params.rread.data = bufp->p; + buf_check_size(bufp, rcall->params.rread.count); + break; + case P9_RWRITE: + rcall->params.rwrite.count = buf_get_int32(bufp); + break; + case P9_RCLUNK: + break; + case P9_RREMOVE: + break; + case P9_RSTAT: + buf_get_int16(bufp); + buf_get_stat(bufp, &rcall->params.rstat.stat, dotu); + break; + case P9_RWSTAT: + break; + case P9_RERROR: + buf_get_str(bufp, &rcall->params.rerror.error); + if (dotu) + rcall->params.rerror.errno = buf_get_int16(bufp); + break; + } + + if (buf_check_overflow(bufp)) { + P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n"); + return -EIO; + } + + return bufp->p - bufp->sp; +} +EXPORT_SYMBOL(p9_deserialize_fcall); + +static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p) +{ + *p = val; + buf_put_int8(bufp, val); +} + +static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p) +{ + *p = val; + buf_put_int16(bufp, val); +} + +static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p) +{ + *p = val; + buf_put_int32(bufp, val); +} + +static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p) +{ + *p = val; + buf_put_int64(bufp, val); +} + +static void +p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str) +{ + int len; + char *s; + + if (data) + len = strlen(data); + else + len = 0; + + s = buf_put_stringn(bufp, data, len); + if (str) { + str->len = len; + str->str = s; + } +} + +static int +p9_put_data(struct cbuf *bufp, const char *data, int count, + unsigned char **pdata) +{ + *pdata = buf_alloc(bufp, count); + memmove(*pdata, data, count); + return count; +} + +static int +p9_put_user_data(struct cbuf *bufp, const char __user *data, int count, + unsigned char **pdata) +{ + *pdata = buf_alloc(bufp, count); + return copy_from_user(*pdata, data, count); +} + +static void +p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat, + struct p9_stat *stat, int statsz, int dotu) +{ + p9_put_int16(bufp, statsz, &stat->size); + p9_put_int16(bufp, wstat->type, &stat->type); + p9_put_int32(bufp, wstat->dev, &stat->dev); + p9_put_int8(bufp, wstat->qid.type, &stat->qid.type); + p9_put_int32(bufp, wstat->qid.version, &stat->qid.version); + p9_put_int64(bufp, wstat->qid.path, &stat->qid.path); + p9_put_int32(bufp, wstat->mode, &stat->mode); + p9_put_int32(bufp, wstat->atime, &stat->atime); + p9_put_int32(bufp, wstat->mtime, &stat->mtime); + p9_put_int64(bufp, wstat->length, &stat->length); + + p9_put_str(bufp, wstat->name, &stat->name); + p9_put_str(bufp, wstat->uid, &stat->uid); + p9_put_str(bufp, wstat->gid, &stat->gid); + p9_put_str(bufp, wstat->muid, &stat->muid); + + if (dotu) { + p9_put_str(bufp, wstat->extension, &stat->extension); + p9_put_int32(bufp, wstat->n_uid, &stat->n_uid); + p9_put_int32(bufp, wstat->n_gid, &stat->n_gid); + p9_put_int32(bufp, wstat->n_muid, &stat->n_muid); + } +} + +static struct p9_fcall * +p9_create_common(struct cbuf *bufp, u32 size, u8 id) +{ + struct p9_fcall *fc; + + size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ + fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL); + if (!fc) + return ERR_PTR(-ENOMEM); + + fc->sdata = (char *)fc + sizeof(*fc); + + buf_init(bufp, (char *)fc->sdata, size); + p9_put_int32(bufp, size, &fc->size); + p9_put_int8(bufp, id, &fc->id); + p9_put_int16(bufp, P9_NOTAG, &fc->tag); + + return fc; +} + +void p9_set_tag(struct p9_fcall *fc, u16 tag) +{ + fc->tag = tag; + *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); +} +EXPORT_SYMBOL(p9_set_tag); + +struct p9_fcall *p9_create_tversion(u32 msize, char *version) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4 + 2 + strlen(version); /* msize[4] version[s] */ + fc = p9_create_common(bufp, size, P9_TVERSION); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, msize, &fc->params.tversion.msize); + p9_put_str(bufp, version, &fc->params.tversion.version); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tversion); + +struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + /* afid[4] uname[s] aname[s] */ + size = 4 + 2 + strlen(uname) + 2 + strlen(aname); + fc = p9_create_common(bufp, size, P9_TAUTH); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, afid, &fc->params.tauth.afid); + p9_put_str(bufp, uname, &fc->params.tauth.uname); + p9_put_str(bufp, aname, &fc->params.tauth.aname); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tauth); + +struct p9_fcall * +p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + /* fid[4] afid[4] uname[s] aname[s] */ + size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); + fc = p9_create_common(bufp, size, P9_TATTACH); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tattach.fid); + p9_put_int32(bufp, afid, &fc->params.tattach.afid); + p9_put_str(bufp, uname, &fc->params.tattach.uname); + p9_put_str(bufp, aname, &fc->params.tattach.aname); + +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tattach); + +struct p9_fcall *p9_create_tflush(u16 oldtag) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 2; /* oldtag[2] */ + fc = p9_create_common(bufp, size, P9_TFLUSH); + if (IS_ERR(fc)) + goto error; + + p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tflush); + +struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, + char **wnames) +{ + int i, size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + if (nwname > P9_MAXWELEM) { + P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM); + return NULL; + } + + size = 4 + 4 + 2; /* fid[4] newfid[4] nwname[2] ... */ + for (i = 0; i < nwname; i++) { + size += 2 + strlen(wnames[i]); /* wname[s] */ + } + + fc = p9_create_common(bufp, size, P9_TWALK); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.twalk.fid); + p9_put_int32(bufp, newfid, &fc->params.twalk.newfid); + p9_put_int16(bufp, nwname, &fc->params.twalk.nwname); + for (i = 0; i < nwname; i++) { + p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); + } + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_twalk); + +struct p9_fcall *p9_create_topen(u32 fid, u8 mode) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4 + 1; /* fid[4] mode[1] */ + fc = p9_create_common(bufp, size, P9_TOPEN); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.topen.fid); + p9_put_int8(bufp, mode, &fc->params.topen.mode); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_topen); + +struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, + char *extension, int dotu) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + /* fid[4] name[s] perm[4] mode[1] */ + size = 4 + 2 + strlen(name) + 4 + 1; + if (dotu) { + size += 2 + /* extension[s] */ + (extension == NULL ? 0 : strlen(extension)); + } + + fc = p9_create_common(bufp, size, P9_TCREATE); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tcreate.fid); + p9_put_str(bufp, name, &fc->params.tcreate.name); + p9_put_int32(bufp, perm, &fc->params.tcreate.perm); + p9_put_int8(bufp, mode, &fc->params.tcreate.mode); + if (dotu) + p9_put_str(bufp, extension, &fc->params.tcreate.extension); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tcreate); + +struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ + fc = p9_create_common(bufp, size, P9_TREAD); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tread.fid); + p9_put_int64(bufp, offset, &fc->params.tread.offset); + p9_put_int32(bufp, count, &fc->params.tread.count); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tread); + +struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, + const char *data) +{ + int size, err; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + /* fid[4] offset[8] count[4] data[count] */ + size = 4 + 8 + 4 + count; + fc = p9_create_common(bufp, size, P9_TWRITE); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.twrite.fid); + p9_put_int64(bufp, offset, &fc->params.twrite.offset); + p9_put_int32(bufp, count, &fc->params.twrite.count); + err = p9_put_data(bufp, data, count, &fc->params.twrite.data); + if (err) { + kfree(fc); + fc = ERR_PTR(err); + } + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_twrite); + +struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, + const char __user *data) +{ + int size, err; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + /* fid[4] offset[8] count[4] data[count] */ + size = 4 + 8 + 4 + count; + fc = p9_create_common(bufp, size, P9_TWRITE); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.twrite.fid); + p9_put_int64(bufp, offset, &fc->params.twrite.offset); + p9_put_int32(bufp, count, &fc->params.twrite.count); + err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data); + if (err) { + kfree(fc); + fc = ERR_PTR(err); + } + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_twrite_u); + +struct p9_fcall *p9_create_tclunk(u32 fid) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4; /* fid[4] */ + fc = p9_create_common(bufp, size, P9_TCLUNK); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tclunk.fid); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tclunk); + +struct p9_fcall *p9_create_tremove(u32 fid) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4; /* fid[4] */ + fc = p9_create_common(bufp, size, P9_TREMOVE); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tremove.fid); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tremove); + +struct p9_fcall *p9_create_tstat(u32 fid) +{ + int size; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + size = 4; /* fid[4] */ + fc = p9_create_common(bufp, size, P9_TSTAT); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.tstat.fid); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_tstat); + +struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, + int dotu) +{ + int size, statsz; + struct p9_fcall *fc; + struct cbuf buffer; + struct cbuf *bufp = &buffer; + + statsz = p9_size_wstat(wstat, dotu); + size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ + fc = p9_create_common(bufp, size, P9_TWSTAT); + if (IS_ERR(fc)) + goto error; + + p9_put_int32(bufp, fid, &fc->params.twstat.fid); + buf_put_int16(bufp, statsz + 2); + p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu); + + if (buf_check_overflow(bufp)) { + kfree(fc); + fc = ERR_PTR(-ENOMEM); + } +error: + return fc; +} +EXPORT_SYMBOL(p9_create_twstat); diff --git a/net/9p/error.c b/net/9p/error.c new file mode 100644 index 000000000000..ab2458b6c903 --- /dev/null +++ b/net/9p/error.c @@ -0,0 +1,240 @@ +/* + * linux/fs/9p/error.c + * + * Error string handling + * + * Plan 9 uses error strings, Unix uses error numbers. These functions + * try to help manage that and provide for dynamically adding error + * mappings. + * + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include + +struct errormap { + char *name; + int val; + + int namelen; + struct hlist_node list; +}; + +#define ERRHASHSZ 32 +static struct hlist_head hash_errmap[ERRHASHSZ]; + +/* FixMe - reduce to a reasonable size */ +static struct errormap errmap[] = { + {"Operation not permitted", EPERM}, + {"wstat prohibited", EPERM}, + {"No such file or directory", ENOENT}, + {"directory entry not found", ENOENT}, + {"file not found", ENOENT}, + {"Interrupted system call", EINTR}, + {"Input/output error", EIO}, + {"No such device or address", ENXIO}, + {"Argument list too long", E2BIG}, + {"Bad file descriptor", EBADF}, + {"Resource temporarily unavailable", EAGAIN}, + {"Cannot allocate memory", ENOMEM}, + {"Permission denied", EACCES}, + {"Bad address", EFAULT}, + {"Block device required", ENOTBLK}, + {"Device or resource busy", EBUSY}, + {"File exists", EEXIST}, + {"Invalid cross-device link", EXDEV}, + {"No such device", ENODEV}, + {"Not a directory", ENOTDIR}, + {"Is a directory", EISDIR}, + {"Invalid argument", EINVAL}, + {"Too many open files in system", ENFILE}, + {"Too many open files", EMFILE}, + {"Text file busy", ETXTBSY}, + {"File too large", EFBIG}, + {"No space left on device", ENOSPC}, + {"Illegal seek", ESPIPE}, + {"Read-only file system", EROFS}, + {"Too many links", EMLINK}, + {"Broken pipe", EPIPE}, + {"Numerical argument out of domain", EDOM}, + {"Numerical result out of range", ERANGE}, + {"Resource deadlock avoided", EDEADLK}, + {"File name too long", ENAMETOOLONG}, + {"No locks available", ENOLCK}, + {"Function not implemented", ENOSYS}, + {"Directory not empty", ENOTEMPTY}, + {"Too many levels of symbolic links", ELOOP}, + {"No message of desired type", ENOMSG}, + {"Identifier removed", EIDRM}, + {"No data available", ENODATA}, + {"Machine is not on the network", ENONET}, + {"Package not installed", ENOPKG}, + {"Object is remote", EREMOTE}, + {"Link has been severed", ENOLINK}, + {"Communication error on send", ECOMM}, + {"Protocol error", EPROTO}, + {"Bad message", EBADMSG}, + {"File descriptor in bad state", EBADFD}, + {"Streams pipe error", ESTRPIPE}, + {"Too many users", EUSERS}, + {"Socket operation on non-socket", ENOTSOCK}, + {"Message too long", EMSGSIZE}, + {"Protocol not available", ENOPROTOOPT}, + {"Protocol not supported", EPROTONOSUPPORT}, + {"Socket type not supported", ESOCKTNOSUPPORT}, + {"Operation not supported", EOPNOTSUPP}, + {"Protocol family not supported", EPFNOSUPPORT}, + {"Network is down", ENETDOWN}, + {"Network is unreachable", ENETUNREACH}, + {"Network dropped connection on reset", ENETRESET}, + {"Software caused connection abort", ECONNABORTED}, + {"Connection reset by peer", ECONNRESET}, + {"No buffer space available", ENOBUFS}, + {"Transport endpoint is already connected", EISCONN}, + {"Transport endpoint is not connected", ENOTCONN}, + {"Cannot send after transport endpoint shutdown", ESHUTDOWN}, + {"Connection timed out", ETIMEDOUT}, + {"Connection refused", ECONNREFUSED}, + {"Host is down", EHOSTDOWN}, + {"No route to host", EHOSTUNREACH}, + {"Operation already in progress", EALREADY}, + {"Operation now in progress", EINPROGRESS}, + {"Is a named type file", EISNAM}, + {"Remote I/O error", EREMOTEIO}, + {"Disk quota exceeded", EDQUOT}, +/* errors from fossil, vacfs, and u9fs */ + {"fid unknown or out of range", EBADF}, + {"permission denied", EACCES}, + {"file does not exist", ENOENT}, + {"authentication failed", ECONNREFUSED}, + {"bad offset in directory read", ESPIPE}, + {"bad use of fid", EBADF}, + {"wstat can't convert between files and directories", EPERM}, + {"directory is not empty", ENOTEMPTY}, + {"file exists", EEXIST}, + {"file already exists", EEXIST}, + {"file or directory already exists", EEXIST}, + {"fid already in use", EBADF}, + {"file in use", ETXTBSY}, + {"i/o error", EIO}, + {"file already open for I/O", ETXTBSY}, + {"illegal mode", EINVAL}, + {"illegal name", ENAMETOOLONG}, + {"not a directory", ENOTDIR}, + {"not a member of proposed group", EPERM}, + {"not owner", EACCES}, + {"only owner can change group in wstat", EACCES}, + {"read only file system", EROFS}, + {"no access to special file", EPERM}, + {"i/o count too large", EIO}, + {"unknown group", EINVAL}, + {"unknown user", EINVAL}, + {"bogus wstat buffer", EPROTO}, + {"exclusive use file already open", EAGAIN}, + {"corrupted directory entry", EIO}, + {"corrupted file entry", EIO}, + {"corrupted block label", EIO}, + {"corrupted meta data", EIO}, + {"illegal offset", EINVAL}, + {"illegal path element", ENOENT}, + {"root of file system is corrupted", EIO}, + {"corrupted super block", EIO}, + {"protocol botch", EPROTO}, + {"file system is full", ENOSPC}, + {"file is in use", EAGAIN}, + {"directory entry is not allocated", ENOENT}, + {"file is read only", EROFS}, + {"file has been removed", EIDRM}, + {"only support truncation to zero length", EPERM}, + {"cannot remove root", EPERM}, + {"file too big", EFBIG}, + {"venti i/o error", EIO}, + /* these are not errors */ + {"u9fs rhostsauth: no authentication required", 0}, + {"u9fs authnone: no authentication required", 0}, + {NULL, -1} +}; + +/** + * p9_error_init - preload + * @errstr: error string + * + */ + +int p9_error_init(void) +{ + struct errormap *c; + int bucket; + + /* initialize hash table */ + for (bucket = 0; bucket < ERRHASHSZ; bucket++) + INIT_HLIST_HEAD(&hash_errmap[bucket]); + + /* load initial error map into hash table */ + for (c = errmap; c->name != NULL; c++) { + c->namelen = strlen(c->name); + bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; + INIT_HLIST_NODE(&c->list); + hlist_add_head(&c->list, &hash_errmap[bucket]); + } + + return 1; +} +EXPORT_SYMBOL(p9_error_init); + +/** + * errstr2errno - convert error string to error number + * @errstr: error string + * + */ + +int p9_errstr2errno(char *errstr, int len) +{ + int errno; + struct hlist_node *p; + struct errormap *c; + int bucket; + + errno = 0; + p = NULL; + c = NULL; + bucket = jhash(errstr, len, 0) % ERRHASHSZ; + hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { + if (c->namelen == len && !memcmp(c->name, errstr, len)) { + errno = c->val; + break; + } + } + + if (errno == 0) { + /* TODO: if error isn't found, add it dynamically */ + errstr[len] = 0; + printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, + errstr); + errno = 1; + } + + return -errno; +} +EXPORT_SYMBOL(p9_errstr2errno); diff --git a/net/9p/fcprint.c b/net/9p/fcprint.c new file mode 100644 index 000000000000..b1ae8ec57d54 --- /dev/null +++ b/net/9p/fcprint.c @@ -0,0 +1,358 @@ +/* + * net/9p/fcprint.c + * + * Print 9P call. + * + * Copyright (C) 2005 by Latchesar Ionkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ +#include +#include +#include +#include +#include + +#ifdef CONFIG_NET_9P_DEBUG + +static int +p9_printqid(char *buf, int buflen, struct p9_qid *q) +{ + int n; + char b[10]; + + n = 0; + if (q->type & P9_QTDIR) + b[n++] = 'd'; + if (q->type & P9_QTAPPEND) + b[n++] = 'a'; + if (q->type & P9_QTAUTH) + b[n++] = 'A'; + if (q->type & P9_QTEXCL) + b[n++] = 'l'; + if (q->type & P9_QTTMP) + b[n++] = 't'; + if (q->type & P9_QTSYMLINK) + b[n++] = 'L'; + b[n] = '\0'; + + return scnprintf(buf, buflen, "(%.16llx %x %s)", + (long long int) q->path, q->version, b); +} + +static int +p9_printperm(char *buf, int buflen, int perm) +{ + int n; + char b[15]; + + n = 0; + if (perm & P9_DMDIR) + b[n++] = 'd'; + if (perm & P9_DMAPPEND) + b[n++] = 'a'; + if (perm & P9_DMAUTH) + b[n++] = 'A'; + if (perm & P9_DMEXCL) + b[n++] = 'l'; + if (perm & P9_DMTMP) + b[n++] = 't'; + if (perm & P9_DMDEVICE) + b[n++] = 'D'; + if (perm & P9_DMSOCKET) + b[n++] = 'S'; + if (perm & P9_DMNAMEDPIPE) + b[n++] = 'P'; + if (perm & P9_DMSYMLINK) + b[n++] = 'L'; + b[n] = '\0'; + + return scnprintf(buf, buflen, "%s%03o", b, perm&077); +} + +static int +p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended) +{ + int n; + + n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len, + st->name.str, st->uid.len, st->uid.str); + if (extended) + n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid); + + n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str); + if (extended) + n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid); + + n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str); + if (extended) + n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); + + n += scnprintf(buf+n, buflen-n, " q "); + n += p9_printqid(buf+n, buflen-n, &st->qid); + n += scnprintf(buf+n, buflen-n, " m "); + n += p9_printperm(buf+n, buflen-n, st->mode); + n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", + st->atime, st->mtime, (long long int) st->length); + + if (extended) + n += scnprintf(buf+n, buflen-n, " ext '%.*s'", + st->extension.len, st->extension.str); + + return n; +} + +static int +p9_dumpdata(char *buf, int buflen, u8 *data, int datalen) +{ + int i, n; + + i = n = 0; + while (i < datalen) { + n += scnprintf(buf + n, buflen - n, "%02x", data[i]); + if (i%4 == 3) + n += scnprintf(buf + n, buflen - n, " "); + if (i%32 == 31) + n += scnprintf(buf + n, buflen - n, "\n"); + + i++; + } + n += scnprintf(buf + n, buflen - n, "\n"); + + return n; +} + +static int +p9_printdata(char *buf, int buflen, u8 *data, int datalen) +{ + return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16); +} + +int +p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) +{ + int i, ret, type, tag; + + if (!fc) + return scnprintf(buf, buflen, ""); + + type = fc->id; + tag = fc->tag; + + ret = 0; + switch (type) { + case P9_TVERSION: + ret += scnprintf(buf+ret, buflen-ret, + "Tversion tag %u msize %u version '%.*s'", tag, + fc->params.tversion.msize, + fc->params.tversion.version.len, + fc->params.tversion.version.str); + break; + + case P9_RVERSION: + ret += scnprintf(buf+ret, buflen-ret, + "Rversion tag %u msize %u version '%.*s'", tag, + fc->params.rversion.msize, + fc->params.rversion.version.len, + fc->params.rversion.version.str); + break; + + case P9_TAUTH: + ret += scnprintf(buf+ret, buflen-ret, + "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, + fc->params.tauth.afid, fc->params.tauth.uname.len, + fc->params.tauth.uname.str, fc->params.tauth.aname.len, + fc->params.tauth.aname.str); + break; + + case P9_RAUTH: + ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); + p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); + break; + + case P9_TATTACH: + ret += scnprintf(buf+ret, buflen-ret, + "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag, + fc->params.tattach.fid, fc->params.tattach.afid, + fc->params.tattach.uname.len, fc->params.tattach.uname.str, + fc->params.tattach.aname.len, fc->params.tattach.aname.str); + break; + + case P9_RATTACH: + ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", + tag); + p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); + break; + + case P9_RERROR: + ret += scnprintf(buf+ret, buflen-ret, + "Rerror tag %u ename '%.*s'", tag, + fc->params.rerror.error.len, + fc->params.rerror.error.str); + if (extended) + ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", + fc->params.rerror.errno); + break; + + case P9_TFLUSH: + ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", + tag, fc->params.tflush.oldtag); + break; + + case P9_RFLUSH: + ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); + break; + + case P9_TWALK: + ret += scnprintf(buf+ret, buflen-ret, + "Twalk tag %u fid %d newfid %d nwname %d", tag, + fc->params.twalk.fid, fc->params.twalk.newfid, + fc->params.twalk.nwname); + for (i = 0; i < fc->params.twalk.nwname; i++) + ret += scnprintf(buf+ret, buflen-ret, " '%.*s'", + fc->params.twalk.wnames[i].len, + fc->params.twalk.wnames[i].str); + break; + + case P9_RWALK: + ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", + tag, fc->params.rwalk.nwqid); + for (i = 0; i < fc->params.rwalk.nwqid; i++) + ret += p9_printqid(buf+ret, buflen-ret, + &fc->params.rwalk.wqids[i]); + break; + + case P9_TOPEN: + ret += scnprintf(buf+ret, buflen-ret, + "Topen tag %u fid %d mode %d", tag, + fc->params.topen.fid, fc->params.topen.mode); + break; + + case P9_ROPEN: + ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); + ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); + ret += scnprintf(buf+ret, buflen-ret, " iounit %d", + fc->params.ropen.iounit); + break; + + case P9_TCREATE: + ret += scnprintf(buf+ret, buflen-ret, + "Tcreate tag %u fid %d name '%.*s' perm ", tag, + fc->params.tcreate.fid, fc->params.tcreate.name.len, + fc->params.tcreate.name.str); + + ret += p9_printperm(buf+ret, buflen-ret, + fc->params.tcreate.perm); + ret += scnprintf(buf+ret, buflen-ret, " mode %d", + fc->params.tcreate.mode); + break; + + case P9_RCREATE: + ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); + ret += p9_printqid(buf+ret, buflen-ret, + &fc->params.rcreate.qid); + ret += scnprintf(buf+ret, buflen-ret, " iounit %d", + fc->params.rcreate.iounit); + break; + + case P9_TREAD: + ret += scnprintf(buf+ret, buflen-ret, + "Tread tag %u fid %d offset %lld count %u", tag, + fc->params.tread.fid, + (long long int) fc->params.tread.offset, + fc->params.tread.count); + break; + + case P9_RREAD: + ret += scnprintf(buf+ret, buflen-ret, + "Rread tag %u count %u data ", tag, + fc->params.rread.count); + ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data, + fc->params.rread.count); + break; + + case P9_TWRITE: + ret += scnprintf(buf+ret, buflen-ret, + "Twrite tag %u fid %d offset %lld count %u data ", + tag, fc->params.twrite.fid, + (long long int) fc->params.twrite.offset, + fc->params.twrite.count); + ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data, + fc->params.twrite.count); + break; + + case P9_RWRITE: + ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", + tag, fc->params.rwrite.count); + break; + + case P9_TCLUNK: + ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", + tag, fc->params.tclunk.fid); + break; + + case P9_RCLUNK: + ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); + break; + + case P9_TREMOVE: + ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", + tag, fc->params.tremove.fid); + break; + + case P9_RREMOVE: + ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); + break; + + case P9_TSTAT: + ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", + tag, fc->params.tstat.fid); + break; + + case P9_RSTAT: + ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); + ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, + extended); + break; + + case P9_TWSTAT: + ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", + tag, fc->params.twstat.fid); + ret += p9_printstat(buf+ret, buflen-ret, + &fc->params.twstat.stat, extended); + break; + + case P9_RWSTAT: + ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); + break; + + default: + ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type); + break; + } + + return ret; +} + +#else +int +p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) +{ + return 0; +} +EXPORT_SYMBOL(p9_printfcall); +#endif /* CONFIG_NET_9P_DEBUG */ diff --git a/net/9p/mod.c b/net/9p/mod.c new file mode 100644 index 000000000000..4f9e1d2ac257 --- /dev/null +++ b/net/9p/mod.c @@ -0,0 +1,85 @@ +/* + * net/9p/9p.c + * + * 9P entry point + * + * Copyright (C) 2007 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include + +#ifdef CONFIG_NET_9P_DEBUG +unsigned int p9_debug_level = 0; /* feature-rific global debug level */ +EXPORT_SYMBOL(p9_debug_level); +module_param_named(debug, p9_debug_level, uint, 0); +MODULE_PARM_DESC(debug, "9P debugging level"); +#endif + +extern int p9_mux_global_init(void); +extern void p9_mux_global_exit(void); +extern int p9_sysctl_register(void); +extern void p9_sysctl_unregister(void); + +/** + * v9fs_init - Initialize module + * + */ +static int __init init_p9(void) +{ + int ret; + + p9_error_init(); + printk(KERN_INFO "Installing 9P2000 support\n"); + ret = p9_mux_global_init(); + if (ret) { + printk(KERN_WARNING "9p: starting mux failed\n"); + return ret; + } + + ret = p9_sysctl_register(); + if (ret) { + printk(KERN_WARNING "9p: registering sysctl failed\n"); + return ret; + } + + return ret; +} + +/** + * v9fs_init - shutdown module + * + */ + +static void __exit exit_p9(void) +{ + p9_sysctl_unregister(); + p9_mux_global_exit(); +} + +module_init(init_p9) +module_exit(exit_p9) + +MODULE_AUTHOR("Latchesar Ionkov "); +MODULE_AUTHOR("Eric Van Hensbergen "); +MODULE_AUTHOR("Ron Minnich "); +MODULE_LICENSE("GPL"); diff --git a/net/9p/mux.c b/net/9p/mux.c new file mode 100644 index 000000000000..c3aa87bc8b97 --- /dev/null +++ b/net/9p/mux.c @@ -0,0 +1,1050 @@ +/* + * net/9p/mux.c + * + * Protocol Multiplexer + * + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2004-2005 by Latchesar Ionkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERREQFLUSH 1 +#define SCHED_TIMEOUT 10 +#define MAXPOLLWADDR 2 + +enum { + Rworksched = 1, /* read work scheduled or running */ + Rpending = 2, /* can read */ + Wworksched = 4, /* write work scheduled or running */ + Wpending = 8, /* can write */ +}; + +enum { + None, + Flushing, + Flushed, +}; + +struct p9_mux_poll_task; + +struct p9_req { + spinlock_t lock; /* protect request structure */ + int tag; + struct p9_fcall *tcall; + struct p9_fcall *rcall; + int err; + p9_conn_req_callback cb; + void *cba; + int flush; + struct list_head req_list; +}; + +struct p9_conn { + spinlock_t lock; /* protect lock structure */ + struct list_head mux_list; + struct p9_mux_poll_task *poll_task; + int msize; + unsigned char *extended; + struct p9_transport *trans; + struct p9_idpool *tagpool; + int err; + wait_queue_head_t equeue; + struct list_head req_list; + struct list_head unsent_req_list; + struct p9_fcall *rcall; + int rpos; + char *rbuf; + int wpos; + int wsize; + char *wbuf; + wait_queue_t poll_wait[MAXPOLLWADDR]; + wait_queue_head_t *poll_waddr[MAXPOLLWADDR]; + poll_table pt; + struct work_struct rq; + struct work_struct wq; + unsigned long wsched; +}; + +struct p9_mux_poll_task { + struct task_struct *task; + struct list_head mux_list; + int muxnum; +}; + +struct p9_mux_rpc { + struct p9_conn *m; + int err; + struct p9_fcall *tcall; + struct p9_fcall *rcall; + wait_queue_head_t wqueue; +}; + +static int p9_poll_proc(void *); +static void p9_read_work(struct work_struct *work); +static void p9_write_work(struct work_struct *work); +static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table * p); +static u16 p9_mux_get_tag(struct p9_conn *); +static void p9_mux_put_tag(struct p9_conn *, u16); + +static DEFINE_MUTEX(p9_mux_task_lock); +static struct workqueue_struct *p9_mux_wq; + +static int p9_mux_num; +static int p9_mux_poll_task_num; +static struct p9_mux_poll_task p9_mux_poll_tasks[100]; + +int p9_mux_global_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) + p9_mux_poll_tasks[i].task = NULL; + + p9_mux_wq = create_workqueue("v9fs"); + if (!p9_mux_wq) { + printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); + return -ENOMEM; + } + + return 0; +} + +void p9_mux_global_exit(void) +{ + destroy_workqueue(p9_mux_wq); +} + +/** + * p9_mux_calc_poll_procs - calculates the number of polling procs + * based on the number of mounted v9fs filesystems. + * + * The current implementation returns sqrt of the number of mounts. + */ +static int p9_mux_calc_poll_procs(int muxnum) +{ + int n; + + if (p9_mux_poll_task_num) + n = muxnum / p9_mux_poll_task_num + + (muxnum % p9_mux_poll_task_num ? 1 : 0); + else + n = 1; + + if (n > ARRAY_SIZE(p9_mux_poll_tasks)) + n = ARRAY_SIZE(p9_mux_poll_tasks); + + return n; +} + +static int p9_mux_poll_start(struct p9_conn *m) +{ + int i, n; + struct p9_mux_poll_task *vpt, *vptlast; + struct task_struct *pproc; + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num, + p9_mux_poll_task_num); + mutex_lock(&p9_mux_task_lock); + + n = p9_mux_calc_poll_procs(p9_mux_num + 1); + if (n > p9_mux_poll_task_num) { + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { + if (p9_mux_poll_tasks[i].task == NULL) { + vpt = &p9_mux_poll_tasks[i]; + P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n", + vpt); + pproc = kthread_create(p9_poll_proc, vpt, + "v9fs-poll"); + + if (!IS_ERR(pproc)) { + vpt->task = pproc; + INIT_LIST_HEAD(&vpt->mux_list); + vpt->muxnum = 0; + p9_mux_poll_task_num++; + wake_up_process(vpt->task); + } + break; + } + } + + if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) + P9_DPRINTK(P9_DEBUG_ERROR, + "warning: no free poll slots\n"); + } + + n = (p9_mux_num + 1) / p9_mux_poll_task_num + + ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0); + + vptlast = NULL; + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { + vpt = &p9_mux_poll_tasks[i]; + if (vpt->task != NULL) { + vptlast = vpt; + if (vpt->muxnum < n) { + P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); + list_add(&m->mux_list, &vpt->mux_list); + vpt->muxnum++; + m->poll_task = vpt; + memset(&m->poll_waddr, 0, + sizeof(m->poll_waddr)); + init_poll_funcptr(&m->pt, p9_pollwait); + break; + } + } + } + + if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) { + if (vptlast == NULL) + return -ENOMEM; + + P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); + list_add(&m->mux_list, &vptlast->mux_list); + vptlast->muxnum++; + m->poll_task = vptlast; + memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); + init_poll_funcptr(&m->pt, p9_pollwait); + } + + p9_mux_num++; + mutex_unlock(&p9_mux_task_lock); + + return 0; +} + +static void p9_mux_poll_stop(struct p9_conn *m) +{ + int i; + struct p9_mux_poll_task *vpt; + + mutex_lock(&p9_mux_task_lock); + vpt = m->poll_task; + list_del(&m->mux_list); + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { + if (m->poll_waddr[i] != NULL) { + remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); + m->poll_waddr[i] = NULL; + } + } + vpt->muxnum--; + if (!vpt->muxnum) { + P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt); + kthread_stop(vpt->task); + vpt->task = NULL; + p9_mux_poll_task_num--; + } + p9_mux_num--; + mutex_unlock(&p9_mux_task_lock); +} + +/** + * p9_conn_create - allocate and initialize the per-session mux data + * Creates the polling task if this is the first session. + * + * @trans - transport structure + * @msize - maximum message size + * @extended - pointer to the extended flag + */ +struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, + unsigned char *extended) +{ + int i, n; + struct p9_conn *m, *mtmp; + + P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize); + m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); + if (!m) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&m->lock); + INIT_LIST_HEAD(&m->mux_list); + m->msize = msize; + m->extended = extended; + m->trans = trans; + m->tagpool = p9_idpool_create(); + if (!m->tagpool) { + kfree(m); + return ERR_PTR(PTR_ERR(m->tagpool)); + } + + m->err = 0; + init_waitqueue_head(&m->equeue); + INIT_LIST_HEAD(&m->req_list); + INIT_LIST_HEAD(&m->unsent_req_list); + m->rcall = NULL; + m->rpos = 0; + m->rbuf = NULL; + m->wpos = m->wsize = 0; + m->wbuf = NULL; + INIT_WORK(&m->rq, p9_read_work); + INIT_WORK(&m->wq, p9_write_work); + m->wsched = 0; + memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); + m->poll_task = NULL; + n = p9_mux_poll_start(m); + if (n) + return ERR_PTR(n); + + n = trans->poll(trans, &m->pt); + if (n & POLLIN) { + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); + set_bit(Rpending, &m->wsched); + } + + if (n & POLLOUT) { + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); + set_bit(Wpending, &m->wsched); + } + + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { + if (IS_ERR(m->poll_waddr[i])) { + p9_mux_poll_stop(m); + mtmp = (void *)m->poll_waddr; /* the error code */ + kfree(m); + m = mtmp; + break; + } + } + + return m; +} +EXPORT_SYMBOL(p9_conn_create); + +/** + * p9_mux_destroy - cancels all pending requests and frees mux resources + */ +void p9_conn_destroy(struct p9_conn *m) +{ + P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, + m->mux_list.prev, m->mux_list.next); + p9_conn_cancel(m, -ECONNRESET); + + if (!list_empty(&m->req_list)) { + /* wait until all processes waiting on this session exit */ + P9_DPRINTK(P9_DEBUG_MUX, + "mux %p waiting for empty request queue\n", m); + wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); + P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, + list_empty(&m->req_list)); + } + + p9_mux_poll_stop(m); + m->trans = NULL; + p9_idpool_destroy(m->tagpool); + kfree(m); +} +EXPORT_SYMBOL(p9_conn_destroy); + +/** + * p9_pollwait - called by files poll operation to add v9fs-poll task + * to files wait queue + */ +static void +p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table * p) +{ + int i; + struct p9_conn *m; + + m = container_of(p, struct p9_conn, pt); + for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) + if (m->poll_waddr[i] == NULL) + break; + + if (i >= ARRAY_SIZE(m->poll_waddr)) { + P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n"); + return; + } + + m->poll_waddr[i] = wait_address; + + if (!wait_address) { + P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n"); + m->poll_waddr[i] = ERR_PTR(-EIO); + return; + } + + init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task); + add_wait_queue(wait_address, &m->poll_wait[i]); +} + +/** + * p9_poll_mux - polls a mux and schedules read or write works if necessary + */ +static void p9_poll_mux(struct p9_conn *m) +{ + int n; + + if (m->err < 0) + return; + + n = m->trans->poll(m->trans, NULL); + if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { + P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n); + if (n >= 0) + n = -ECONNRESET; + p9_conn_cancel(m, n); + } + + if (n & POLLIN) { + set_bit(Rpending, &m->wsched); + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); + if (!test_and_set_bit(Rworksched, &m->wsched)) { + P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); + queue_work(p9_mux_wq, &m->rq); + } + } + + if (n & POLLOUT) { + set_bit(Wpending, &m->wsched); + P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); + if ((m->wsize || !list_empty(&m->unsent_req_list)) + && !test_and_set_bit(Wworksched, &m->wsched)) { + P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); + queue_work(p9_mux_wq, &m->wq); + } + } +} + +/** + * p9_poll_proc - polls all v9fs transports for new events and queues + * the appropriate work to the work queue + */ +static int p9_poll_proc(void *a) +{ + struct p9_conn *m, *mtmp; + struct p9_mux_poll_task *vpt; + + vpt = a; + P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt); + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + + list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { + p9_poll_mux(m); + } + + P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n"); + schedule_timeout(SCHED_TIMEOUT * HZ); + } + + __set_current_state(TASK_RUNNING); + P9_DPRINTK(P9_DEBUG_MUX, "finish\n"); + return 0; +} + +/** + * p9_write_work - called when a transport can send some data + */ +static void p9_write_work(struct work_struct *work) +{ + int n, err; + struct p9_conn *m; + struct p9_req *req; + + m = container_of(work, struct p9_conn, wq); + + if (m->err < 0) { + clear_bit(Wworksched, &m->wsched); + return; + } + + if (!m->wsize) { + if (list_empty(&m->unsent_req_list)) { + clear_bit(Wworksched, &m->wsched); + return; + } + + spin_lock(&m->lock); +again: + req = list_entry(m->unsent_req_list.next, struct p9_req, + req_list); + list_move_tail(&req->req_list, &m->req_list); + if (req->err == ERREQFLUSH) + goto again; + + m->wbuf = req->tcall->sdata; + m->wsize = req->tcall->size; + m->wpos = 0; + spin_unlock(&m->lock); + } + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, + m->wsize); + clear_bit(Wpending, &m->wsched); + err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); + P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); + if (err == -EAGAIN) { + clear_bit(Wworksched, &m->wsched); + return; + } + + if (err <= 0) + goto error; + + m->wpos += err; + if (m->wpos == m->wsize) + m->wpos = m->wsize = 0; + + if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) { + if (test_and_clear_bit(Wpending, &m->wsched)) + n = POLLOUT; + else + n = m->trans->poll(m->trans, NULL); + + if (n & POLLOUT) { + P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); + queue_work(p9_mux_wq, &m->wq); + } else + clear_bit(Wworksched, &m->wsched); + } else + clear_bit(Wworksched, &m->wsched); + + return; + +error: + p9_conn_cancel(m, err); + clear_bit(Wworksched, &m->wsched); +} + +static void process_request(struct p9_conn *m, struct p9_req *req) +{ + int ecode; + struct p9_str *ename; + + if (!req->err && req->rcall->id == P9_RERROR) { + ecode = req->rcall->params.rerror.errno; + ename = &req->rcall->params.rerror.error; + + P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, + ename->str); + + if (*m->extended) + req->err = -ecode; + + if (!req->err) { + req->err = p9_errstr2errno(ename->str, ename->len); + + if (!req->err) { /* string match failed */ + PRINT_FCALL_ERROR("unknown error", req->rcall); + } + + if (!req->err) + req->err = -ESERVERFAULT; + } + } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { + P9_DPRINTK(P9_DEBUG_ERROR, + "fcall mismatch: expected %d, got %d\n", + req->tcall->id + 1, req->rcall->id); + if (!req->err) + req->err = -EIO; + } +} + +/** + * p9_read_work - called when there is some data to be read from a transport + */ +static void p9_read_work(struct work_struct *work) +{ + int n, err; + struct p9_conn *m; + struct p9_req *req, *rptr, *rreq; + struct p9_fcall *rcall; + char *rbuf; + + m = container_of(work, struct p9_conn, rq); + + if (m->err < 0) + return; + + rcall = NULL; + P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); + + if (!m->rcall) { + m->rcall = + kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL); + if (!m->rcall) { + err = -ENOMEM; + goto error; + } + + m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); + m->rpos = 0; + } + + clear_bit(Rpending, &m->wsched); + err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); + P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); + if (err == -EAGAIN) { + clear_bit(Rworksched, &m->wsched); + return; + } + + if (err <= 0) + goto error; + + m->rpos += err; + while (m->rpos > 4) { + n = le32_to_cpu(*(__le32 *) m->rbuf); + if (n >= m->msize) { + P9_DPRINTK(P9_DEBUG_ERROR, + "requested packet size too big: %d\n", n); + err = -EIO; + goto error; + } + + if (m->rpos < n) + break; + + err = + p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); + if (err < 0) { + goto error; + } + +#ifdef CONFIG_NET_9P_DEBUG + if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { + char buf[150]; + + p9_printfcall(buf, sizeof(buf), m->rcall, + *m->extended); + printk(KERN_NOTICE ">>> %p %s\n", m, buf); + } +#endif + + rcall = m->rcall; + rbuf = m->rbuf; + if (m->rpos > n) { + m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize, + GFP_KERNEL); + if (!m->rcall) { + err = -ENOMEM; + goto error; + } + + m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); + memmove(m->rbuf, rbuf + n, m->rpos - n); + m->rpos -= n; + } else { + m->rcall = NULL; + m->rbuf = NULL; + m->rpos = 0; + } + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, + rcall->id, rcall->tag); + + req = NULL; + spin_lock(&m->lock); + list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { + if (rreq->tag == rcall->tag) { + req = rreq; + if (req->flush != Flushing) + list_del(&req->req_list); + break; + } + } + spin_unlock(&m->lock); + + if (req) { + req->rcall = rcall; + process_request(m, req); + + if (req->flush != Flushing) { + if (req->cb) + (*req->cb) (req, req->cba); + else + kfree(req->rcall); + + wake_up(&m->equeue); + } + } else { + if (err >= 0 && rcall->id != P9_RFLUSH) + P9_DPRINTK(P9_DEBUG_ERROR, + "unexpected response mux %p id %d tag %d\n", + m, rcall->id, rcall->tag); + kfree(rcall); + } + } + + if (!list_empty(&m->req_list)) { + if (test_and_clear_bit(Rpending, &m->wsched)) + n = POLLIN; + else + n = m->trans->poll(m->trans, NULL); + + if (n & POLLIN) { + P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); + queue_work(p9_mux_wq, &m->rq); + } else + clear_bit(Rworksched, &m->wsched); + } else + clear_bit(Rworksched, &m->wsched); + + return; + +error: + p9_conn_cancel(m, err); + clear_bit(Rworksched, &m->wsched); +} + +/** + * p9_send_request - send 9P request + * The function can sleep until the request is scheduled for sending. + * The function can be interrupted. Return from the function is not + * a guarantee that the request is sent successfully. Can return errors + * that can be retrieved by PTR_ERR macros. + * + * @m: mux data + * @tc: request to be sent + * @cb: callback function to call when response is received + * @cba: parameter to pass to the callback function + */ +static struct p9_req *p9_send_request(struct p9_conn *m, + struct p9_fcall *tc, + p9_conn_req_callback cb, void *cba) +{ + int n; + struct p9_req *req; + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, + tc, tc->id); + if (m->err < 0) + return ERR_PTR(m->err); + + req = kmalloc(sizeof(struct p9_req), GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + if (tc->id == P9_TVERSION) + n = P9_NOTAG; + else + n = p9_mux_get_tag(m); + + if (n < 0) + return ERR_PTR(-ENOMEM); + + p9_set_tag(tc, n); + +#ifdef CONFIG_NET_9P_DEBUG + if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { + char buf[150]; + + p9_printfcall(buf, sizeof(buf), tc, *m->extended); + printk(KERN_NOTICE "<<< %p %s\n", m, buf); + } +#endif + + spin_lock_init(&req->lock); + req->tag = n; + req->tcall = tc; + req->rcall = NULL; + req->err = 0; + req->cb = cb; + req->cba = cba; + req->flush = None; + + spin_lock(&m->lock); + list_add_tail(&req->req_list, &m->unsent_req_list); + spin_unlock(&m->lock); + + if (test_and_clear_bit(Wpending, &m->wsched)) + n = POLLOUT; + else + n = m->trans->poll(m->trans, NULL); + + if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) + queue_work(p9_mux_wq, &m->wq); + + return req; +} + +static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req) +{ + p9_mux_put_tag(m, req->tag); + kfree(req); +} + +static void p9_mux_flush_cb(struct p9_req *freq, void *a) +{ + p9_conn_req_callback cb; + int tag; + struct p9_conn *m; + struct p9_req *req, *rreq, *rptr; + + m = a; + P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, + freq->tcall, freq->rcall, freq->err, + freq->tcall->params.tflush.oldtag); + + spin_lock(&m->lock); + cb = NULL; + tag = freq->tcall->params.tflush.oldtag; + req = NULL; + list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { + if (rreq->tag == tag) { + req = rreq; + list_del(&req->req_list); + break; + } + } + spin_unlock(&m->lock); + + if (req) { + spin_lock(&req->lock); + req->flush = Flushed; + spin_unlock(&req->lock); + + if (req->cb) + (*req->cb) (req, req->cba); + else + kfree(req->rcall); + + wake_up(&m->equeue); + } + + kfree(freq->tcall); + kfree(freq->rcall); + p9_mux_free_request(m, freq); +} + +static int +p9_mux_flush_request(struct p9_conn *m, struct p9_req *req) +{ + struct p9_fcall *fc; + struct p9_req *rreq, *rptr; + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); + + /* if a response was received for a request, do nothing */ + spin_lock(&req->lock); + if (req->rcall || req->err) { + spin_unlock(&req->lock); + P9_DPRINTK(P9_DEBUG_MUX, + "mux %p req %p response already received\n", m, req); + return 0; + } + + req->flush = Flushing; + spin_unlock(&req->lock); + + spin_lock(&m->lock); + /* if the request is not sent yet, just remove it from the list */ + list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { + if (rreq->tag == req->tag) { + P9_DPRINTK(P9_DEBUG_MUX, + "mux %p req %p request is not sent yet\n", m, req); + list_del(&rreq->req_list); + req->flush = Flushed; + spin_unlock(&m->lock); + if (req->cb) + (*req->cb) (req, req->cba); + return 0; + } + } + spin_unlock(&m->lock); + + clear_thread_flag(TIF_SIGPENDING); + fc = p9_create_tflush(req->tag); + p9_send_request(m, fc, p9_mux_flush_cb, m); + return 1; +} + +static void +p9_conn_rpc_cb(struct p9_req *req, void *a) +{ + struct p9_mux_rpc *r; + + P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a); + r = a; + r->rcall = req->rcall; + r->err = req->err; + + if (req->flush != None && !req->err) + r->err = -ERESTARTSYS; + + wake_up(&r->wqueue); +} + +/** + * p9_mux_rpc - sends 9P request and waits until a response is available. + * The function can be interrupted. + * @m: mux data + * @tc: request to be sent + * @rc: pointer where a pointer to the response is stored + */ +int +p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, + struct p9_fcall **rc) +{ + int err, sigpending; + unsigned long flags; + struct p9_req *req; + struct p9_mux_rpc r; + + r.err = 0; + r.tcall = tc; + r.rcall = NULL; + r.m = m; + init_waitqueue_head(&r.wqueue); + + if (rc) + *rc = NULL; + + sigpending = 0; + if (signal_pending(current)) { + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); + } + + req = p9_send_request(m, tc, p9_conn_rpc_cb, &r); + if (IS_ERR(req)) { + err = PTR_ERR(req); + P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); + return err; + } + + err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0); + if (r.err < 0) + err = r.err; + + if (err == -ERESTARTSYS && m->trans->status == Connected + && m->err == 0) { + if (p9_mux_flush_request(m, req)) { + /* wait until we get response of the flush message */ + do { + clear_thread_flag(TIF_SIGPENDING); + err = wait_event_interruptible(r.wqueue, + r.rcall || r.err); + } while (!r.rcall && !r.err && err == -ERESTARTSYS && + m->trans->status == Connected && !m->err); + + err = -ERESTARTSYS; + } + sigpending = 1; + } + + if (sigpending) { + spin_lock_irqsave(¤t->sighand->siglock, flags); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + } + + if (rc) + *rc = r.rcall; + else + kfree(r.rcall); + + p9_mux_free_request(m, req); + if (err > 0) + err = -EIO; + + return err; +} +EXPORT_SYMBOL(p9_conn_rpc); + +#ifdef P9_NONBLOCK +/** + * p9_conn_rpcnb - sends 9P request without waiting for response. + * @m: mux data + * @tc: request to be sent + * @cb: callback function to be called when response arrives + * @cba: value to pass to the callback function + */ +int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, + p9_conn_req_callback cb, void *a) +{ + int err; + struct p9_req *req; + + req = p9_send_request(m, tc, cb, a); + if (IS_ERR(req)) { + err = PTR_ERR(req); + P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); + return PTR_ERR(req); + } + + P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); + return 0; +} +EXPORT_SYMBOL(p9_conn_rpcnb); +#endif /* P9_NONBLOCK */ + +/** + * p9_conn_cancel - cancel all pending requests with error + * @m: mux data + * @err: error code + */ +void p9_conn_cancel(struct p9_conn *m, int err) +{ + struct p9_req *req, *rtmp; + LIST_HEAD(cancel_list); + + P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); + m->err = err; + spin_lock(&m->lock); + list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { + list_move(&req->req_list, &cancel_list); + } + list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { + list_move(&req->req_list, &cancel_list); + } + spin_unlock(&m->lock); + + list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { + list_del(&req->req_list); + if (!req->err) + req->err = err; + + if (req->cb) + (*req->cb) (req, req->cba); + else + kfree(req->rcall); + } + + wake_up(&m->equeue); +} +EXPORT_SYMBOL(p9_conn_cancel); + +static u16 p9_mux_get_tag(struct p9_conn *m) +{ + int tag; + + tag = p9_idpool_get(m->tagpool); + if (tag < 0) + return P9_NOTAG; + else + return (u16) tag; +} + +static void p9_mux_put_tag(struct p9_conn *m, u16 tag) +{ + if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool)) + p9_idpool_put(tag, m->tagpool); +} diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c new file mode 100644 index 000000000000..e7fe706ab95a --- /dev/null +++ b/net/9p/sysctl.c @@ -0,0 +1,86 @@ +/* + * net/9p/sysctl.c + * + * 9P sysctl interface + * + * Copyright (C) 2007 by Latchesar Ionkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include + +enum { + P9_SYSCTL_NET = 487, + P9_SYSCTL_DEBUG = 1, +}; + +static ctl_table p9_table[] = { +#ifdef CONFIG_NET_9P_DEBUG + { + .ctl_name = P9_SYSCTL_DEBUG, + .procname = "debug", + .data = &p9_debug_level, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, +#endif + { .ctl_name = 0 }, +}; + +static ctl_table p9_net_table[] = { + { + .ctl_name = P9_SYSCTL_NET, + .procname = "9p", + .maxlen = 0, + .mode = 0555, + .child = p9_table, + }, + { .ctl_name = 0 }, +}; + +static ctl_table p9_ctl_table[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .maxlen = 0, + .mode = 0555, + .child = p9_net_table, + }, + { .ctl_name = 0 }, +}; + +static struct ctl_table_header *p9_table_header; + +int __init p9_sysctl_register(void) +{ + p9_table_header = register_sysctl_table(p9_ctl_table); + if (!p9_table_header) + return -ENOMEM; + + return 0; +} + +void __exit p9_sysctl_unregister(void) +{ + unregister_sysctl_table(p9_table_header); +} diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c new file mode 100644 index 000000000000..fd636e94358f --- /dev/null +++ b/net/9p/trans_fd.c @@ -0,0 +1,363 @@ +/* + * linux/fs/9p/trans_fd.c + * + * Fd transport layer. Includes deprecated socket layer. + * + * Copyright (C) 2006 by Russ Cox + * Copyright (C) 2004-2005 by Latchesar Ionkov + * Copyright (C) 2004-2005 by Eric Van Hensbergen + * Copyright (C) 1997-2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define P9_PORT 564 + +struct p9_trans_fd { + struct file *rd; + struct file *wr; +}; + +static int p9_socket_open(struct p9_transport *trans, struct socket *csocket); +static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd); +static int p9_fd_read(struct p9_transport *trans, void *v, int len); +static int p9_fd_write(struct p9_transport *trans, void *v, int len); +static unsigned int p9_fd_poll(struct p9_transport *trans, + struct poll_table_struct *pt); +static void p9_fd_close(struct p9_transport *trans); + +struct p9_transport *p9_trans_create_tcp(const char *addr, int port) +{ + int err; + struct p9_transport *trans; + struct socket *csocket; + struct sockaddr_in sin_server; + + csocket = NULL; + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + sin_server.sin_family = AF_INET; + sin_server.sin_addr.s_addr = in_aton(addr); + sin_server.sin_port = htons(port); + sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); + + if (!csocket) { + P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); + err = -EIO; + goto error; + } + + err = csocket->ops->connect(csocket, + (struct sockaddr *)&sin_server, + sizeof(struct sockaddr_in), 0); + if (err < 0) { + P9_EPRINTK(KERN_ERR, + "p9_trans_tcp: problem connecting socket to %s\n", + addr); + goto error; + } + + err = p9_socket_open(trans, csocket); + if (err < 0) + goto error; + + return trans; + +error: + if (csocket) + sock_release(csocket); + + kfree(trans); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_trans_create_tcp); + +struct p9_transport *p9_trans_create_unix(const char *addr) +{ + int err; + struct socket *csocket; + struct sockaddr_un sun_server; + struct p9_transport *trans; + + csocket = NULL; + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + if (strlen(addr) > UNIX_PATH_MAX) { + P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", + addr); + err = -ENAMETOOLONG; + goto error; + } + + sun_server.sun_family = PF_UNIX; + strcpy(sun_server.sun_path, addr); + sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); + err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, + sizeof(struct sockaddr_un) - 1, 0); + if (err < 0) { + P9_EPRINTK(KERN_ERR, + "p9_trans_unix: problem connecting socket: %s: %d\n", + addr, err); + goto error; + } + + err = p9_socket_open(trans, csocket); + if (err < 0) + goto error; + + return trans; + +error: + if (csocket) + sock_release(csocket); + + kfree(trans); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_trans_create_unix); + +struct p9_transport *p9_trans_create_fd(int rfd, int wfd) +{ + int err; + struct p9_transport *trans; + + if (rfd == ~0 || wfd == ~0) { + printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); + return ERR_PTR(-ENOPROTOOPT); + } + + trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + err = p9_fd_open(trans, rfd, wfd); + if (err < 0) + goto error; + + return trans; + +error: + kfree(trans); + return ERR_PTR(err); +} +EXPORT_SYMBOL(p9_trans_create_fd); + +static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) +{ + int fd, ret; + + csocket->sk->sk_allocation = GFP_NOIO; + fd = sock_map_fd(csocket); + if (fd < 0) { + P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); + return fd; + } + + ret = p9_fd_open(trans, fd, fd); + if (ret < 0) { + P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); + sockfd_put(csocket); + return ret; + } + + ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK; + + return 0; +} + +static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) +{ + struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), + GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ts->rd = fget(rfd); + ts->wr = fget(wfd); + if (!ts->rd || !ts->wr) { + if (ts->rd) + fput(ts->rd); + if (ts->wr) + fput(ts->wr); + kfree(ts); + return -EIO; + } + + trans->priv = ts; + trans->status = Connected; + + return 0; +} + +/** + * p9_fd_read- read from a fd + * @v9ses: session information + * @v: buffer to receive data into + * @len: size of receive buffer + * + */ +static int p9_fd_read(struct p9_transport *trans, void *v, int len) +{ + int ret; + struct p9_trans_fd *ts = NULL; + + if (trans && trans->status != Disconnected) + ts = trans->priv; + + if (!ts) + return -EREMOTEIO; + + if (!(ts->rd->f_flags & O_NONBLOCK)) + P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n"); + + ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); + if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) + trans->status = Disconnected; + return ret; +} + +/** + * p9_fd_write - write to a socket + * @v9ses: session information + * @v: buffer to send data from + * @len: size of send buffer + * + */ +static int p9_fd_write(struct p9_transport *trans, void *v, int len) +{ + int ret; + mm_segment_t oldfs; + struct p9_trans_fd *ts = NULL; + + if (trans && trans->status != Disconnected) + ts = trans->priv; + + if (!ts) + return -EREMOTEIO; + + if (!(ts->wr->f_flags & O_NONBLOCK)) + P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n"); + + oldfs = get_fs(); + set_fs(get_ds()); + /* The cast to a user pointer is valid due to the set_fs() */ + ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos); + set_fs(oldfs); + + if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) + trans->status = Disconnected; + return ret; +} + +static unsigned int +p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt) +{ + int ret, n; + struct p9_trans_fd *ts = NULL; + mm_segment_t oldfs; + + if (trans && trans->status == Connected) + ts = trans->priv; + + if (!ts) + return -EREMOTEIO; + + if (!ts->rd->f_op || !ts->rd->f_op->poll) + return -EIO; + + if (!ts->wr->f_op || !ts->wr->f_op->poll) + return -EIO; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = ts->rd->f_op->poll(ts->rd, pt); + if (ret < 0) + goto end; + + if (ts->rd != ts->wr) { + n = ts->wr->f_op->poll(ts->wr, pt); + if (n < 0) { + ret = n; + goto end; + } + ret = (ret & ~POLLOUT) | (n & ~POLLIN); + } + +end: + set_fs(oldfs); + return ret; +} + +/** + * p9_sock_close - shutdown socket + * @trans: private socket structure + * + */ +static void p9_fd_close(struct p9_transport *trans) +{ + struct p9_trans_fd *ts; + + if (!trans) + return; + + ts = xchg(&trans->priv, NULL); + + if (!ts) + return; + + trans->status = Disconnected; + if (ts->rd) + fput(ts->rd); + if (ts->wr) + fput(ts->wr); + kfree(ts); +} + diff --git a/net/9p/util.c b/net/9p/util.c new file mode 100644 index 000000000000..22077b79395d --- /dev/null +++ b/net/9p/util.c @@ -0,0 +1,125 @@ +/* + * net/9p/util.c + * + * This file contains some helper functions + * + * Copyright (C) 2007 by Latchesar Ionkov + * Copyright (C) 2004 by Eric Van Hensbergen + * Copyright (C) 2002 by Ron Minnich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct p9_idpool { + struct semaphore lock; + struct idr pool; +}; + +struct p9_idpool *p9_idpool_create(void) +{ + struct p9_idpool *p; + + p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); + if (!p) + return ERR_PTR(-ENOMEM); + + init_MUTEX(&p->lock); + idr_init(&p->pool); + + return p; +} +EXPORT_SYMBOL(p9_idpool_create); + +void p9_idpool_destroy(struct p9_idpool *p) +{ + idr_destroy(&p->pool); + kfree(p); +} +EXPORT_SYMBOL(p9_idpool_destroy); + +/** + * p9_idpool_get - allocate numeric id from pool + * @p - pool to allocate from + * + * XXX - This seems to be an awful generic function, should it be in idr.c with + * the lock included in struct idr? + */ + +int p9_idpool_get(struct p9_idpool *p) +{ + int i = 0; + int error; + +retry: + if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) + return 0; + + if (down_interruptible(&p->lock) == -EINTR) { + P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); + return -1; + } + + /* no need to store exactly p, we just need something non-null */ + error = idr_get_new(&p->pool, p, &i); + up(&p->lock); + + if (error == -EAGAIN) + goto retry; + else if (error) + return -1; + + return i; +} +EXPORT_SYMBOL(p9_idpool_get); + +/** + * p9_idpool_put - release numeric id from pool + * @p - pool to allocate from + * + * XXX - This seems to be an awful generic function, should it be in idr.c with + * the lock included in struct idr? + */ + +void p9_idpool_put(int id, struct p9_idpool *p) +{ + if (down_interruptible(&p->lock) == -EINTR) { + P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); + return; + } + idr_remove(&p->pool, id); + up(&p->lock); +} +EXPORT_SYMBOL(p9_idpool_put); + +/** + * p9_idpool_check - check if the specified id is available + * @id - id to check + * @p - pool + */ +int p9_idpool_check(int id, struct p9_idpool *p) +{ + return idr_find(&p->pool, id) != NULL; +} +EXPORT_SYMBOL(p9_idpool_check); diff --git a/net/Kconfig b/net/Kconfig index f3de72978ab6..cdba08ca2efe 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -227,6 +227,7 @@ source "net/ieee80211/Kconfig" endmenu source "net/rfkill/Kconfig" +source "net/9p/Kconfig" endif # if NET endmenu # Networking diff --git a/net/Makefile b/net/Makefile index a87a88963432..bbe7d2a41486 100644 --- a/net/Makefile +++ b/net/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_TIPC) += tipc/ obj-$(CONFIG_NETLABEL) += netlabel/ obj-$(CONFIG_IUCV) += iucv/ obj-$(CONFIG_RFKILL) += rfkill/ +obj-$(CONFIG_NET_9P) += 9p/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o -- cgit v1.2.3 From acd159b6b5828175be6b9ccccd9b054239ec63e9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 14 Jul 2007 19:00:59 -0700 Subject: [INET_SOCK]: make net/ipv4/inet_timewait_sock.c:__inet_twsk_kill() static This patch makes the needlessly global __inet_twsk_kill() static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- include/net/inet_timewait_sock.h | 3 --- net/ipv4/inet_timewait_sock.c | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'include/net') diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 09a2532699b2..47d52b2414db 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -209,9 +209,6 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw) extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state); -extern void __inet_twsk_kill(struct inet_timewait_sock *tw, - struct inet_hashinfo *hashinfo); - extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, struct inet_hashinfo *hashinfo); diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index a73cf93cee36..2586df09b9b6 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -14,7 +14,8 @@ #include /* Must be called with locally disabled BHs. */ -void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo) +static void __inet_twsk_kill(struct inet_timewait_sock *tw, + struct inet_hashinfo *hashinfo) { struct inet_bind_hashbucket *bhead; struct inet_bind_bucket *tb; @@ -47,8 +48,6 @@ void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashi inet_twsk_put(tw); } -EXPORT_SYMBOL_GPL(__inet_twsk_kill); - /* * Enter the time wait state. This is called with locally disabled BH. * Essentially we whip up a timewait bucket, copy the relevant info into it -- cgit v1.2.3 From febca281f677a775c61cd0572c2f35e4ead9e7d5 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Sat, 14 Jul 2007 19:04:25 -0700 Subject: [AF_IUCV]: Add lock when updating accept_q The accept_queue of an af_iucv socket will be corrupted, if adding and deleting of entries in this queue occurs at the same time (connect request from one client, while accept call is processed for another client). Solution: add locking when updating accept_q Signed-off-by: Ursula Braun Acked-by: Frank Pavlic Signed-off-by: David S. Miller --- include/net/iucv/af_iucv.h | 1 + net/iucv/af_iucv.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'include/net') diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index f9bd11be1891..b6c468cd7f5b 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -60,6 +60,7 @@ struct iucv_sock { char dst_user_id[8]; char dst_name[8]; struct list_head accept_q; + spinlock_t accept_q_lock; struct sock *parent; struct iucv_path *path; struct sk_buff_head send_skb_q; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index d9e9ddb8eac5..53ae14c35f70 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -219,6 +219,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) sock_init_data(sock, sk); INIT_LIST_HEAD(&iucv_sk(sk)->accept_q); + spin_lock_init(&iucv_sk(sk)->accept_q_lock); skb_queue_head_init(&iucv_sk(sk)->send_skb_q); skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); iucv_sk(sk)->send_tag = 0; @@ -274,15 +275,25 @@ void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk) void iucv_accept_enqueue(struct sock *parent, struct sock *sk) { + unsigned long flags; + struct iucv_sock *par = iucv_sk(parent); + sock_hold(sk); - list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q); + spin_lock_irqsave(&par->accept_q_lock, flags); + list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q); + spin_unlock_irqrestore(&par->accept_q_lock, flags); iucv_sk(sk)->parent = parent; parent->sk_ack_backlog++; } void iucv_accept_unlink(struct sock *sk) { + unsigned long flags; + struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent); + + spin_lock_irqsave(&par->accept_q_lock, flags); list_del_init(&iucv_sk(sk)->accept_q); + spin_unlock_irqrestore(&par->accept_q_lock, flags); iucv_sk(sk)->parent->sk_ack_backlog--; iucv_sk(sk)->parent = NULL; sock_put(sk); @@ -298,8 +309,8 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) lock_sock(sk); if (sk->sk_state == IUCV_CLOSED) { - release_sock(sk); iucv_accept_unlink(sk); + release_sock(sk); continue; } @@ -879,6 +890,7 @@ static int iucv_callback_connreq(struct iucv_path *path, /* Find out if this path belongs to af_iucv. */ read_lock(&iucv_sk_list.lock); iucv = NULL; + sk = NULL; sk_for_each(sk, node, &iucv_sk_list.head) if (sk->sk_state == IUCV_LISTEN && !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { -- cgit v1.2.3 From ffc30690480bdd337e4914302b926d24870b56b2 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 14 Jul 2007 20:44:50 -0700 Subject: [NETFILTER]: nf_conntrack: make l3proto->prepare() generic and renames it The icmp[v6] l4proto modules parse headers in ICMP[v6] error to get tuple. But they have to find the offset to transport protocol header before that. Their processings are almost same as prepare() of l3proto modules. This makes prepare() more generic to simplify icmp[v6] l4proto module later. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 2 +- include/net/netfilter/nf_conntrack_l3proto.h | 6 +++--- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 23 +++++++++++++--------- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 27 +++++++++++++++----------- net/netfilter/nf_conntrack_core.c | 5 +++-- net/netfilter/nf_conntrack_l3proto_generic.c | 7 +++---- 6 files changed, 40 insertions(+), 30 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h index b4b6049e01fa..5a8965904377 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h @@ -7,7 +7,7 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; -extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, +extern int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len); extern int nf_ct_frag6_init(void); diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 890752d7f673..e3708a698d8b 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -58,11 +58,11 @@ struct nf_conntrack_l3proto /* * Called before tracking. - * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb + * *dataoff: offset of protocol header (TCP, UDP,...) in skb * *protonum: protocol number */ - int (*prepare)(struct sk_buff **pskb, unsigned int hooknum, - unsigned int *dataoff, u_int8_t *protonum); + int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff, + unsigned int *dataoff, u_int8_t *protonum); int (*tuple_to_nfattr)(struct sk_buff *skb, const struct nf_conntrack_tuple *t); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 3c5629938487..ee29f4e9eac2 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -78,21 +78,26 @@ nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) return skb; } -static int -ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, - u_int8_t *protonum) +static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, + unsigned int *dataoff, u_int8_t *protonum) { + struct iphdr _iph, *iph; + + iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); + if (iph == NULL) + return -NF_DROP; + /* Never happen */ - if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) { + if (iph->frag_off & htons(IP_OFFSET)) { if (net_ratelimit()) { - printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", - ip_hdr(*pskb)->protocol, hooknum); + printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n", + iph->protocol); } return -NF_DROP; } - *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb); - *protonum = ip_hdr(*pskb)->protocol; + *dataoff = nhoff + (iph->ihl << 2); + *protonum = iph->protocol; return NF_ACCEPT; } @@ -407,7 +412,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .invert_tuple = ipv4_invert_tuple, .print_tuple = ipv4_print_tuple, .print_conntrack = ipv4_print_conntrack, - .prepare = ipv4_prepare, + .get_l4proto = ipv4_get_l4proto, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv4_tuple_to_nfattr, .nfattr_to_tuple = ipv4_nfattr_to_tuple, diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index b5c4bb54691e..9b7eaaadc67e 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -86,7 +86,7 @@ static int ipv6_print_conntrack(struct seq_file *s, * - Note also special handling of AUTH header. Thanks to IPsec wizards. */ -int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, +int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len) { u8 nexthdr = *nexthdrp; @@ -117,19 +117,24 @@ int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, return start; } -static int -ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, - u_int8_t *protonum) +static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, + unsigned int *dataoff, u_int8_t *protonum) { - unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; - unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; - int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, - (*pskb)->len - extoff); + unsigned int extoff = nhoff + sizeof(struct ipv6hdr); + unsigned char pnum; + int protoff; + + if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), + &pnum, sizeof(pnum)) != 0) { + pr_debug("ip6_conntrack_core: can't get nexthdr\n"); + return -NF_ACCEPT; + } + protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff); /* - * (protoff == (*pskb)->len) mean that the packet doesn't have no data + * (protoff == skb->len) mean that the packet doesn't have no data * except of IPv6 & ext headers. but it's tracked anyway. - YK */ - if ((protoff < 0) || (protoff > (*pskb)->len)) { + if ((protoff < 0) || (protoff > skb->len)) { pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); return -NF_ACCEPT; } @@ -375,7 +380,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .invert_tuple = ipv6_invert_tuple, .print_tuple = ipv6_print_tuple, .print_conntrack = ipv6_print_conntrack, - .prepare = ipv6_prepare, + .get_l4proto = ipv6_get_l4proto, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv6_tuple_to_nfattr, .nfattr_to_tuple = ipv6_nfattr_to_tuple, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b730413738a6..5b194e3c4e25 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -622,8 +622,9 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) /* rcu_read_lock()ed by nf_hook_slow */ l3proto = __nf_ct_l3proto_find((u_int16_t)pf); - - if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) { + ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), + &dataoff, &protonum); + if (ret <= 0) { pr_debug("not prepared to track yet or error occured\n"); NF_CT_STAT_INC_ATOMIC(error); NF_CT_STAT_INC_ATOMIC(invalid); diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index b1bfa207a850..0691642b7724 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -61,9 +61,8 @@ static int generic_print_conntrack(struct seq_file *s, return 0; } -static int -generic_prepare(struct sk_buff **pskb, unsigned int hooknum, - unsigned int *dataoff, u_int8_t *protonum) +static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, + unsigned int *dataoff, u_int8_t *protonum) { /* Never track !!! */ return -NF_ACCEPT; @@ -77,6 +76,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { .invert_tuple = generic_invert_tuple, .print_tuple = generic_print_tuple, .print_conntrack = generic_print_conntrack, - .prepare = generic_prepare, + .get_l4proto = generic_get_l4proto, }; EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); -- cgit v1.2.3 From e2a3123fbe58da9fd3f35cd242087896ace6049f Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 14 Jul 2007 20:45:14 -0700 Subject: [NETFILTER]: nf_conntrack: Introduces nf_ct_get_tuplepr and uses it nf_ct_get_tuple() requires the offset to transport header and that bothers callers such as icmp[v6] l4proto modules. This introduces new function to simplify them. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 4 +++ net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 32 +++++--------------- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 42 +++++--------------------- net/netfilter/nf_conntrack_core.c | 30 ++++++++++++++++++ 4 files changed, 49 insertions(+), 59 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index d4f02eb0c66c..810020ec345d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -186,6 +186,10 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_conntrack_flush(void); +extern int nf_ct_get_tuplepr(const struct sk_buff *skb, + unsigned int nhoff, + u_int16_t l3num, + struct nf_conntrack_tuple *tuple); extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 0fe8fb0466ef..b8b79992797e 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -136,40 +136,22 @@ icmp_error_message(struct sk_buff *skb, unsigned int hooknum) { struct nf_conntrack_tuple innertuple, origtuple; - struct { - struct icmphdr icmp; - struct iphdr ip; - } _in, *inside; struct nf_conntrack_l4proto *innerproto; struct nf_conntrack_tuple_hash *h; - int dataoff; NF_CT_ASSERT(skb->nfct == NULL); - /* Not enough header? */ - inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in); - if (inside == NULL) - return -NF_ACCEPT; - - /* Ignore ICMP's containing fragments (shouldn't happen) */ - if (inside->ip.frag_off & htons(IP_OFFSET)) { - pr_debug("icmp_error_message: fragment of proto %u\n", - inside->ip.protocol); + /* Are they talking about one of our connections? */ + if (!nf_ct_get_tuplepr(skb, + skb_network_offset(skb) + ip_hdrlen(skb) + + sizeof(struct icmphdr), + PF_INET, &origtuple)) { + pr_debug("icmp_error_message: failed to get tuple\n"); return -NF_ACCEPT; } /* rcu_read_lock()ed by nf_hook_slow */ - innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); - - dataoff = ip_hdrlen(skb) + sizeof(inside->icmp); - /* Are they talking about one of our connections? */ - if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, - inside->ip.protocol, &origtuple, - &nf_conntrack_l3proto_ipv4, innerproto)) { - pr_debug("icmp_error_message: ! get_tuple p=%u", - inside->ip.protocol); - return -NF_ACCEPT; - } + innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum); /* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */ diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9defc7e14554..0fca7e8abeb7 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -136,49 +136,23 @@ icmpv6_error_message(struct sk_buff *skb, { struct nf_conntrack_tuple intuple, origtuple; struct nf_conntrack_tuple_hash *h; - struct icmp6hdr _hdr, *hp; - unsigned int inip6off; struct nf_conntrack_l4proto *inproto; - u_int8_t inprotonum; - unsigned int inprotoff; NF_CT_ASSERT(skb->nfct == NULL); - hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr); - if (hp == NULL) { - pr_debug("icmpv6_error: Can't get ICMPv6 hdr.\n"); - return -NF_ACCEPT; - } - - inip6off = icmp6off + sizeof(_hdr); - if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr), - &inprotonum, sizeof(inprotonum)) != 0) { - pr_debug("icmpv6_error: Can't get nexthdr in inner IPv6 " - "header.\n"); - return -NF_ACCEPT; - } - inprotoff = nf_ct_ipv6_skip_exthdr(skb, - inip6off + sizeof(struct ipv6hdr), - &inprotonum, - skb->len - inip6off - - sizeof(struct ipv6hdr)); - - if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) { - pr_debug("icmpv6_error: Can't get protocol header in ICMPv6 " - "payload.\n"); - return -NF_ACCEPT; - } - - /* rcu_read_lock()ed by nf_hook_slow */ - inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum); - /* Are they talking about one of our connections? */ - if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, - &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) { + if (!nf_ct_get_tuplepr(skb, + skb_network_offset(skb) + + sizeof(struct ipv6hdr) + + sizeof(struct icmp6hdr), + PF_INET6, &origtuple)) { pr_debug("icmpv6_error: Can't get tuple\n"); return -NF_ACCEPT; } + /* rcu_read_lock()ed by nf_hook_slow */ + inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum); + /* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */ if (!nf_ct_invert_tuple(&intuple, &origtuple, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 5b194e3c4e25..8cce814f6bee 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -113,6 +113,36 @@ nf_ct_get_tuple(const struct sk_buff *skb, } EXPORT_SYMBOL_GPL(nf_ct_get_tuple); +int nf_ct_get_tuplepr(const struct sk_buff *skb, + unsigned int nhoff, + u_int16_t l3num, + struct nf_conntrack_tuple *tuple) +{ + struct nf_conntrack_l3proto *l3proto; + struct nf_conntrack_l4proto *l4proto; + unsigned int protoff; + u_int8_t protonum; + int ret; + + rcu_read_lock(); + + l3proto = __nf_ct_l3proto_find(l3num); + ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum); + if (ret != NF_ACCEPT) { + rcu_read_unlock(); + return 0; + } + + l4proto = __nf_ct_l4proto_find(l3num, protonum); + + ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple, + l3proto, l4proto); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr); + int nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig, -- cgit v1.2.3 From 61075af51f252913401c41fbe94075b46c94e9f1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 14 Jul 2007 20:48:19 -0700 Subject: [NETFILTER]: nf_conntrack: mark protocols __read_mostly Also remove two unnecessary EXPORT_SYMBOLs and move the nf_conntrack_l3proto_ipv4 declaration to the correct file. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 2 ++ include/net/netfilter/nf_conntrack_l3proto.h | 2 -- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 3 +-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 4 +--- net/netfilter/nf_conntrack_l3proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 4 ++-- net/netfilter/nf_conntrack_proto_tcp.c | 4 ++-- net/netfilter/nf_conntrack_proto_udp.c | 4 ++-- 12 files changed, 15 insertions(+), 18 deletions(-) (limited to 'include/net') diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 3ed4e14970c5..7a671603fca6 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -12,6 +12,8 @@ /* Returns new sk_buff, or NULL */ struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); +extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index e3708a698d8b..3c58a2c4df28 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -89,8 +89,6 @@ extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); /* Existing built-in protocols */ -extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; -extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic; static inline struct nf_conntrack_l3proto * diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index ee29f4e9eac2..64552afd01cb 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -405,7 +405,7 @@ static struct nf_sockopt_ops so_getorigdst = { .get = &getorigdst, }; -struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { +struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { .l3proto = PF_INET, .name = "ipv4", .pkt_to_tuple = ipv4_pkt_to_tuple, diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index f96573304f5b..6593fd2c5b10 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -312,7 +312,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = +struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = { .l3proto = PF_INET, .l4proto = IPPROTO_ICMP, @@ -338,4 +338,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = #endif #endif }; -EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 9b7eaaadc67e..36df2218b669 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -373,7 +373,7 @@ static int ipv6_nfattr_to_tuple(struct nfattr *tb[], } #endif -struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { +struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { .l3proto = PF_INET6, .name = "ipv6", .pkt_to_tuple = ipv6_pkt_to_tuple, diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 0fca7e8abeb7..ab154fb90018 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -276,7 +276,7 @@ static struct ctl_table icmpv6_sysctl_table[] = { }; #endif /* CONFIG_SYSCTL */ -struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = { .l3proto = PF_INET6, .l4proto = IPPROTO_ICMPV6, @@ -297,5 +297,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .ctl_table = icmpv6_sysctl_table, #endif }; - -EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 0691642b7724..991c52c9a28b 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -69,7 +69,7 @@ static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, } -struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { +struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = { .l3proto = PF_UNSPEC, .name = "unknown", .pkt_to_tuple = generic_pkt_to_tuple, diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 6faf1bed7224..d8b501878d9f 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -98,7 +98,7 @@ static struct ctl_table generic_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = +struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = { .l3proto = PF_UNSPEC, .l4proto = 0, diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 771c4c29936e..bdbead8a7a83 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -261,7 +261,7 @@ static void gre_destroy(struct nf_conn *ct) } /* protocol helper struct */ -static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { +static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { .l3proto = AF_INET, .l4proto = IPPROTO_GRE, .name = "gre", diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index debfe61378a1..04192acc7c40 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -601,7 +601,7 @@ static struct ctl_table sctp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { +static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { .l3proto = PF_INET, .l4proto = IPPROTO_SCTP, .name = "sctp", @@ -622,7 +622,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { #endif }; -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { +static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { .l3proto = PF_INET6, .l4proto = IPPROTO_SCTP, .name = "sctp", diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 1c8206e6560a..87ad3ccf8aff 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1372,7 +1372,7 @@ static struct ctl_table tcp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = { .l3proto = PF_INET, .l4proto = IPPROTO_TCP, @@ -1401,7 +1401,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); -struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = { .l3proto = PF_INET6, .l4proto = IPPROTO_TCP, diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 3620ecc095fd..13d94a025723 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -191,7 +191,7 @@ static struct ctl_table udp_compat_sysctl_table[] = { #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ -struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = { .l3proto = PF_INET, .l4proto = IPPROTO_UDP, @@ -218,7 +218,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = }; EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); -struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = { .l3proto = PF_INET6, .l4proto = IPPROTO_UDP, -- cgit v1.2.3 From 73ca4918fbb98311421259d82ef4ab44feeace43 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 15 Jul 2007 00:02:31 -0700 Subject: [NET_SCHED]: act_api: qdisc internal reclassify support The behaviour of NET_CLS_POLICE for TC_POLICE_RECLASSIFY was to return it to the qdisc, which could handle it internally or ignore it. With NET_CLS_ACT however, tc_classify starts over at the first classifier and never returns it to the qdisc. This makes it impossible to support qdisc-internal reclassification, which in turn makes it impossible to remove the old NET_CLS_POLICE code without breaking compatibility since we have two qdiscs (CBQ and ATM) that support this. This patch adds a tc_classify_compat function that handles reclassification the old way and changes CBQ and ATM to use it. This again is of course not fully backwards compatible with the previous NET_CLS_ACT behaviour. Unfortunately there is no way to fully maintain compatibility *and* support qdisc internal reclassification with NET_CLS_ACT, but this seems like the better choice over keeping the two incompatible options around forever. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 4 ++- include/net/sch_generic.h | 2 +- net/sched/sch_api.c | 67 +++++++++++++++++++++++++++-------------------- net/sched/sch_atm.c | 11 ++++++-- net/sched/sch_cbq.c | 39 ++++++++++++++------------- net/sched/sch_tbf.c | 2 +- 6 files changed, 73 insertions(+), 52 deletions(-) (limited to 'include/net') diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 5754d53d9efc..9e22526e80e7 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -89,8 +89,10 @@ static inline void qdisc_run(struct net_device *dev) __qdisc_run(dev); } +extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, + struct tcf_result *res); extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, - struct tcf_result *res); + struct tcf_result *res); /* Calculate maximal size of packet seen by hard_start_xmit routine of this device. diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 1b8e35197ebe..0153cd9d1b8d 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -290,7 +290,7 @@ static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch) { sch->qstats.drops++; -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) goto drop; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 4fd0beca9450..13c09bc32aa3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1145,47 +1145,57 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) to this qdisc, (optionally) tests for protocol and asks specific classifiers. */ +int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, + struct tcf_result *res) +{ + __be16 protocol = skb->protocol; + int err = 0; + + for (; tp; tp = tp->next) { + if ((tp->protocol == protocol || + tp->protocol == htons(ETH_P_ALL)) && + (err = tp->classify(skb, tp, res)) >= 0) { +#ifdef CONFIG_NET_CLS_ACT + if (err != TC_ACT_RECLASSIFY && skb->tc_verd) + skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); +#endif + return err; + } + } + return -1; +} +EXPORT_SYMBOL(tc_classify_compat); + int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, - struct tcf_result *res) + struct tcf_result *res) { int err = 0; - __be16 protocol = skb->protocol; + __be16 protocol; #ifdef CONFIG_NET_CLS_ACT struct tcf_proto *otp = tp; reclassify: #endif protocol = skb->protocol; - for ( ; tp; tp = tp->next) { - if ((tp->protocol == protocol || - tp->protocol == htons(ETH_P_ALL)) && - (err = tp->classify(skb, tp, res)) >= 0) { + err = tc_classify_compat(skb, tp, res); #ifdef CONFIG_NET_CLS_ACT - if ( TC_ACT_RECLASSIFY == err) { - __u32 verd = (__u32) G_TC_VERD(skb->tc_verd); - tp = otp; - - if (MAX_REC_LOOP < verd++) { - printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n", - tp->prio&0xffff, ntohs(tp->protocol)); - return TC_ACT_SHOT; - } - skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd); - goto reclassify; - } else { - if (skb->tc_verd) - skb->tc_verd = SET_TC_VERD(skb->tc_verd,0); - return err; - } -#else - - return err; -#endif + if (err == TC_ACT_RECLASSIFY) { + u32 verd = G_TC_VERD(skb->tc_verd); + tp = otp; + + if (verd++ >= MAX_REC_LOOP) { + printk("rule prio %u protocol %02x reclassify loop, " + "packet dropped\n", + tp->prio&0xffff, ntohs(tp->protocol)); + return TC_ACT_SHOT; } - + skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); + goto reclassify; } - return -1; +#endif + return err; } +EXPORT_SYMBOL(tc_classify); void tcf_destroy(struct tcf_proto *tp) { @@ -1252,4 +1262,3 @@ EXPORT_SYMBOL(qdisc_get_rtab); EXPORT_SYMBOL(qdisc_put_rtab); EXPORT_SYMBOL(register_qdisc); EXPORT_SYMBOL(unregister_qdisc); -EXPORT_SYMBOL(tc_classify); diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index ccee10dae66d..37ae6d1deb14 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -396,8 +396,9 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) for (flow = p->flows; flow; flow = flow->next) if (flow->filter_list) { - result = tc_classify(skb, flow->filter_list, - &res); + result = tc_classify_compat(skb, + flow->filter_list, + &res); if (result < 0) continue; flow = (struct atm_flow_data *)res.class; @@ -420,6 +421,12 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) case TC_ACT_SHOT: kfree_skb(skb); goto drop; + case TC_POLICE_RECLASSIFY: + if (flow->excess) + flow = flow->excess; + else + ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP; + break; } #elif defined(CONFIG_NET_CLS_POLICE) switch (result) { diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index b184c3545145..77381f1c6541 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -82,7 +82,7 @@ struct cbq_class unsigned char priority2; /* priority to be used after overlimit */ unsigned char ewma_log; /* time constant for idle time calculation */ unsigned char ovl_strategy; -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) unsigned char police; #endif @@ -154,7 +154,7 @@ struct cbq_sched_data struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes with backlog */ -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) struct cbq_class *rx_class; #endif struct cbq_class *tx_class; @@ -196,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid) return NULL; } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) static struct cbq_class * cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) @@ -247,7 +247,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) /* * Step 2+n. Apply classifier. */ - if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0) + if (!head->filter_list || + (result = tc_classify_compat(skb, head->filter_list, &res)) < 0) goto fallback; if ((cl = (void*)res.class) == NULL) { @@ -267,6 +268,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) *qerr = NET_XMIT_SUCCESS; case TC_ACT_SHOT: return NULL; + case TC_ACT_RECLASSIFY: + return cbq_reclassify(skb, cl); } #elif defined(CONFIG_NET_CLS_POLICE) switch (result) { @@ -389,7 +392,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) int ret; struct cbq_class *cl = cbq_classify(skb, sch, &ret); -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) q->rx_class = cl; #endif if (cl == NULL) { @@ -399,7 +402,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) return ret; } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) cl->q->__parent = sch; #endif if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { @@ -434,7 +437,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) cbq_mark_toplevel(q, cl); -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) q->rx_class = cl; cl->q->__parent = sch; #endif @@ -670,7 +673,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) { @@ -1364,7 +1367,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) return 0; } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) { cl->police = p->police; @@ -1532,7 +1535,7 @@ rtattr_failure: return -1; } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) { unsigned char *b = skb_tail_pointer(skb); @@ -1558,7 +1561,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl) cbq_dump_rate(skb, cl) < 0 || cbq_dump_wrr(skb, cl) < 0 || cbq_dump_ovl(skb, cl) < 0 || -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) cbq_dump_police(skb, cl) < 0 || #endif cbq_dump_fopt(skb, cl) < 0) @@ -1653,7 +1656,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, cl->classid)) == NULL) return -ENOBUFS; } else { -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (cl->police == TC_POLICE_RECLASSIFY) new->reshape_fail = cbq_reshape_fail; #endif @@ -1718,7 +1721,7 @@ cbq_destroy(struct Qdisc* sch) struct cbq_class *cl; unsigned h; -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) q->rx_class = NULL; #endif /* @@ -1747,7 +1750,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg) struct cbq_class *cl = (struct cbq_class*)arg; if (--cl->refcnt == 0) { -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) struct cbq_sched_data *q = qdisc_priv(sch); spin_lock_bh(&sch->dev->queue_lock); @@ -1795,7 +1798,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) return -EINVAL; -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (tb[TCA_CBQ_POLICE-1] && RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) return -EINVAL; @@ -1838,7 +1841,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t if (tb[TCA_CBQ_OVL_STRATEGY-1]) cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (tb[TCA_CBQ_POLICE-1]) cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); #endif @@ -1931,7 +1934,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t cl->overlimit = cbq_ovl_classic; if (tb[TCA_CBQ_OVL_STRATEGY-1]) cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (tb[TCA_CBQ_POLICE-1]) cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); #endif @@ -1975,7 +1978,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) q->tx_class = NULL; q->tx_borrowed = NULL; } -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (q->rx_class == cl) q->rx_class = NULL; #endif diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 22e431dace54..b8b3345cede8 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -125,7 +125,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) if (skb->len > q->max_size) { sch->qstats.drops++; -#ifdef CONFIG_NET_CLS_POLICE +#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) #endif kfree_skb(skb); -- cgit v1.2.3 From c3bc7cff8fddb6ff9715be8bfc3d911378c4d69d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 15 Jul 2007 00:03:05 -0700 Subject: [NET_SCHED]: Kill CONFIG_NET_CLS_POLICE The NET_CLS_ACT option is now a full replacement for NET_CLS_POLICE, remove the old code. The config option will be kept around to select the equivalent NET_CLS_ACT options for a short time to allow easier upgrades. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/act_api.h | 30 ------ include/net/pkt_cls.h | 8 -- include/net/sch_generic.h | 2 +- net/sched/Kconfig | 8 +- net/sched/Makefile | 1 - net/sched/act_police.c | 246 +++------------------------------------------- net/sched/cls_api.c | 40 -------- net/sched/cls_u32.c | 3 - net/sched/sch_atm.c | 19 +--- net/sched/sch_cbq.c | 45 ++++----- net/sched/sch_dsmark.c | 13 +-- net/sched/sch_hfsc.c | 3 - net/sched/sch_htb.c | 3 - net/sched/sch_ingress.c | 19 ---- net/sched/sch_tbf.c | 2 +- 15 files changed, 38 insertions(+), 404 deletions(-) (limited to 'include/net') diff --git a/include/net/act_api.h b/include/net/act_api.h index 2f0273feabd3..68b4eaf7719d 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -121,34 +121,4 @@ extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, in extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int); #endif /* CONFIG_NET_CLS_ACT */ - -extern int tcf_police(struct sk_buff *skb, struct tcf_police *p); -extern void tcf_police_destroy(struct tcf_police *p); -extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est); -extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p); -extern int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p); - -static inline int -tcf_police_release(struct tcf_police *p, int bind) -{ - int ret = 0; -#ifdef CONFIG_NET_CLS_ACT - if (p) { - if (bind) - p->tcf_bindcnt--; - - p->tcf_refcnt--; - if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { - tcf_police_destroy(p); - ret = 1; - } - } -#else - if (p && --p->tcf_refcnt == 0) - tcf_police_destroy(p); - -#endif /* CONFIG_NET_CLS_ACT */ - return ret; -} - #endif diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 6c29920cbe29..7968b1d66369 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -65,8 +65,6 @@ struct tcf_exts { #ifdef CONFIG_NET_CLS_ACT struct tc_action *action; -#elif defined CONFIG_NET_CLS_POLICE - struct tcf_police *police; #endif }; @@ -91,8 +89,6 @@ tcf_exts_is_predicative(struct tcf_exts *exts) { #ifdef CONFIG_NET_CLS_ACT return !!exts->action; -#elif defined CONFIG_NET_CLS_POLICE - return !!exts->police; #else return 0; #endif @@ -129,11 +125,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, #ifdef CONFIG_NET_CLS_ACT if (exts->action) return tcf_action_exec(skb, exts->action, res); -#elif defined CONFIG_NET_CLS_POLICE - if (exts->police) - return tcf_police(skb, exts->police); #endif - return 0; } diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 0153cd9d1b8d..8a67f24cbe02 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -290,7 +290,7 @@ static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch) { sch->qstats.drops++; -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) goto drop; diff --git a/net/sched/Kconfig b/net/sched/Kconfig index b4662888bdbd..d3f7c3f9407a 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -472,12 +472,12 @@ config NET_ACT_SIMP config NET_CLS_POLICE bool "Traffic Policing (obsolete)" - depends on NET_CLS_ACT!=y + select NET_CLS_ACT + select NET_ACT_POLICE ---help--- Say Y here if you want to do traffic policing, i.e. strict - bandwidth limiting. This option is obsoleted by the traffic - policer implemented as action, it stays here for compatibility - reasons. + bandwidth limiting. This option is obsolete and just selects + the option replacing it. It will be removed in the future. config NET_CLS_IND bool "Incoming device classification" diff --git a/net/sched/Makefile b/net/sched/Makefile index 020767a204d4..b67c36f65cf2 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o obj-$(CONFIG_NET_CLS) += cls_api.o obj-$(CONFIG_NET_CLS_ACT) += act_api.o obj-$(CONFIG_NET_ACT_POLICE) += act_police.o -obj-$(CONFIG_NET_CLS_POLICE) += act_police.o obj-$(CONFIG_NET_ACT_GACT) += act_gact.o obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o diff --git a/net/sched/act_police.c b/net/sched/act_police.c index d20403890877..bf90e60f8411 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -50,7 +50,6 @@ struct tc_police_compat /* Each policer is serialized by its individual spinlock */ -#ifdef CONFIG_NET_CLS_ACT static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a) { @@ -96,9 +95,8 @@ rtattr_failure: nlmsg_trim(skb, r); goto done; } -#endif -void tcf_police_destroy(struct tcf_police *p) +static void tcf_police_destroy(struct tcf_police *p) { unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); struct tcf_common **p1p; @@ -121,7 +119,6 @@ void tcf_police_destroy(struct tcf_police *p) BUG_TRAP(0); } -#ifdef CONFIG_NET_CLS_ACT static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind) { @@ -247,10 +244,19 @@ failure: static int tcf_act_police_cleanup(struct tc_action *a, int bind) { struct tcf_police *p = a->priv; + int ret = 0; - if (p != NULL) - return tcf_police_release(p, bind); - return 0; + if (p != NULL) { + if (bind) + p->tcf_bindcnt--; + + p->tcf_refcnt--; + if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { + tcf_police_destroy(p); + ret = 1; + } + } + return ret; } static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, @@ -372,229 +378,3 @@ police_cleanup_module(void) module_init(police_init_module); module_exit(police_cleanup_module); - -#else /* CONFIG_NET_CLS_ACT */ - -static struct tcf_common *tcf_police_lookup(u32 index) -{ - struct tcf_hashinfo *hinfo = &police_hash_info; - struct tcf_common *p; - - read_lock(hinfo->lock); - for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; - p = p->tcfc_next) { - if (p->tcfc_index == index) - break; - } - read_unlock(hinfo->lock); - - return p; -} - -static u32 tcf_police_new_index(void) -{ - u32 *idx_gen = &police_idx_gen; - u32 val = *idx_gen; - - do { - if (++val == 0) - val = 1; - } while (tcf_police_lookup(val)); - - return (*idx_gen = val); -} - -struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) -{ - unsigned int h; - struct tcf_police *police; - struct rtattr *tb[TCA_POLICE_MAX]; - struct tc_police *parm; - int size; - - if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) - return NULL; - - if (tb[TCA_POLICE_TBF-1] == NULL) - return NULL; - size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]); - if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) - return NULL; - - parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); - - if (parm->index) { - struct tcf_common *pc; - - pc = tcf_police_lookup(parm->index); - if (pc) { - police = to_police(pc); - police->tcf_refcnt++; - return police; - } - } - police = kzalloc(sizeof(*police), GFP_KERNEL); - if (unlikely(!police)) - return NULL; - - police->tcf_refcnt = 1; - spin_lock_init(&police->tcf_lock); - if (parm->rate.rate) { - police->tcfp_R_tab = - qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); - if (police->tcfp_R_tab == NULL) - goto failure; - if (parm->peakrate.rate) { - police->tcfp_P_tab = - qdisc_get_rtab(&parm->peakrate, - tb[TCA_POLICE_PEAKRATE-1]); - if (police->tcfp_P_tab == NULL) - goto failure; - } - } - if (tb[TCA_POLICE_RESULT-1]) { - if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) - goto failure; - police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); - } - if (tb[TCA_POLICE_AVRATE-1]) { - if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) - goto failure; - police->tcfp_ewma_rate = - *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); - } - police->tcfp_toks = police->tcfp_burst = parm->burst; - police->tcfp_mtu = parm->mtu; - if (police->tcfp_mtu == 0) { - police->tcfp_mtu = ~0; - if (police->tcfp_R_tab) - police->tcfp_mtu = 255<tcfp_R_tab->rate.cell_log; - } - if (police->tcfp_P_tab) - police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); - police->tcfp_t_c = psched_get_time(); - police->tcf_index = parm->index ? parm->index : - tcf_police_new_index(); - police->tcf_action = parm->action; - if (est) - gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, - &police->tcf_lock, est); - h = tcf_hash(police->tcf_index, POL_TAB_MASK); - write_lock_bh(&police_lock); - police->tcf_next = tcf_police_ht[h]; - tcf_police_ht[h] = &police->common; - write_unlock_bh(&police_lock); - return police; - -failure: - if (police->tcfp_R_tab) - qdisc_put_rtab(police->tcfp_R_tab); - kfree(police); - return NULL; -} - -int tcf_police(struct sk_buff *skb, struct tcf_police *police) -{ - psched_time_t now; - long toks; - long ptoks = 0; - - spin_lock(&police->tcf_lock); - - police->tcf_bstats.bytes += skb->len; - police->tcf_bstats.packets++; - - if (police->tcfp_ewma_rate && - police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; - } - if (skb->len <= police->tcfp_mtu) { - if (police->tcfp_R_tab == NULL) { - spin_unlock(&police->tcf_lock); - return police->tcfp_result; - } - - now = psched_get_time(); - toks = psched_tdiff_bounded(now, police->tcfp_t_c, - police->tcfp_burst); - if (police->tcfp_P_tab) { - ptoks = toks + police->tcfp_ptoks; - if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) - ptoks = (long)L2T_P(police, police->tcfp_mtu); - ptoks -= L2T_P(police, skb->len); - } - toks += police->tcfp_toks; - if (toks > (long)police->tcfp_burst) - toks = police->tcfp_burst; - toks -= L2T(police, skb->len); - if ((toks|ptoks) >= 0) { - police->tcfp_t_c = now; - police->tcfp_toks = toks; - police->tcfp_ptoks = ptoks; - spin_unlock(&police->tcf_lock); - return police->tcfp_result; - } - } - - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; -} -EXPORT_SYMBOL(tcf_police); - -int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) -{ - unsigned char *b = skb_tail_pointer(skb); - struct tc_police opt; - - opt.index = police->tcf_index; - opt.action = police->tcf_action; - opt.mtu = police->tcfp_mtu; - opt.burst = police->tcfp_burst; - if (police->tcfp_R_tab) - opt.rate = police->tcfp_R_tab->rate; - else - memset(&opt.rate, 0, sizeof(opt.rate)); - if (police->tcfp_P_tab) - opt.peakrate = police->tcfp_P_tab->rate; - else - memset(&opt.peakrate, 0, sizeof(opt.peakrate)); - RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (police->tcfp_result) - RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), - &police->tcfp_result); - if (police->tcfp_ewma_rate) - RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); - return skb->len; - -rtattr_failure: - nlmsg_trim(skb, b); - return -1; -} - -int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) -{ - struct gnet_dump d; - - if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, - TCA_XSTATS, &police->tcf_lock, - &d) < 0) - goto errout; - - if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 || - gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 || - gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0) - goto errout; - - if (gnet_stats_finish_copy(&d) < 0) - goto errout; - - return 0; - -errout: - return -1; -} - -#endif /* CONFIG_NET_CLS_ACT */ diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 36b72aab1bde..5f0fbca7393f 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -458,11 +458,6 @@ tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) tcf_action_destroy(exts->action, TCA_ACT_UNBIND); exts->action = NULL; } -#elif defined CONFIG_NET_CLS_POLICE - if (exts->police) { - tcf_police_release(exts->police, TCA_ACT_UNBIND); - exts->police = NULL; - } #endif } @@ -496,17 +491,6 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb, exts->action = act; } } -#elif defined CONFIG_NET_CLS_POLICE - if (map->police && tb[map->police-1]) { - struct tcf_police *p; - - p = tcf_police_locate(tb[map->police-1], rate_tlv); - if (p == NULL) - return -EINVAL; - - exts->police = p; - } else if (map->action && tb[map->action-1]) - return -EOPNOTSUPP; #else if ((map->action && tb[map->action-1]) || (map->police && tb[map->police-1])) @@ -529,15 +513,6 @@ tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, if (act) tcf_action_destroy(act, TCA_ACT_UNBIND); } -#elif defined CONFIG_NET_CLS_POLICE - if (src->police) { - struct tcf_police *p; - tcf_tree_lock(tp); - p = xchg(&dst->police, src->police); - tcf_tree_unlock(tp); - if (p) - tcf_police_release(p, TCA_ACT_UNBIND); - } #endif } @@ -566,17 +541,6 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; } } -#elif defined CONFIG_NET_CLS_POLICE - if (map->police && exts->police) { - struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); - - RTA_PUT(skb, map->police, 0, NULL); - - if (tcf_police_dump(skb, exts->police) < 0) - goto rtattr_failure; - - p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; - } #endif return 0; rtattr_failure: __attribute__ ((unused)) @@ -591,10 +555,6 @@ tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, if (exts->action) if (tcf_action_copy_stats(skb, exts->action, 1) < 0) goto rtattr_failure; -#elif defined CONFIG_NET_CLS_POLICE - if (exts->police) - if (tcf_police_dump_stats(skb, exts->police) < 0) - goto rtattr_failure; #endif return 0; rtattr_failure: __attribute__ ((unused)) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 77961e2314dc..8dbe36912ecb 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -782,9 +782,6 @@ static int __init init_u32(void) #ifdef CONFIG_CLS_U32_PERF printk(" Performance counters on\n"); #endif -#ifdef CONFIG_NET_CLS_POLICE - printk(" OLD policer on \n"); -#endif #ifdef CONFIG_NET_CLS_IND printk(" input device check on \n"); #endif diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 37ae6d1deb14..417ec8fb7f1a 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -428,26 +428,9 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP; break; } -#elif defined(CONFIG_NET_CLS_POLICE) - switch (result) { - case TC_POLICE_SHOT: - kfree_skb(skb); - goto drop; - case TC_POLICE_RECLASSIFY: - if (flow->excess) - flow = flow->excess; - else { - ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP; - break; - } - /* fall through */ - case TC_POLICE_OK: - /* fall through */ - default: - break; - } #endif } + if ((ret = flow->q->enqueue(skb, flow->q)) != 0) { drop: __maybe_unused sch->qstats.drops++; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 77381f1c6541..e38c2839b25c 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -82,7 +82,7 @@ struct cbq_class unsigned char priority2; /* priority to be used after overlimit */ unsigned char ewma_log; /* time constant for idle time calculation */ unsigned char ovl_strategy; -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT unsigned char police; #endif @@ -154,7 +154,7 @@ struct cbq_sched_data struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes with backlog */ -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT struct cbq_class *rx_class; #endif struct cbq_class *tx_class; @@ -196,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid) return NULL; } -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT static struct cbq_class * cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) @@ -271,15 +271,6 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) case TC_ACT_RECLASSIFY: return cbq_reclassify(skb, cl); } -#elif defined(CONFIG_NET_CLS_POLICE) - switch (result) { - case TC_POLICE_RECLASSIFY: - return cbq_reclassify(skb, cl); - case TC_POLICE_SHOT: - return NULL; - default: - break; - } #endif if (cl->level == 0) return cl; @@ -392,7 +383,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) int ret; struct cbq_class *cl = cbq_classify(skb, sch, &ret); -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT q->rx_class = cl; #endif if (cl == NULL) { @@ -402,7 +393,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) return ret; } -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT cl->q->__parent = sch; #endif if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { @@ -437,7 +428,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) cbq_mark_toplevel(q, cl); -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT q->rx_class = cl; cl->q->__parent = sch; #endif @@ -672,9 +663,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) return HRTIMER_NORESTART; } - -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) - +#ifdef CONFIG_NET_CLS_ACT static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) { int len = skb->len; @@ -1367,7 +1356,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) return 0; } -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) { cl->police = p->police; @@ -1535,7 +1524,7 @@ rtattr_failure: return -1; } -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) { unsigned char *b = skb_tail_pointer(skb); @@ -1561,7 +1550,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl) cbq_dump_rate(skb, cl) < 0 || cbq_dump_wrr(skb, cl) < 0 || cbq_dump_ovl(skb, cl) < 0 || -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT cbq_dump_police(skb, cl) < 0 || #endif cbq_dump_fopt(skb, cl) < 0) @@ -1656,7 +1645,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, cl->classid)) == NULL) return -ENOBUFS; } else { -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (cl->police == TC_POLICE_RECLASSIFY) new->reshape_fail = cbq_reshape_fail; #endif @@ -1721,7 +1710,7 @@ cbq_destroy(struct Qdisc* sch) struct cbq_class *cl; unsigned h; -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT q->rx_class = NULL; #endif /* @@ -1750,7 +1739,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg) struct cbq_class *cl = (struct cbq_class*)arg; if (--cl->refcnt == 0) { -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT struct cbq_sched_data *q = qdisc_priv(sch); spin_lock_bh(&sch->dev->queue_lock); @@ -1798,7 +1787,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) return -EINVAL; -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (tb[TCA_CBQ_POLICE-1] && RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) return -EINVAL; @@ -1841,7 +1830,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t if (tb[TCA_CBQ_OVL_STRATEGY-1]) cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (tb[TCA_CBQ_POLICE-1]) cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); #endif @@ -1934,7 +1923,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t cl->overlimit = cbq_ovl_classic; if (tb[TCA_CBQ_OVL_STRATEGY-1]) cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (tb[TCA_CBQ_POLICE-1]) cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); #endif @@ -1978,7 +1967,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) q->tx_class = NULL; q->tx_borrowed = NULL; } -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (q->rx_class == cl) q->rx_class = NULL; #endif diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 2d7e891e6b0d..60f89199e3da 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -246,21 +246,10 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) kfree_skb(skb); sch->qstats.drops++; return NET_XMIT_BYPASS; -#elif defined(CONFIG_NET_CLS_POLICE) - case TC_POLICE_SHOT: - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_POLICED; -#if 0 - case TC_POLICE_RECLASSIFY: - /* FIXME: what to do here ??? */ -#endif #endif - case TC_POLICE_OK: + case TC_ACT_OK: skb->tc_index = TC_H_MIN(res.classid); break; - case TC_POLICE_UNSPEC: - /* fall through */ default: if (p->default_index != NO_DEFAULT_INDEX) skb->tc_index = p->default_index; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 874452c41a01..55e7e4530f43 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1174,9 +1174,6 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) case TC_ACT_SHOT: return NULL; } -#elif defined(CONFIG_NET_CLS_POLICE) - if (result == TC_POLICE_SHOT) - return NULL; #endif if ((cl = (struct hfsc_class *)res.class) == NULL) { if ((cl = hfsc_find_class(res.classid, sch)) == NULL) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index b417a95df322..246a2f9765f1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -249,9 +249,6 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, case TC_ACT_SHOT: return NULL; } -#elif defined(CONFIG_NET_CLS_POLICE) - if (result == TC_POLICE_SHOT) - return HTB_DIRECT; #endif if ((cl = (void *)res.class) == NULL) { if (res.classid == sch->handle) diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index cd0aab6a2a7c..51f16b0af198 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c @@ -164,30 +164,11 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch) result = TC_ACT_OK; break; } -/* backward compat */ -#else -#ifdef CONFIG_NET_CLS_POLICE - switch (result) { - case TC_POLICE_SHOT: - result = NF_DROP; - sch->qstats.drops++; - break; - case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */ - case TC_POLICE_OK: - case TC_POLICE_UNSPEC: - default: - sch->bstats.packets++; - sch->bstats.bytes += skb->len; - result = NF_ACCEPT; - break; - } - #else D2PRINTK("Overriding result to ACCEPT\n"); result = NF_ACCEPT; sch->bstats.packets++; sch->bstats.bytes += skb->len; -#endif #endif return result; diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index b8b3345cede8..8c2639af4c6a 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -125,7 +125,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) if (skb->len > q->max_size) { sch->qstats.drops++; -#if defined(CONFIG_NET_CLS_ACT) || defined(CONFIG_NET_CLS_POLICE) +#ifdef CONFIG_NET_CLS_ACT if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) #endif kfree_skb(skb); -- cgit v1.2.3 From c09edd6eba683741bb8aa8e388a2bfaf1c1a28f9 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 17 Jul 2007 04:03:48 -0700 Subject: avoid OPEN_MAX in SCM_MAX_FD The OPEN_MAX constant is an arbitrary number with no useful relation to anything. Nothing should be using it. SCM_MAX_FD is just an arbitrary constant and it should be clear that its value is chosen in net/scm.h and not actually derived from anything else meaningful in the system. Signed-off-by: Roland McGrath Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/net/scm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/net/scm.h b/include/net/scm.h index 5637d5e22d5f..423cb1d5ac25 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -8,7 +8,7 @@ /* Well, we should have at least one descriptor open * to accept passed FDs 8) */ -#define SCM_MAX_FD (OPEN_MAX-1) +#define SCM_MAX_FD 255 struct scm_fp_list { -- cgit v1.2.3 From 16751347a060a10c09b11593bb179fd5b0240c04 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 16 Jul 2007 18:35:52 -0700 Subject: [TCP]: remove unused argument to cong_avoid op None of the existing TCP congestion controls use the rtt value pased in the ca_ops->cong_avoid interface. Which is lucky because seq_rtt could have been -1 when handling a duplicate ack. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/tcp.h | 6 ++---- net/ipv4/tcp_bic.c | 2 +- net/ipv4/tcp_cong.c | 3 +-- net/ipv4/tcp_cubic.c | 2 +- net/ipv4/tcp_highspeed.c | 2 +- net/ipv4/tcp_htcp.c | 2 +- net/ipv4/tcp_hybla.c | 4 ++-- net/ipv4/tcp_illinois.c | 2 +- net/ipv4/tcp_input.c | 8 ++++---- net/ipv4/tcp_lp.c | 5 ++--- net/ipv4/tcp_scalable.c | 2 +- net/ipv4/tcp_vegas.c | 6 +++--- net/ipv4/tcp_veno.c | 6 +++--- net/ipv4/tcp_yeah.c | 2 +- 14 files changed, 24 insertions(+), 28 deletions(-) (limited to 'include/net') diff --git a/include/net/tcp.h b/include/net/tcp.h index a8af9ae00177..8b404b1ef7c8 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -652,8 +652,7 @@ struct tcp_congestion_ops { /* lower bound for congestion window (optional) */ u32 (*min_cwnd)(const struct sock *sk); /* do new cwnd calculation (required) */ - void (*cong_avoid)(struct sock *sk, u32 ack, - u32 rtt, u32 in_flight, int good_ack); + void (*cong_avoid)(struct sock *sk, u32 ack, u32 in_flight, int good_ack); /* call before changing ca_state (optional) */ void (*set_state)(struct sock *sk, u8 new_state); /* call when cwnd event occurs (optional) */ @@ -684,8 +683,7 @@ extern void tcp_slow_start(struct tcp_sock *tp); extern struct tcp_congestion_ops tcp_init_congestion_ops; extern u32 tcp_reno_ssthresh(struct sock *sk); -extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack, - u32 rtt, u32 in_flight, int flag); +extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag); extern u32 tcp_reno_min_cwnd(const struct sock *sk); extern struct tcp_congestion_ops tcp_reno; diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index dd9ef65ad3ff..519de091a94d 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c @@ -137,7 +137,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) } static void bictcp_cong_avoid(struct sock *sk, u32 ack, - u32 seq_rtt, u32 in_flight, int data_acked) + u32 in_flight, int data_acked) { struct tcp_sock *tp = tcp_sk(sk); struct bictcp *ca = inet_csk_ca(sk); diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 1260e52ad772..55fca1820c34 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -324,8 +324,7 @@ EXPORT_SYMBOL_GPL(tcp_slow_start); /* This is Jacobson's slow start and congestion avoidance. * SIGCOMM '88, p. 328. */ -void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight, - int flag) +void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index ebfaac2f9f46..d17da30d82d6 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -270,7 +270,7 @@ static inline void measure_delay(struct sock *sk) } static void bictcp_cong_avoid(struct sock *sk, u32 ack, - u32 seq_rtt, u32 in_flight, int data_acked) + u32 in_flight, int data_acked) { struct tcp_sock *tp = tcp_sk(sk); struct bictcp *ca = inet_csk_ca(sk); diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index 43d624e5043c..14a073d8b60f 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c @@ -109,7 +109,7 @@ static void hstcp_init(struct sock *sk) tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128); } -static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, +static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 in_flight, int data_acked) { struct tcp_sock *tp = tcp_sk(sk); diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 4ba4a7ae0a85..632c05a75883 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -225,7 +225,7 @@ static u32 htcp_recalc_ssthresh(struct sock *sk) return max((tp->snd_cwnd * ca->beta) >> 7, 2U); } -static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, +static void htcp_cong_avoid(struct sock *sk, u32 ack, s32 rtt, u32 in_flight, int data_acked) { struct tcp_sock *tp = tcp_sk(sk); diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c index e5be35117223..b3e55cf56171 100644 --- a/net/ipv4/tcp_hybla.c +++ b/net/ipv4/tcp_hybla.c @@ -85,7 +85,7 @@ static inline u32 hybla_fraction(u32 odds) * o Give cwnd a new value based on the model proposed * o remember increments <1 */ -static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 rtt, +static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); @@ -103,7 +103,7 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 rtt, return; if (!ca->hybla_en) - return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); + return tcp_reno_cong_avoid(sk, ack, in_flight, flag); if (ca->rho == 0) hybla_recalc_param(sk); diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index b2b2256d3b84..cc5de6f69d46 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -258,7 +258,7 @@ static void tcp_illinois_state(struct sock *sk, u8 new_state) /* * Increase window in response to successful acknowledgment. */ -static void tcp_illinois_cong_avoid(struct sock *sk, u32 ack, u32 rtt, +static void tcp_illinois_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4e5884ac8f29..fec8a7a4dbaf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2323,11 +2323,11 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag, tcp_ack_no_tstamp(sk, seq_rtt, flag); } -static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, +static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int good) { const struct inet_connection_sock *icsk = inet_csk(sk); - icsk->icsk_ca_ops->cong_avoid(sk, ack, rtt, in_flight, good); + icsk->icsk_ca_ops->cong_avoid(sk, ack, in_flight, good); tcp_sk(sk)->snd_cwnd_stamp = tcp_time_stamp; } @@ -2826,11 +2826,11 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) /* Advance CWND, if state allows this. */ if ((flag & FLAG_DATA_ACKED) && !frto_cwnd && tcp_may_raise_cwnd(sk, flag)) - tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 0); + tcp_cong_avoid(sk, ack, prior_in_flight, 0); tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) - tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 1); + tcp_cong_avoid(sk, ack, prior_in_flight, 1); } if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP)) diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index e49836ce012e..80e140e3ec2d 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c @@ -115,13 +115,12 @@ static void tcp_lp_init(struct sock *sk) * Will only call newReno CA when away from inference. * From TCP-LP's paper, this will be handled in additive increasement. */ -static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight, - int flag) +static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag) { struct lp *lp = inet_csk_ca(sk); if (!(lp->flag & LP_WITHIN_INF)) - tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); + tcp_reno_cong_avoid(sk, ack, in_flight, flag); } /** diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 4624501e9680..be27a33a1c68 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c @@ -15,7 +15,7 @@ #define TCP_SCALABLE_AI_CNT 50U #define TCP_SCALABLE_MD_SCALE 3 -static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 rtt, +static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index e218a51ceced..914e0307f7af 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c @@ -163,13 +163,13 @@ void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event) EXPORT_SYMBOL_GPL(tcp_vegas_cwnd_event); static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, - u32 seq_rtt, u32 in_flight, int flag) + u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); struct vegas *vegas = inet_csk_ca(sk); if (!vegas->doing_vegas_now) - return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + return tcp_reno_cong_avoid(sk, ack, in_flight, flag); /* The key players are v_beg_snd_una and v_beg_snd_nxt. * @@ -228,7 +228,7 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, /* We don't have enough RTT samples to do the Vegas * calculation, so we'll behave like Reno. */ - tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + tcp_reno_cong_avoid(sk, ack, in_flight, flag); } else { u32 rtt, target_cwnd, diff; diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index ec854cc5fad5..7a55ddf86032 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c @@ -115,13 +115,13 @@ static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event) } static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, - u32 seq_rtt, u32 in_flight, int flag) + u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); struct veno *veno = inet_csk_ca(sk); if (!veno->doing_veno_now) - return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + return tcp_reno_cong_avoid(sk, ack, in_flight, flag); /* limited by applications */ if (!tcp_is_cwnd_limited(sk, in_flight)) @@ -132,7 +132,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, /* We don't have enough rtt samples to do the Veno * calculation, so we'll behave like Reno. */ - tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + tcp_reno_cong_avoid(sk, ack, in_flight, flag); } else { u32 rtt, target_cwnd; diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index 545ed237ab53..c04b7c6ec702 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c @@ -70,7 +70,7 @@ static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, ktime_t last) } static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, - u32 seq_rtt, u32 in_flight, int flag) + u32 in_flight, int flag) { struct tcp_sock *tp = tcp_sk(sk); struct yeah *yeah = inet_csk_ca(sk); -- cgit v1.2.3 From bd0bf0765ea1fba80d7085e1f0375ec045631dc1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 18 Jul 2007 01:55:52 -0700 Subject: [XFRM]: Fix crash introduced by struct dst_entry reordering XFRM expects xfrm_dst->u.next to be same pointer as dst->next, which was broken by the dst_entry reordering in commit 1e19e02c~, causing an oops in xfrm_bundle_ok when walking the bundle upwards. Kill xfrm_dst->u.next and change the only user to use dst->next instead. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/xfrm.h | 1 - net/xfrm/xfrm_policy.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'include/net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ae959e950174..a5f80bfbaaa4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -585,7 +585,6 @@ static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ct struct xfrm_dst { union { - struct xfrm_dst *next; struct dst_entry dst; struct rtable rt; struct rt6_info rt6; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 157bfbd250ba..b48f06fc9fd9 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2141,7 +2141,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, if (last == first) break; - last = last->u.next; + last = (struct xfrm_dst *)last->u.dst.next; last->child_mtu_cached = mtu; } -- cgit v1.2.3