From efa53ebe0d2f50bf342eb1976824f59bba9941eb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 13 Nov 2006 11:32:50 +0800 Subject: [PATCH] ieee80211: Fix kernel panic when QoS is enabled The 802.11 header length is affected by the wireless mode (WDS or not) and type (QoS or not). We should use the variable hdr_len instead of the hard coded IEEE80211_3ADDR_LEN, otherwise we may touch invalid memory. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index ae254497ba3d..854fc13cd78d 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -390,7 +390,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account * for it when determining the amount of payload space. */ - bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; + bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; @@ -412,7 +412,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } else { nr_frags = 1; bytes_per_frag = bytes_last_frag = bytes; - frag_size = bytes + IEEE80211_3ADDR_LEN; + frag_size = bytes + hdr_len; } rts_required = (frag_size > ieee->rts -- cgit v1.2.3-70-g09d2 From 38f7efd52c4f3f0b22c460eadbfe7c42f9ebff82 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 21 Nov 2006 21:46:02 -0800 Subject: [NETFILTER]: H.323 conntrack: fix crash with CONFIG_IP_NF_CT_ACCT H.323 connection tracking code calls ip_ct_refresh_acct() when processing RCFs and URQs but passes NULL as the skb. When CONFIG_IP_NF_CT_ACCT is enabled, the connection tracking core tries to derefence the skb, which results in an obvious panic. A similar fix was applied on the SIP connection tracking code some time ago. Signed-off-by: Faidon Liambotis Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_helper_h323.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 7b7441202bfd..6cb9070cd0bc 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -1417,7 +1417,7 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, DEBUGP ("ip_ct_ras: set RAS connection timeout to %u seconds\n", info->timeout); - ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ); + ip_ct_refresh(ct, *pskb, info->timeout * HZ); /* Set expect timeout */ read_lock_bh(&ip_conntrack_lock); @@ -1465,7 +1465,7 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, info->sig_port[!dir] = 0; /* Give it 30 seconds for UCF or URJ */ - ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ); + ip_ct_refresh(ct, *pskb, 30 * HZ); return 0; } -- cgit v1.2.3-70-g09d2 From 753eab76a3337863a0d86ce045fa4eb6c3cbeef9 Mon Sep 17 00:00:00 2001 From: Olaf Kirch Date: Wed, 22 Nov 2006 20:11:42 -0800 Subject: [UDP]: Make udp_encap_rcv use pskb_may_pull Make udp_encap_rcv use pskb_may_pull IPsec with NAT-T breaks on some notebooks using the latest e1000 chipset, when header split is enabled. When receiving sufficiently large packets, the driver puts everything up to and including the UDP header into the header portion of the skb, and the rest goes into the paged part. udp_encap_rcv forgets to use pskb_may_pull, and fails to decapsulate it. Instead, it passes it up it to the IKE daemon. Signed-off-by: Olaf Kirch Signed-off-by: Jean Delvare Signed-off-by: David S. Miller --- net/ipv4/udp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 865d75214a9a..9e1bd374875e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -928,23 +928,32 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) return 1; #else struct udp_sock *up = udp_sk(sk); - struct udphdr *uh = skb->h.uh; + struct udphdr *uh; struct iphdr *iph; int iphlen, len; - __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr); - __be32 *udpdata32 = (__be32 *)udpdata; + __u8 *udpdata; + __be32 *udpdata32; __u16 encap_type = up->encap_type; /* if we're overly short, let UDP handle it */ - if (udpdata > skb->tail) + 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; - len = skb->tail - udpdata; + /* 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 = skb->h.uh; + udpdata = (__u8 *)uh + sizeof(struct udphdr); + udpdata32 = (__be32 *)udpdata; switch (encap_type) { default: -- cgit v1.2.3-70-g09d2 From ac16ca6412d9feb5b2f8fc76a4ed938b5d107f94 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 22 Nov 2006 20:26:11 -0800 Subject: [NET]: Fix kfifo_alloc() error check. The return value of kfifo_alloc() should be checked by IS_ERR(). Signed-off-by: Akinobu Mita Signed-off-by: David S. Miller --- net/dccp/probe.c | 2 ++ net/ipv4/tcp_probe.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'net') diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 146496fce2e2..fded1493c1dc 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -160,6 +160,8 @@ static __init int dccpprobe_init(void) init_waitqueue_head(&dccpw.wait); spin_lock_init(&dccpw.lock); dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock); + if (IS_ERR(dccpw.fifo)) + return PTR_ERR(dccpw.fifo); if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops)) goto err0; diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 4be336f17883..f230eeecf092 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -156,6 +156,8 @@ static __init int tcpprobe_init(void) init_waitqueue_head(&tcpw.wait); spin_lock_init(&tcpw.lock); tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); + if (IS_ERR(tcpw.fifo)) + return PTR_ERR(tcpw.fifo); if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) goto err0; -- cgit v1.2.3-70-g09d2 From 9abbffee861c6c56fce27e4eda96a10cf0de0f84 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Fri, 24 Nov 2006 20:34:51 -0800 Subject: [XFRM] STATE: Fix to respond error to get operation if no matching entry exists. When application uses XFRM_MSG_GETSA to get state entry through netlink socket and kernel has no matching one, the application expects reply message with error status by kernel. Kernel doesn't send the message back in the case of Mobile IPv6 route optimization protocols (i.e. routing header or destination options header). This is caused by incorrect return code "0" from net/xfrm/xfrm_user.c(xfrm_user_state_lookup) and it makes kernel skip to acknowledge at net/netlink/af_netlink.c(netlink_rcv_skb). This patch fix to reply ESRCH to application. Signed-off-by: Masahide NAKAMURA Signed-off-by: TAKAMIYA Noriaki Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c4cde57d9216..2ee14f8a1908 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -495,6 +495,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, goto out; } + err = -ESRCH; x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, p->family); } -- cgit v1.2.3-70-g09d2 From a3df3b6f2e37474cdb8b56d55d31be41c22f9b18 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 27 Nov 2006 14:37:21 -0600 Subject: [PATCH] softmac: remove netif_tx_disable when scanning In the scan section of ieee80211softmac, network transmits are disabled. When SoftMAC re-enables transmits, it may override the wishes of a driver that may have very good reasons for disabling transmits. At least one failure in bcm43xx can be traced to this problem. In addition, several unexplained problems may arise from the unexpected enabling of transmits. Note that making this change introduces a new bug that would allow transmits for the current session to be transmitted on the wrong channel; however, the new bug is much less severe than the one being fixed, as the new one only leads to a few retransmits, whereas the old one can bring the interface down. A fix that will not introduce new bugs is being investigated; however, the current, more serious one should be fixed now. Signed-off-by: Michael Buesch Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_scan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net') diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index d31cf77498c4..ad67368b58ed 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,7 +47,6 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); - netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -248,7 +247,6 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } - netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); -- cgit v1.2.3-70-g09d2 From ba8379b220509e9448c00a77cf6c15ac2a559cc7 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 20 Nov 2006 15:02:49 -0800 Subject: [PATCH] bridge: fix possible overflow in get_fdb_entries Make sure to properly clamp maxnum to avoid overflow Signed-off-by: Chris Wright Acked-by: Eugene Teo Acked-by: Marcel Holtmann Signed-off-by: Linus Torvalds --- net/bridge/br_ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 4e4119a12139..4c61a7e0a86e 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -58,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, { int num; void *buf; - size_t size = maxnum * sizeof(struct __fdb_entry); + size_t size; - if (size > PAGE_SIZE) { - size = PAGE_SIZE; + /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */ + if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry)) maxnum = PAGE_SIZE/sizeof(struct __fdb_entry); - } + + size = maxnum * sizeof(struct __fdb_entry); buf = kmalloc(size, GFP_USER); if (!buf) -- cgit v1.2.3-70-g09d2 From dafc741cf23351a6f43895579a72ab8818ba00ae Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:25:32 -0800 Subject: [NETFILTER]: nfctnetlink: assign helper to newly created conntrack This fixes the bug which doesn't assign helper to newly created conntrack via nf_conntrack_netlink. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bd0156a28ecd..77a46eef66c1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -949,6 +949,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], { struct nf_conn *ct; int err = -EINVAL; + struct nf_conn_help *help; ct = nf_conntrack_alloc(otuple, rtuple); if (ct == NULL || IS_ERR(ct)) @@ -976,9 +977,16 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif + help = nfct_help(ct); + if (help) + help->helper = nf_ct_helper_find_get(rtuple); + add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); + if (help && help->helper) + nf_ct_helper_put(help->helper); + return 0; err: -- cgit v1.2.3-70-g09d2 From 22e7410b760b9c1777839fdd10382c60df8cbda2 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:25:59 -0800 Subject: [NETFILTER]: nf_conntrack: fix the race on assign helper to new conntrack The found helper cannot be assigned to conntrack after unlocking nf_conntrack_lock. This tries to find helper to assign again. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 836541e509fe..0f5830779b44 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -893,12 +893,6 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, memset(conntrack, 0, nf_ct_cache[features].size); conntrack->features = features; - if (helper) { - struct nf_conn_help *help = nfct_help(conntrack); - NF_CT_ASSERT(help); - help->helper = helper; - } - atomic_set(&conntrack->ct_general.use, 1); conntrack->ct_general.destroy = destroy_conntrack; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; @@ -982,8 +976,13 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, #endif nf_conntrack_get(&conntrack->master->ct_general); NF_CT_STAT_INC(expect_new); - } else + } else { + struct nf_conn_help *help = nfct_help(conntrack); + + if (help) + help->helper = __nf_ct_helper_find(&repl_tuple); NF_CT_STAT_INC(new); + } /* Overload tuple linked list to put us in unconfirmed list. */ list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); -- cgit v1.2.3-70-g09d2 From c537b75a3ba9f5d2569f313742cd379dff6ceb70 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 27 Nov 2006 10:26:25 -0800 Subject: [NETFILTER]: ctnetlink: fix reference count leak When NFA_NEST exceeds the skb size the protocol reference is leaked. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netlink.c | 1 + net/netfilter/nf_conntrack_netlink.c | 1 + 2 files changed, 2 insertions(+) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 262d0d44ec1b..55f0ae641081 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -153,6 +153,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct) return ret; nfattr_failure: + ip_conntrack_proto_put(proto); return -1; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 77a46eef66c1..ab67c2be2b5d 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -161,6 +161,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) return ret; nfattr_failure: + nf_ct_proto_put(proto); return -1; } -- cgit v1.2.3-70-g09d2 From 2e47c264a2e6ea24c27b4987607222202818c1f4 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:26:46 -0800 Subject: [NETFILTER]: conntrack: fix refcount leak when finding expectation All users of __{ip,nf}_conntrack_expect_find() don't expect that it increments the reference count of expectation. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 6 +++--- net/netfilter/nf_conntrack_core.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 143c4668538b..8b848aa77bfc 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -225,10 +225,8 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) struct ip_conntrack_expect *i; list_for_each_entry(i, &ip_conntrack_expect_list, list) { - if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { - atomic_inc(&i->use); + if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; - } } return NULL; } @@ -241,6 +239,8 @@ ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) read_lock_bh(&ip_conntrack_lock); i = __ip_conntrack_expect_find(tuple); + if (i) + atomic_inc(&i->use); read_unlock_bh(&ip_conntrack_lock); return i; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0f5830779b44..de0567b1f422 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -469,10 +469,8 @@ __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) struct nf_conntrack_expect *i; list_for_each_entry(i, &nf_conntrack_expect_list, list) { - if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { - atomic_inc(&i->use); + if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; - } } return NULL; } @@ -485,6 +483,8 @@ nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) read_lock_bh(&nf_conntrack_lock); i = __nf_conntrack_expect_find(tuple); + if (i) + atomic_inc(&i->use); read_unlock_bh(&nf_conntrack_lock); return i; -- cgit v1.2.3-70-g09d2 From af443b6d90de17f7630621269cf0610d9d772670 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 28 Nov 2006 20:10:21 -0800 Subject: [NETFILTER]: ipt_REJECT: fix memory corruption On devices with hard_header_len > LL_MAX_HEADER ip_route_me_harder() reallocates the skb, leading to memory corruption when using the stale tcph pointer to update the checksum. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_REJECT.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index ad0312d0e4fd..264763adc39b 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -114,6 +114,14 @@ static void send_reset(struct sk_buff *oldskb, int hook) tcph->window = 0; tcph->urg_ptr = 0; + /* Adjust TCP checksum */ + tcph->check = 0; + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), + nskb->nh.iph->saddr, + nskb->nh.iph->daddr, + csum_partial((char *)tcph, + sizeof(struct tcphdr), 0)); + /* Set DF, id = 0 */ nskb->nh.iph->frag_off = htons(IP_DF); nskb->nh.iph->id = 0; @@ -129,14 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook) if (ip_route_me_harder(&nskb, addr_type)) goto free_nskb; - /* Adjust TCP checksum */ nskb->ip_summed = CHECKSUM_NONE; - tcph->check = 0; - tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), - nskb->nh.iph->saddr, - nskb->nh.iph->daddr, - csum_partial((char *)tcph, - sizeof(struct tcphdr), 0)); + /* Adjust IP TTL */ nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); -- cgit v1.2.3-70-g09d2 From 0779bf2d2ecc4d9b1e9437ae659f50e6776a7666 Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 05:24:39 +0100 Subject: Fix misc .c/.h comment typos Fix various .c/.h typos in comments (no code changes). Signed-off-by: Matt LaPlante Signed-off-by: Adrian Bunk --- arch/cris/arch-v10/drivers/eeprom.c | 6 +++--- arch/cris/arch-v10/drivers/i2c.c | 2 +- arch/cris/arch-v10/kernel/kgdb.c | 2 +- arch/ia64/hp/common/sba_iommu.c | 8 ++++---- arch/sh64/lib/dbg.c | 2 +- drivers/atm/iphase.c | 2 +- drivers/char/rio/riocmd.c | 2 +- drivers/char/rio/rioinit.c | 2 +- drivers/char/rio/rioparam.c | 6 +++--- drivers/ide/ide-floppy.c | 2 +- drivers/isdn/hardware/eicon/os_4bri.c | 2 +- drivers/isdn/hisax/hfc4s8s_l1.h | 2 +- drivers/media/dvb/ttpci/budget-patch.c | 8 ++++---- drivers/net/e100.c | 2 +- drivers/net/e1000/e1000_hw.c | 2 +- drivers/net/sk98lin/h/skdrv2nd.h | 2 +- drivers/net/sk98lin/skdim.c | 4 ++-- drivers/net/wireless/ipw2200.c | 4 ++-- drivers/parisc/ccio-dma.c | 2 +- drivers/parisc/iosapic.c | 6 +++--- drivers/pci/hotplug/ibmphp_hpc.c | 2 +- drivers/s390/net/claw.h | 2 +- drivers/scsi/aic94xx/aic94xx_reg_def.h | 2 +- drivers/scsi/aic94xx/aic94xx_sds.c | 4 ++-- drivers/scsi/ncr53c8xx.c | 14 +++++++------- drivers/scsi/ncr53c8xx.h | 6 +++--- drivers/usb/host/u132-hcd.c | 6 +++--- drivers/usb/misc/usb_u132.h | 2 +- drivers/usb/serial/digi_acceleport.c | 2 +- fs/reiserfs/journal.c | 6 +++--- include/asm-m68knommu/mcfmbus.h | 2 +- include/asm-parisc/dma.h | 6 +++--- include/asm-parisc/pci.h | 2 +- include/asm-parisc/ropes.h | 2 +- include/linux/ixjuser.h | 2 +- include/linux/reiserfs_fs_sb.h | 2 +- net/wanrouter/af_wanpipe.c | 4 ++-- net/wanrouter/wanmain.c | 2 +- sound/oss/cs46xx.c | 6 +++--- 39 files changed, 71 insertions(+), 71 deletions(-) (limited to 'net') diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index 6e1f191a71e3..284ebfda03f0 100644 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ b/arch/cris/arch-v10/drivers/eeprom.c @@ -1,7 +1,7 @@ /*!***************************************************************************** *! -*! Implements an interface for i2c compatible eeproms to run under linux. -*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustents by +*! Implements an interface for i2c compatible eeproms to run under Linux. +*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustments by *! Johan.Adolfsson@axis.com *! *! Probing results: @@ -51,7 +51,7 @@ *! Revision 1.8 2001/06/15 13:24:29 jonashg *! * Added verification of pointers from userspace in read and write. *! * Made busy counter volatile. -*! * Added define for inital write delay. +*! * Added define for initial write delay. *! * Removed warnings by using loff_t instead of unsigned long. *! *! Revision 1.7 2001/06/14 15:26:54 jonashg diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 6114596c3b33..092c724a645f 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -47,7 +47,7 @@ *! Update Port B register and shadow even when running with hardware support *! to avoid glitches when reading bits *! Never set direction to out in i2c_inbyte -*! Removed incorrect clock togling at end of i2c_inbyte +*! Removed incorrect clock toggling at end of i2c_inbyte *! *! Revision 1.8 2002/08/13 06:31:53 starvik *! Made SDA and SCL line configurable diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c index 34528da98817..07628a13c6c4 100644 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ b/arch/cris/arch-v10/kernel/kgdb.c @@ -33,7 +33,7 @@ *! *! Revision 1.2 2002/11/19 14:35:24 starvik *! Changes from linux 2.4 -*! Changed struct initializer syntax to the currently prefered notation +*! Changed struct initializer syntax to the currently preferred notation *! *! Revision 1.1 2001/12/17 13:59:27 bjornw *! Initial revision diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index db8e1fcfa047..14691cda05c3 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -75,7 +75,7 @@ ** If a device prefetches beyond the end of a valid pdir entry, it will cause ** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should ** disconnect on 4k boundaries and prevent such issues. If the device is -** particularly agressive, this option will keep the entire pdir valid such +** particularly aggressive, this option will keep the entire pdir valid such ** that prefetching will hit a valid address. This could severely impact ** error containment, and is therefore off by default. The page that is ** used for spill-over is poisoned, so that should help debugging somewhat. @@ -258,10 +258,10 @@ static u64 prefetch_spill_page; /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up -** (or rather not merge) DMA's into managable chunks. +** (or rather not merge) DMAs into manageable chunks. ** On parisc, this is more of the software/tuning constraint -** rather than the HW. I/O MMU allocation alogorithms can be -** faster with smaller size is (to some degree). +** rather than the HW. I/O MMU allocation algorithms can be +** faster with smaller sizes (to some degree). */ #define DMA_CHUNK_SIZE (BITS_PER_LONG*iovp_size) diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c index 1326f45f31eb..4310fc87444e 100644 --- a/arch/sh64/lib/dbg.c +++ b/arch/sh64/lib/dbg.c @@ -383,7 +383,7 @@ void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs) /* ======================================================================= */ /* -** Depending on scan the MMU, Data or Instrction side +** Depending on scan the MMU, Data or Instruction side ** looking for a valid mapping matching Eaddr & asid. ** Return -1 if not found or the TLB id entry otherwise. ** Note: it works only for 4k pages! diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 9ed1c60048f0..bb7ef570514c 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -305,7 +305,7 @@ static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) { ** | R | NZ | 5-bit exponent | 9-bit mantissa | ** +----+----+------------------+-------------------------------+ ** -** R = reserverd (written as 0) +** R = reserved (written as 0) ** NZ = 0 if 0 cells/sec; 1 otherwise ** ** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 4df6ab2206a1..167ebc84e8d7 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -922,7 +922,7 @@ int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) ** ** Packet is an actual packet structure to be filled in with the packet ** information associated with the command. You need to fill in everything, -** as the command processore doesn't process the command packet in any way. +** as the command processor doesn't process the command packet in any way. ** ** The PreFuncP is called before the packet is enqueued on the host rup. ** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 99f3df02b61c..0794844369d6 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -222,7 +222,7 @@ int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, i ** which value will be written into memory. ** Call with op set to zero means that the RAM will not be read and checked ** before it is written. -** Call with op not zero, and the RAM will be read and compated with val[op-1] +** Call with op not zero and the RAM will be read and compared with val[op-1] ** to check that the data from the previous phase was retained. */ diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index 1066d9760704..bb498d24adcc 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -87,8 +87,8 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; ** command bit set onto the port. The command bit is in the len field, ** and gets ORed in with the actual byte count. ** -** When you send a packet with the command bit set, then the first -** data byte ( data[0] ) is interpretted as the command to execute. +** When you send a packet with the command bit set the first +** data byte (data[0]) is interpreted as the command to execute. ** It also governs what data structure overlay should accompany the packet. ** Commands are defined in cirrus/cirrus.h ** @@ -103,7 +103,7 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; ** ** Most commands do not use the remaining bytes in the data array. The ** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and -** OPEN are currently analagous). With these three commands the following +** OPEN are currently analogous). With these three commands the following ** 11 data bytes are all used to pass config information such as baud rate etc. ** The fields are also defined in cirrus.h. Some contain straightforward ** information such as the transmit XON character. Two contain the transmit and diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 8ccee9c769f8..e3a267622bb6 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1635,7 +1635,7 @@ static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg) /* ** Get ATAPI_FORMAT_UNIT progress indication. ** -** Userland gives a pointer to an int. The int is set to a progresss +** Userland gives a pointer to an int. The int is set to a progress ** indicator 0-65536, with 65536=100%. ** ** If the drive does not support format progress indication, we just check diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c index 11e6f937c1e4..7b4ec3f60dbf 100644 --- a/drivers/isdn/hardware/eicon/os_4bri.c +++ b/drivers/isdn/hardware/eicon/os_4bri.c @@ -464,7 +464,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a) /* ** Cleanup function will be called for master adapter only -** this is garanteed by design: cleanup callback is set +** this is guaranteed by design: cleanup callback is set ** by master adapter only */ static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a) diff --git a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h index e8f9c077fa85..9d5d2a56b4e9 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.h +++ b/drivers/isdn/hisax/hfc4s8s_l1.h @@ -16,7 +16,7 @@ /* * include Genero generated HFC-4S/8S header file hfc48scu.h -* for comlete register description. This will define _HFC48SCU_H_ +* for complete register description. This will define _HFC48SCU_H_ * to prevent redefinitions */ diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index fc1267b8c892..9a155396d6ac 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -500,14 +500,14 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte /* New design (By Emard) ** this rps1 code will copy internal HS event to GPIO3 pin. -** GPIO3 is in budget-patch hardware connectd to port B VSYNC +** GPIO3 is in budget-patch hardware connected to port B VSYNC ** HS is an internal event of 7146, accessible with RPS ** and temporarily raised high every n lines ** (n in defined in the RPS_THRESH1 counter threshold) ** I think HS is raised high on the beginning of the n-th line ** and remains high until this n-th line that triggered -** it is completely received. When the receiption of n-th line +** it is completely received. When the reception of n-th line ** ends, HS is lowered. ** To transmit data over DMA, 7146 needs changing state at @@ -541,7 +541,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ** hardware debug note: a working budget card (including budget patch) ** with vpeirq() interrupt setup in mode "0x90" (every 64K) will ** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes -** and that means 3*25=75 Hz of interrupt freqency, as seen by +** and that means 3*25=75 Hz of interrupt frequency, as seen by ** watch cat /proc/interrupts ** ** If this frequency is 3x lower (and data received in the DMA @@ -550,7 +550,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ** this means VSYNC line is not connected in the hardware. ** (check soldering pcb and pins) ** The same behaviour of missing VSYNC can be duplicated on budget -** cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. +** cards, by setting DD1_INIT trigger mode 7 in 3rd nibble. */ // Setup RPS1 "program" (p35) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 19ab3441269c..3a8df479cbda 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1215,7 +1215,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb * the literal in the instruction before the code is loaded, the * driver can change the algorithm. * -* INTDELAY - This loads the dead-man timer with its inital value. +* INTDELAY - This loads the dead-man timer with its initial value. * When this timer expires the interrupt is asserted, and the * timer is reset each time a new packet is received. (see * BUNDLEMAX below to set the limit on number of chained packets) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 65077f39da69..796c4f7d4260 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -3868,7 +3868,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code * -* Sets bit 15 of the MII Control regiser +* Sets bit 15 of the MII Control register ******************************************************************************/ int32_t e1000_phy_reset(struct e1000_hw *hw) diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h index 778d9e618ebd..3fa67171e832 100644 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ b/drivers/net/sk98lin/h/skdrv2nd.h @@ -160,7 +160,7 @@ struct s_IOCTL { /* ** Interim definition of SK_DRV_TIMER placed in this file until -** common modules have boon finallized +** common modules have been finalized */ #define SK_DRV_TIMER 11 #define SK_DRV_MODERATION_TIMER 1 diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c index 07c1b4c8699d..37ce03fb8de3 100644 --- a/drivers/net/sk98lin/skdim.c +++ b/drivers/net/sk98lin/skdim.c @@ -252,7 +252,7 @@ SkDimEnableModerationIfNeeded(SK_AC *pAC) { /******************************************************************************* ** Function : SkDimDisplayModerationSettings -** Description : Displays the current settings regaring interrupt moderation +** Description : Displays the current settings regarding interrupt moderation ** Programmer : Ralph Roesler ** Last Modified: 22-mar-03 ** Returns : void (!) @@ -510,7 +510,7 @@ EnableIntMod(SK_AC *pAC) { /******************************************************************************* ** Function : DisableIntMod() -** Description : Disbles the interrupt moderation independent of what inter- +** Description : Disables the interrupt moderation independent of what inter- ** rupts are running or not ** Programmer : Ralph Roesler ** Last Modified: 23-mar-03 diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 1f742814a01c..72120d5c2f7b 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6920,8 +6920,8 @@ static int ipw_qos_association(struct ipw_priv *priv, } /* -* handling the beaconing responces. if we get different QoS setting -* of the network from the the associated setting adjust the QoS +* handling the beaconing responses. if we get different QoS setting +* off the network from the associated setting, adjust the QoS * setting */ static int ipw_qos_association_resp(struct ipw_priv *priv, diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 68cb3a080050..fe3f5f5365c5 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -486,7 +486,7 @@ typedef unsigned long space_t; ** This bit tells U2 to do R/M/W for partial cachelines. "Streaming" ** data can avoid this if the mapping covers full cache lines. ** o STOP_MOST is needed for atomicity across cachelines. -** Apperently only "some EISA devices" need this. +** Apparently only "some EISA devices" need this. ** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs ** to use this hint iff the EISA devices needs this feature. ** According to the U2 ERS, STOP_MOST enabled pages hurt performance. diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index c2949b4367e5..12bab64a62a1 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -50,12 +50,12 @@ ** ** PA Firmware ** ----------- -** PA-RISC platforms have two fundementally different types of firmware. +** PA-RISC platforms have two fundamentally different types of firmware. ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register ** and BARs similar to a traditional PC BIOS. ** The newer "PAT" firmware supports PDC calls which return tables. -** PAT firmware only initializes PCI Console and Boot interface. -** With these tables, the OS can progam all other PCI devices. +** PAT firmware only initializes the PCI Console and Boot interface. +** With these tables, the OS can program all other PCI devices. ** ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT). ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index c3ac98a0a6a6..f55ac3885cb3 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -531,7 +531,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index) * * Action: issue a READ command to HPC * -* Input: pslot - can not be NULL for READ_ALLSTAT +* Input: pslot - cannot be NULL for READ_ALLSTAT * pstatus - can be NULL for READ_ALLSTAT * * Return 0 or error codes diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 969be465309c..1ee9a6f06541 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -29,7 +29,7 @@ #define CLAW_COMPLETE 0xff /* flag to indicate i/o completed */ /*-----------------------------------------------------* -* CLAW control comand code * +* CLAW control command code * *------------------------------------------------------*/ #define SYSTEM_VALIDATE_REQUEST 0x01 /* System Validate request */ diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index b79f45f3ad47..a11f4e6d8bd9 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h @@ -2000,7 +2000,7 @@ * The host accesses this scratch in a different manner from the * central sequencer. The sequencer has to use CSEQ registers CSCRPAGE * and CMnSCRPAGE to access the scratch memory. A flat mapping of the - * scratch memory is avaliable for software convenience and to prevent + * scratch memory is available for software convenience and to prevent * corruption while the sequencer is running. This memory is mapped * onto addresses 800h - BFFh, total of 400h bytes. * diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index de7c04d4254d..e5a0ec37e954 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -64,7 +64,7 @@ struct asd_ocm_dir { #define OCM_INIT_DIR_ENTRIES 5 /*************************************************************************** -* OCM dircetory default +* OCM directory default ***************************************************************************/ static struct asd_ocm_dir OCMDirInit = { @@ -73,7 +73,7 @@ static struct asd_ocm_dir OCMDirInit = }; /*************************************************************************** -* OCM dircetory Entries default +* OCM directory Entries default ***************************************************************************/ static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] = { diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 6cc2bc2f62be..adb8eb4f5fd1 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -185,7 +185,7 @@ static inline struct list_head *ncr_list_pop(struct list_head *head) ** power of 2 cache line size. ** Enhanced in linux-2.3.44 to provide a memory pool ** per pcidev to support dynamic dma mapping. (I would -** have preferred a real bus astraction, btw). +** have preferred a real bus abstraction, btw). ** **========================================================== */ @@ -1438,7 +1438,7 @@ struct head { ** The first four bytes (scr_st[4]) are used inside the script by ** "COPY" commands. ** Because source and destination must have the same alignment -** in a DWORD, the fields HAVE to be at the choosen offsets. +** in a DWORD, the fields HAVE to be at the chosen offsets. ** xerr_st 0 (0x34) scratcha ** sync_st 1 (0x05) sxfer ** wide_st 3 (0x03) scntl3 @@ -1498,7 +1498,7 @@ struct head { ** the DSA (data structure address) register points ** to this substructure of the ccb. ** This substructure contains the header with -** the script-processor-changable data and +** the script-processor-changeable data and ** data blocks for the indirect move commands. ** **---------------------------------------------------------- @@ -5107,7 +5107,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) /* ** This CCB has been skipped by the NCR. -** Queue it in the correponding unit queue. +** Queue it in the corresponding unit queue. */ static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp) { @@ -5896,8 +5896,8 @@ static void ncr_log_hard_error(struct ncb *np, u16 sist, u_char dstat) ** ** In normal cases, interrupt conditions occur one at a ** time. The ncr is able to stack in some extra registers -** other interrupts that will occurs after the first one. -** But severall interrupts may occur at the same time. +** other interrupts that will occur after the first one. +** But, several interrupts may occur at the same time. ** ** We probably should only try to deal with the normal ** case, but it seems that multiple interrupts occur in @@ -6796,7 +6796,7 @@ void ncr_int_sir (struct ncb *np) ** The host status field is set to HS_NEGOTIATE to mark this ** situation. ** -** If the target doesn't answer this message immidiately +** If the target doesn't answer this message immediately ** (as required by the standard), the SIR_NEGO_FAIL interrupt ** will be raised eventually. ** The handler removes the HS_NEGOTIATE status, and sets the diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index cb8b7701431e..b39357d9af8d 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -218,7 +218,7 @@ ** Same as option 1, but also deal with ** misconfigured interrupts. ** -** - Edge triggerred instead of level sensitive. +** - Edge triggered instead of level sensitive. ** - No interrupt line connected. ** - IRQ number misconfigured. ** @@ -549,7 +549,7 @@ struct ncr_driver_setup { /* ** Initial setup. -** Can be overriden at startup by a command line. +** Can be overridden at startup by a command line. */ #define SCSI_NCR_DRIVER_SETUP \ { \ @@ -1093,7 +1093,7 @@ struct scr_tblsel { **----------------------------------------------------------- ** On 810A, 860, 825A, 875, 895 and 896 chips the content ** of SFBR register can be used as data (SCR_SFBR_DATA). -** The 896 has additionnal IO registers starting at +** The 896 has additional IO registers starting at ** offset 0x80. Bit 7 of register offset is stored in ** bit 7 of the SCRIPTS instruction first DWORD. **----------------------------------------------------------- diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 32c635ecbf31..a00d1595656c 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -211,7 +211,7 @@ int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs, int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs, u8 width, u32 data); /* -* these can not be inlines because we need the structure offset!! +* these cannot be inlines because we need the structure offset!! * Does anyone have a better way????? */ #define u132_read_pcimem(u132, member, data) \ @@ -3045,7 +3045,7 @@ static struct hc_driver u132_hc_driver = { * This function may be called by the USB core whilst the "usb_all_devices_rwsem" * is held for writing, thus this module must not call usb_remove_hcd() * synchronously - but instead should immediately stop activity to the -* device and ansynchronously call usb_remove_hcd() +* device and asynchronously call usb_remove_hcd() */ static int __devexit u132_remove(struct platform_device *pdev) { @@ -3241,7 +3241,7 @@ static int u132_resume(struct platform_device *pdev) #define u132_resume NULL #endif /* -* this driver is loaded explicitely by ftdi_u132 +* this driver is loaded explicitly by ftdi_u132 * * the platform_driver struct is static because it is per type of module */ diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h index 551ba8906d62..5b5a3e621daa 100644 --- a/drivers/usb/misc/usb_u132.h +++ b/drivers/usb/misc/usb_u132.h @@ -52,7 +52,7 @@ * the kernel to load the "u132-hcd" module. * * The "ftdi-u132" module provides the interface to the inserted -* PC card and the "u132-hcd" module uses the API to send and recieve +* PC card and the "u132-hcd" module uses the API to send and receive * data. The API features call-backs, so that part of the "u132-hcd" * module code will run in the context of one of the kernel threads * of the "ftdi-u132" module. diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index bdb58100fc1d..5e3ac281a2f8 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -157,7 +157,7 @@ * to TASK_RUNNING will be lost and write_chan's subsequent call to * schedule() will never return (unless it catches a signal). * This race condition occurs because write_bulk_callback() (and thus -* the wakeup) are called asynchonously from an interrupt, rather than +* the wakeup) are called asynchronously from an interrupt, rather than * from the scheduler. We can avoid the race by calling the wakeup * from the scheduler queue and that's our fix: Now, at the end of * write_bulk_callback() we queue up a wakeup call on the scheduler diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 85ce23268302..ac93174c9639 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1464,7 +1464,7 @@ static int flush_journal_list(struct super_block *s, } /* if someone has this block in a newer transaction, just make - ** sure they are commited, and don't try writing it to disk + ** sure they are committed, and don't try writing it to disk */ if (pjl) { if (atomic_read(&pjl->j_commit_left)) @@ -3384,7 +3384,7 @@ static int remove_from_transaction(struct super_block *p_s_sb, /* ** for any cnode in a journal list, it can only be dirtied of all the -** transactions that include it are commited to disk. +** transactions that include it are committed to disk. ** this checks through each transaction, and returns 1 if you are allowed to dirty, ** and 0 if you aren't ** @@ -3426,7 +3426,7 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) } /* syncs the commit blocks, but does not force the real buffers to disk -** will wait until the current transaction is done/commited before returning +** will wait until the current transaction is done/committed before returning */ int journal_end_sync(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) diff --git a/include/asm-m68knommu/mcfmbus.h b/include/asm-m68knommu/mcfmbus.h index 13df9d41bd1a..319899c47a2c 100644 --- a/include/asm-m68knommu/mcfmbus.h +++ b/include/asm-m68knommu/mcfmbus.h @@ -37,7 +37,7 @@ #define MCFMBUS_MFDR_MBC(a) ((a)&0x3F) /*M-Bus Clock*/ /* -* Define bit flags in Controll Register +* Define bit flags in Control Register */ #define MCFMBUS_MBCR_MEN (0x80) /* M-Bus Enable */ diff --git a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h index da2cf373e31c..31ad0f05af3d 100644 --- a/include/asm-parisc/dma.h +++ b/include/asm-parisc/dma.h @@ -17,10 +17,10 @@ /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up -** (or rather not merge) DMA's into managable chunks. +** (or rather not merge) DMAs into manageable chunks. ** On parisc, this is more of the software/tuning constraint -** rather than the HW. I/O MMU allocation alogorithms can be -** faster with smaller size is (to some degree). +** rather than the HW. I/O MMU allocation algorithms can be +** faster with smaller sizes (to some degree). */ #define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE) diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index 7b8ad118d2fe..7b3be9ac0dda 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -149,7 +149,7 @@ extern int parisc_bus_is_phys; /* in arch/parisc/kernel/setup.c */ /* ** Most PCI devices (eg Tulip, NCR720) also export the same registers ** to both MMIO and I/O port space. Due to poor performance of I/O Port -** access under HP PCI bus adapters, strongly reccomend use of MMIO +** access under HP PCI bus adapters, strongly recommend the use of MMIO ** address space. ** ** While I'm at it more PA programming notes: diff --git a/include/asm-parisc/ropes.h b/include/asm-parisc/ropes.h index 5542dd00472b..007a880615eb 100644 --- a/include/asm-parisc/ropes.h +++ b/include/asm-parisc/ropes.h @@ -14,7 +14,7 @@ #endif /* -** The number of pdir entries to "free" before issueing +** The number of pdir entries to "free" before issuing ** a read to PCOM register to flush out PCOM writes. ** Interacts with allocation granularity (ie 4 or 8 entries ** allocated and free'd/purged at a time might make this diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h index fd1756d3a47e..88b45895746d 100644 --- a/include/linux/ixjuser.h +++ b/include/linux/ixjuser.h @@ -315,7 +315,7 @@ typedef struct { * structures. If the freq0 variable is non-zero, the tone table contents * for the tone_index are updated to the frequencies and gains defined. It * should be noted that DTMF tones cannot be reassigned, so if DTMF tone -* table indexs are used in a cadence the frequency and gain variables will +* table indexes are used in a cadence the frequency and gain variables will * be ignored. * * If the array elements contain frequency parameters the driver will diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 73e0becec086..62a7169aed8b 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -429,7 +429,7 @@ enum reiserfs_mount_options { /* -o hash={tea, rupasov, r5, detect} is meant for properly mounting ** reiserfs disks from 3.5.19 or earlier. 99% of the time, this option ** is not required. If the normal autodection code can't determine which -** hash to use (because both hases had the same value for a file) +** hash to use (because both hashes had the same value for a file) ** use this option to force a specific hash. It won't allow you to override ** the existing hash on the FS, so if you have a tea hash disk, and mount ** with -o hash=rupasov, the mount will fail. diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c index 6f39faa15832..c2059733e15a 100644 --- a/net/wanrouter/af_wanpipe.c +++ b/net/wanrouter/af_wanpipe.c @@ -13,7 +13,7 @@ * Due Credit: * Wanpipe socket layer is based on Packet and * the X25 socket layers. The above sockets were -* used for the specific use of Sangoma Technoloiges +* used for the specific use of Sangoma Technologies * API programs. * Packet socket Authors: Ross Biro, Fred N. van Kempen and * Alan Cox. @@ -23,7 +23,7 @@ * Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets. * Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call. * Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem. -* Server and client applicaton can run +* Server and client application can run * simultaneously without conflicts. * Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as * CHDLC, Frame Relay and HDLC API. diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 9479659277ae..316211d9f17d 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -3,7 +3,7 @@ * * This module is completely hardware-independent and provides * the following common services for the WAN Link Drivers: -* o WAN device managenment (registering, unregistering) +* o WAN device management (registering, unregistering) * o Network interface management * o Physical connection management (dial-up, incoming calls) * o Logical connection management (switched virtual circuits) diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c index 6e3c41f530e6..b1c5d8286e40 100644 --- a/sound/oss/cs46xx.c +++ b/sound/oss/cs46xx.c @@ -779,7 +779,7 @@ static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate) rate = 48000 / 9; /* - * We can not capture at at rate greater than the Input Rate (48000). + * We cannot capture at at rate greater than the Input Rate (48000). * Return an error if an attempt is made to stray outside that limit. */ if (rate > 48000) @@ -4754,8 +4754,8 @@ static int cs_hardware_init(struct cs_card *card) mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */ /* -* If we are resuming under 2.2.x then we can not schedule a timeout. -* so, just spin the CPU. +* If we are resuming under 2.2.x then we cannot schedule a timeout, +* so just spin the CPU. */ if (card->pm.flags & CS46XX_PM_IDLE) { /* -- cgit v1.2.3-70-g09d2 From c9308b06c049a107edfbd4e5271771564eb6024d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 27 Sep 2006 03:50:31 +0100 Subject: [PATCH] ieee80211: Move IV/ICV stripping into ieee80211_rx This patch adds a host_strip_iv_icv flag to ieee80211 which indicates that ieee80211_rx should strip the IV/ICV/other security features from the payload. This saves on some memmove() calls in the driver and seems like something that belongs in the stack as it can be used by bcm43xx, ipw2200, and zd1211rw I will submit the ipw2200 patch separately as it needs testing. This patch also adds some sensible variable reuse (idx vs keyidx) in ieee80211_rx Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 19 ---------- include/net/ieee80211.h | 4 +++ net/ieee80211/ieee80211_rx.c | 56 +++++++++++++++++++++++++---- 4 files changed, 55 insertions(+), 25 deletions(-) (limited to 'net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 12043f8be1bf..a659442b9c15 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -690,6 +690,7 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; + bcm->ieee->host_strip_iv_icv = !on; spin_unlock_irqrestore(&bcm->irq_lock, flags); mutex_unlock(&bcm->mutex); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 0159e4e93201..a957bc861382 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -543,25 +543,6 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, break; } - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { - frame_ctl &= ~IEEE80211_FCTL_PROTECTED; - wlhdr->frame_ctl = cpu_to_le16(frame_ctl); - /* trim IV and ICV */ - /* FIXME: this must be done only for WEP encrypted packets */ - if (skb->len < 32) { - dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " - "set and length < 32)\n"); - return -EINVAL; - } else { - memmove(skb->data + 4, skb->data, 24); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - stats.len -= 8; - } - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - } - switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index b174ebb277a9..cb255432e4e4 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1037,6 +1037,10 @@ struct ieee80211_device { /* host performs multicast decryption */ int host_mc_decrypt; + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + int host_open_frag; int host_build_iv; int ieee802_1x; /* is IEEE 802.1X used */ diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 2759312a4204..d9265195656d 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { - int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ - idx = skb->data[hdrlen + 3] >> 6; + keyidx = skb->data[hdrlen + 3] >> 6; } - /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx - * is only allowed 2-bits of storage, no value of idx can - * be provided via above code that would result in idx + /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx + * is only allowed 2-bits of storage, no value of keyidx can + * be provided via above code that would result in keyidx * being out of range */ - crypt = ieee->crypt[idx]; + crypt = ieee->crypt[keyidx]; #ifdef NOT_YET sta = NULL; @@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; } + /* If the frame was decrypted in hardware, we may need to strip off + * any security data (IV, ICV, etc) that was left behind */ + if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && + ieee->host_strip_iv_icv) { + int trimlen = 0; + + /* Top two-bits of byte 3 are the key index */ + if (skb->len >= hdrlen + 3) + keyidx = skb->data[hdrlen + 3] >> 6; + + /* To strip off any security data which appears before the + * payload, we simply increase hdrlen (as the header gets + * chopped off immediately below). For the security data which + * appears after the payload, we use skb_trim. */ + + switch (ieee->sec.encode_alg[keyidx]) { + case SEC_ALG_WEP: + /* 4 byte IV */ + hdrlen += 4; + /* 4 byte ICV */ + trimlen = 4; + break; + case SEC_ALG_TKIP: + /* 4 byte IV, 4 byte ExtIV */ + hdrlen += 8; + /* 8 byte MIC, 4 byte ICV */ + trimlen = 12; + break; + case SEC_ALG_CCMP: + /* 8 byte CCMP header */ + hdrlen += 8; + /* 8 byte MIC */ + trimlen = 8; + break; + } + + if (skb->len < trimlen) + goto rx_dropped; + + __skb_trim(skb, skb->len - trimlen); + + if (skb->len < hdrlen) + goto rx_dropped; + } + /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; -- cgit v1.2.3-70-g09d2 From 42a4cf9576f036db69e15fa6b4e72986e17f0359 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Thu, 28 Sep 2006 19:57:25 +0200 Subject: [PATCH] ieee80211: allow mtu bigger than 1500 Hi this patch allow to set the mtu between 1500 and 2304 (max octets in an MSDU) for devices using ieee80211 linux stack. Signed-off-by: Matthieu CASTET Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_module.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'net') diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 13b1e5fff7e4..2b14c2f3e21d 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -118,6 +118,14 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } +static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -133,6 +141,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) } ieee = netdev_priv(dev); dev->hard_start_xmit = ieee80211_xmit; + dev->change_mtu = ieee80211_change_mtu; ieee->dev = dev; -- cgit v1.2.3-70-g09d2 From 837925df022a667c302b24aad9d6a58f94efd959 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 3 Oct 2006 18:49:32 -0500 Subject: [PATCH] ieee80211: Drop and count duplicate data frames to remove 'replay detected' log messages In the SoftMAC version of the IEEE 802.11 stack, not all duplicate messages are detected. For the most part, there is no difficulty; however for TKIP and CCMP encryption, the duplicates result in a "replay detected" log message where the received and previous values of the TSC are identical. This change adds a new variable to the ieee80211_device structure that holds the 'seq_ctl' value for the previous frame. When a new frame repeats the value, the frame is dropped and the appropriate counter is incremented. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- include/net/ieee80211.h | 2 ++ net/ieee80211/ieee80211_rx.c | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'net') diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index cb255432e4e4..e6af381e206d 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1080,6 +1080,8 @@ struct ieee80211_device { int perfect_rssi; int worst_rssi; + u16 prev_seq_ctl; /* used to drop duplicate frames */ + /* Callback functions */ void (*set_security) (struct net_device * dev, struct ieee80211_security * sec); diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index d9265195656d..ce28d571afac 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -478,6 +478,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_exit; } #endif + /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ + if (sc == ieee->prev_seq_ctl) + goto rx_dropped; + else + ieee->prev_seq_ctl = sc; /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_3ADDR_LEN) -- cgit v1.2.3-70-g09d2 From 5398d5901dcb677d24d839d3feac7209e250b161 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 4 Nov 2006 13:29:50 -0600 Subject: [PATCH] ieee80211softmac: fix verbosity when debug disabled SoftMAC contains a number of debug-type messages that continue to print even when debugging is turned off. This patch substitutes dprintkl for printkl for those lines. Signed-off-by: Larry Finger Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_auth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 4cef39e171d0..95e5287e12bb 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -158,7 +158,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Make sure that we've got an auth queue item for this request */ if(aq == NULL) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); /* Error #? */ return -1; } @@ -166,7 +166,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Check for out of order authentication */ if(!net->authenticating) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); return -1; } @@ -342,7 +342,7 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, /* Make sure the network is authenticated */ if (!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } @@ -376,7 +376,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2); if (net == NULL) { - printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", + dprintkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", MAC_ARG(deauth->header.addr2)); return 0; } @@ -384,7 +384,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de /* Make sure the network is authenticated */ if(!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } -- cgit v1.2.3-70-g09d2 From 571d6eee9b5bce28fcbeb7588890ad5ca3f8c718 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:26:49 -0200 Subject: [PATCH] Check ieee80211softmac_auth_resp kmalloc result And use kmemdup and kzalloc where applicable Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_module.c | 5 +---- net/ieee80211/ieee80211_rx.c | 7 +++---- net/ieee80211/softmac/ieee80211softmac_auth.c | 14 ++++++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 2b14c2f3e21d..f16e60ee9ce9 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -67,7 +67,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return 0; ieee->networks = - kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), + kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), GFP_KERNEL); if (!ieee->networks) { printk(KERN_WARNING "%s: Out of memory allocating beacons\n", @@ -75,9 +75,6 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return -ENOMEM; } - memset(ieee->networks, 0, - MAX_NETWORK_COUNT * sizeof(struct ieee80211_network)); - return 0; } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index ce28d571afac..d97e5412e31b 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -1304,12 +1304,11 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element case MFIE_TYPE_IBSS_DFS: if (network->ibss_dfs) break; - network->ibss_dfs = - kmalloc(info_element->len, GFP_ATOMIC); + network->ibss_dfs = kmemdup(info_element->data, + info_element->len, + GFP_ATOMIC); if (!network->ibss_dfs) return 1; - memcpy(network->ibss_dfs, info_element->data, - info_element->len); network->flags |= NETWORK_HAS_IBSS_DFS; break; diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 95e5287e12bb..0612015f1c78 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -216,10 +216,16 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) net->challenge_len = *data++; if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - if (net->challenge != NULL) - kfree(net->challenge); - net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); - memcpy(net->challenge, data, net->challenge_len); + kfree(net->challenge); + net->challenge = kmemdup(data, net->challenge_len, + GFP_ATOMIC); + if (net->challenge == NULL) { + printkl(KERN_NOTICE PFX "Shared Key " + "Authentication failed due to " + "memory shortage.\n"); + spin_unlock_irqrestore(&mac->lock, flags); + break; + } aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; /* We reuse the work struct from the auth request here. -- cgit v1.2.3-70-g09d2 From 718cc4ca2bfb3263c7ea3ceba9c194f9cd7292e2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 03:15:46 +0000 Subject: [PATCH] ieee80211: Provide generic get_stats implementation bcm43xx and ipw2100 currently duplicate the same simplistic get_stats handler. Additionally, zd1211rw requires the same handler to fix a bug where all stats are reported as 0. This patch adds a generic implementation to the ieee80211 layer, which drivers are free to override. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 6 ------ drivers/net/wireless/ipw2100.c | 14 -------------- net/ieee80211/ieee80211_module.c | 11 +++++++++++ 3 files changed, 11 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 60a97450a6ed..5b3c27359a18 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4013,11 +4013,6 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, return NETDEV_TX_OK; } -static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) -{ - return &(bcm43xx_priv(net_dev)->ieee->stats); -} - static void bcm43xx_net_tx_timeout(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); @@ -4131,7 +4126,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, net_dev->open = bcm43xx_net_open; net_dev->stop = bcm43xx_net_stop; - net_dev->get_stats = bcm43xx_net_get_stats; net_dev->tx_timeout = bcm43xx_net_tx_timeout; #ifdef CONFIG_NET_POLL_CONTROLLER net_dev->poll_controller = bcm43xx_net_poll_controller; diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 3bc6be9d20f8..79607b8b877c 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5827,19 +5827,6 @@ static void ipw2100_tx_timeout(struct net_device *dev) schedule_reset(priv); } -/* - * TODO: reimplement it so that it reads statistics - * from the adapter using ordinal tables - * instead of/in addition to collecting them - * in the driver - */ -static struct net_device_stats *ipw2100_stats(struct net_device *dev) -{ - struct ipw2100_priv *priv = ieee80211_priv(dev); - - return &priv->ieee->stats; -} - static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) { /* This is called when wpa_supplicant loads and closes the driver @@ -6022,7 +6009,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, dev->open = ipw2100_open; dev->stop = ipw2100_close; dev->init = ipw2100_net_init; - dev->get_stats = ipw2100_stats; dev->ethtool_ops = &ipw2100_ethtool_ops; dev->tx_timeout = ipw2100_tx_timeout; dev->wireless_handlers = &ipw2100_wx_handler_def; diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index f16e60ee9ce9..b1c6d1f717d9 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -123,6 +123,13 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static struct net_device_stats *ieee80211_generic_get_stats( + struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + return &ieee->stats; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -140,6 +147,10 @@ struct net_device *alloc_ieee80211(int sizeof_priv) dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; + /* Drivers are free to override this if the generic implementation + * does not meet their needs. */ + dev->get_stats = ieee80211_generic_get_stats; + ieee->dev = dev; err = ieee80211_networks_allocate(ieee); -- cgit v1.2.3-70-g09d2 From 38e3a6466f369944a2a1ec9aee9a9e472689d0a9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 25 Nov 2006 18:30:03 -0600 Subject: [PATCH] softmac: reduce scan debug output When scanning in debug mode, softmac is very chatty in that it puts 3 lines in the logs for each time it scans. This patch has only one line containing all the information previously reported. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index ad67368b58ed..5507feab32de 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -134,7 +134,8 @@ void ieee80211softmac_scan(void *d) si->started = 0; spin_unlock_irqrestore(&sm->lock, flags); - dprintk(PFX "Scanning finished\n"); + dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n", + sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel); ieee80211softmac_scan_finished(sm); complete_all(&sm->scaninfo->finished); } @@ -182,8 +183,6 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->channels = sm->ieee->geo.bg; sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; } - dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel); - dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels); sm->scaninfo->current_channel_idx = 0; sm->scaninfo->started = 1; sm->scaninfo->stop = 0; -- cgit v1.2.3-70-g09d2 From 88041b79f864dcd7f95e1d594eba683244dd968a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 13:41:58 -0800 Subject: [PATCH] netdev: don't allow register_netdev with blank name This bit of old backwards compatibility cruft can be removed in 2.6.20. If there is still an device that calls register_netdev() with a zero or blank name, it will get -EINVAL from register_netdevice(). Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- net/core/dev.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 81c426adcd1e..411c2428d268 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3035,15 +3035,6 @@ int register_netdev(struct net_device *dev) goto out; } - /* - * Back compatibility hook. Kill this one in 2.5 - */ - if (dev->name[0] == 0 || dev->name[0] == ' ') { - err = dev_alloc_name(dev, "eth%d"); - if (err < 0) - goto out; - } - err = register_netdevice(dev); out: rtnl_unlock(); -- cgit v1.2.3-70-g09d2 From d54a81d341af80875c201890500f727c8188dd9b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 2 Dec 2006 21:00:06 -0800 Subject: [IPV6] NDISC: Calculate packet length correctly for allocation. MAX_HEADER does not include the ipv6 header length in it, so we need to add it in explicitly. With help from YOSHIFUJI Hideaki. Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 73eb8c33e9f0..89d527ebd7f6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -472,7 +472,9 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, inc_opt = 0; } - skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), + skb = sock_alloc_send_skb(sk, + (MAX_HEADER + sizeof(struct ipv6hdr) + + len + LL_RESERVED_SPACE(dev)), 1, &err); if (skb == NULL) { @@ -561,7 +563,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, if (send_llinfo) len += ndisc_opt_addr_space(dev); - skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), + skb = sock_alloc_send_skb(sk, + (MAX_HEADER + sizeof(struct ipv6hdr) + + len + LL_RESERVED_SPACE(dev)), 1, &err); if (skb == NULL) { ND_PRINTK0(KERN_ERR @@ -636,7 +640,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, if (dev->addr_len) len += ndisc_opt_addr_space(dev); - skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), + skb = sock_alloc_send_skb(sk, + (MAX_HEADER + sizeof(struct ipv6hdr) + + len + LL_RESERVED_SPACE(dev)), 1, &err); if (skb == NULL) { ND_PRINTK0(KERN_ERR @@ -1446,7 +1452,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, rd_len &= ~0x7; len += rd_len; - buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), + buff = sock_alloc_send_skb(sk, + (MAX_HEADER + sizeof(struct ipv6hdr) + + len + LL_RESERVED_SPACE(dev)), 1, &err); if (buff == NULL) { ND_PRINTK0(KERN_ERR -- cgit v1.2.3-70-g09d2 From 3e6c8cd5669c1202fe806ce3e13d701f20a71c7e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:19:09 -0800 Subject: [TIPC]: endianness annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/tipc_config.h | 32 ++++++++++++++++---------------- include/net/tipc/tipc_bearer.h | 2 +- include/net/tipc/tipc_msg.h | 2 +- net/tipc/config.c | 32 +++++++++++--------------------- net/tipc/dbg.c | 3 +-- net/tipc/name_distr.c | 10 +++++----- net/tipc/node.c | 9 +++------ 7 files changed, 38 insertions(+), 52 deletions(-) (limited to 'net') diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h index 33a653913d94..b0c916d1f375 100644 --- a/include/linux/tipc_config.h +++ b/include/linux/tipc_config.h @@ -194,34 +194,34 @@ struct tipc_node_info { - __u32 addr; /* network address of node */ - __u32 up; /* 0=down, 1= up */ + __be32 addr; /* network address of node */ + __be32 up; /* 0=down, 1= up */ }; struct tipc_link_info { - __u32 dest; /* network address of peer node */ - __u32 up; /* 0=down, 1=up */ + __be32 dest; /* network address of peer node */ + __be32 up; /* 0=down, 1=up */ char str[TIPC_MAX_LINK_NAME]; /* link name */ }; struct tipc_bearer_config { - __u32 priority; /* Range [1,31]. Override per link */ - __u32 detect_scope; + __be32 priority; /* Range [1,31]. Override per link */ + __be32 detect_scope; char name[TIPC_MAX_BEARER_NAME]; }; struct tipc_link_config { - __u32 value; + __be32 value; char name[TIPC_MAX_LINK_NAME]; }; #define TIPC_NTQ_ALLTYPES 0x80000000 struct tipc_name_table_query { - __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ - __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ - __u32 lowbound; /* (i.e. displays all entries of name table) */ - __u32 upbound; + __be32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ + __be32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ + __be32 lowbound; /* (i.e. displays all entries of name table) */ + __be32 upbound; }; /* @@ -262,8 +262,8 @@ struct tipc_route_info { */ struct tlv_desc { - __u16 tlv_len; /* TLV length (descriptor + value) */ - __u16 tlv_type; /* TLV identifier */ + __be16 tlv_len; /* TLV length (descriptor + value) */ + __be16 tlv_type; /* TLV identifier */ }; #define TLV_ALIGNTO 4 @@ -377,9 +377,9 @@ struct tipc_genlmsghdr { struct tipc_cfg_msg_hdr { - __u32 tcm_len; /* Message length (including header) */ - __u16 tcm_type; /* Command type */ - __u16 tcm_flags; /* Additional flags */ + __be32 tcm_len; /* Message length (including header) */ + __be16 tcm_type; /* Command type */ + __be16 tcm_flags; /* Additional flags */ char tcm_reserved[8]; /* Unused */ }; diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h index e07136d74c2f..2151a80cdf30 100644 --- a/include/net/tipc/tipc_bearer.h +++ b/include/net/tipc/tipc_bearer.h @@ -58,7 +58,7 @@ */ struct tipc_media_addr { - __u32 type; /* bearer type (network byte order) */ + __be32 type; /* bearer type (network byte order) */ union { __u8 eth_addr[6]; /* 48 bit Ethernet addr (byte array) */ #if 0 diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h index 4d096eebc93f..fb42eb7a86a5 100644 --- a/include/net/tipc/tipc_msg.h +++ b/include/net/tipc/tipc_msg.h @@ -40,7 +40,7 @@ #ifdef __KERNEL__ struct tipc_msg { - u32 hdr[15]; + __be32 hdr[15]; }; diff --git a/net/tipc/config.c b/net/tipc/config.c index ed1351ed05e1..458a2c46cef3 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -107,7 +107,7 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) { struct sk_buff *buf; - u32 value_net; + __be32 value_net; buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); if (buf) { @@ -284,8 +284,7 @@ static struct sk_buff *cfg_set_own_addr(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - addr = *(u32 *)TLV_DATA(req_tlv_area); - addr = ntohl(addr); + addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) @@ -319,8 +318,7 @@ static struct sk_buff *cfg_set_remote_mng(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); tipc_remote_management = (value != 0); return tipc_cfg_reply_none(); } @@ -332,8 +330,7 @@ static struct sk_buff *cfg_set_max_publications(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max publications must be 1-65535)"); @@ -348,8 +345,7 @@ static struct sk_buff *cfg_set_max_subscriptions(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max subscriptions must be 1-65535"); @@ -363,8 +359,7 @@ static struct sk_buff *cfg_set_max_ports(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_max_ports) return tipc_cfg_reply_none(); if (value != delimit(value, 127, 65535)) @@ -383,8 +378,7 @@ static struct sk_buff *cfg_set_max_zones(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_max_zones) return tipc_cfg_reply_none(); if (value != delimit(value, 1, 255)) @@ -403,8 +397,7 @@ static struct sk_buff *cfg_set_max_clusters(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 1)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max clusters fixed at 1)"); @@ -417,8 +410,7 @@ static struct sk_buff *cfg_set_max_nodes(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_max_nodes) return tipc_cfg_reply_none(); if (value != delimit(value, 8, 2047)) @@ -437,8 +429,7 @@ static struct sk_buff *cfg_set_max_slaves(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != 0) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (max secondary nodes fixed at 0)"); @@ -451,8 +442,7 @@ static struct sk_buff *cfg_set_netid(void) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value == tipc_net_id) return tipc_cfg_reply_none(); if (value != delimit(value, 1, 9999)) diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index d8af4c28695d..627f99b7afdf 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -393,8 +393,7 @@ struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = *(u32 *)TLV_DATA(req_tlv_area); - value = ntohl(value); + value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 0, 32768)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (log size must be 0-32768)"); diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 03bd659c43ca..7bf87cb26ef3 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -66,11 +66,11 @@ */ struct distr_item { - u32 type; - u32 lower; - u32 upper; - u32 ref; - u32 key; + __be32 type; + __be32 lower; + __be32 upper; + __be32 ref; + __be32 key; }; /** diff --git a/net/tipc/node.c b/net/tipc/node.c index 886bda5e88db..106cd0dfac78 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -597,8 +597,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - domain = *(u32 *)TLV_DATA(req_tlv_area); - domain = ntohl(domain); + domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (!tipc_addr_domain_valid(domain)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); @@ -642,8 +641,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - domain = *(u32 *)TLV_DATA(req_tlv_area); - domain = ntohl(domain); + domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (!tipc_addr_domain_valid(domain)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); @@ -664,8 +662,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) /* Add TLV for broadcast link */ - link_info.dest = tipc_own_addr & 0xfffff00; - link_info.dest = htonl(link_info.dest); + link_info.dest = htonl(tipc_own_addr & 0xfffff00); link_info.up = htonl(1); sprintf(link_info.str, tipc_bclink_name); tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); -- cgit v1.2.3-70-g09d2 From 5a874db4d9bfd8a4c6324d844a4d1c7cfa5cf2c4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:19:38 -0800 Subject: [NET]: ipconfig and nfsroot annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- fs/nfs/nfsroot.c | 13 +++--- include/linux/nfs_fs.h | 2 +- include/net/ipconfig.h | 8 ++-- net/ipv4/ipconfig.c | 105 +++++++++++++++++++++++++------------------------ 4 files changed, 64 insertions(+), 64 deletions(-) (limited to 'net') diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 8dfefe41a8da..75f819dc0255 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -98,7 +98,7 @@ static char nfs_root_name[256] __initdata = ""; /* Address of NFS server */ -static __u32 servaddr __initdata = 0; +static __be32 servaddr __initdata = 0; /* Name of directory to mount */ static char nfs_path[NFS_MAXPATHLEN] __initdata = { 0, }; @@ -327,7 +327,7 @@ static int __init root_nfs_name(char *name) */ static int __init root_nfs_addr(void) { - if ((servaddr = root_server_addr) == INADDR_NONE) { + if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) { printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n"); return -1; } @@ -411,7 +411,7 @@ __setup("nfsroot=", nfs_root_setup); * Construct sockaddr_in from address and port number. */ static inline void -set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port) +set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port) { sin->sin_family = AF_INET; sin->sin_addr.s_addr = addr; @@ -468,14 +468,13 @@ static int __init root_nfs_ports(void) dprintk("Root-NFS: Portmapper on server returned %d " "as nfsd port\n", port); } - nfs_port = htons(nfs_port); if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) { printk(KERN_ERR "Root-NFS: Unable to get mountd port " "number from server, using default\n"); port = mountd_port; } - mount_port = htons(port); + mount_port = port; dprintk("Root-NFS: mountd port is %d\n", port); return 0; @@ -496,7 +495,7 @@ static int __init root_nfs_get_handle(void) int version = (nfs_data.flags & NFS_MOUNT_VER3) ? NFS_MNT3_VERSION : NFS_MNT_VERSION; - set_sockaddr(&sin, servaddr, mount_port); + set_sockaddr(&sin, servaddr, htons(mount_port)); status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol); if (status < 0) printk(KERN_ERR "Root-NFS: Server returned error %d " @@ -519,6 +518,6 @@ void * __init nfs_root_data(void) || root_nfs_ports() < 0 || root_nfs_get_handle() < 0) return NULL; - set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port); + set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port)); return (void*)&nfs_data; } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 45228c1a1195..625ffea98561 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -318,7 +318,7 @@ extern void put_nfs_open_context(struct nfs_open_context *ctx); extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ -extern u32 root_nfs_parse_addr(char *name); /*__init*/ +extern __be32 root_nfs_parse_addr(char *name); /*__init*/ static inline void nfs_fattr_init(struct nfs_fattr *fattr) { diff --git a/include/net/ipconfig.h b/include/net/ipconfig.h index 2a1fe996fbc6..3924d7d2cb11 100644 --- a/include/net/ipconfig.h +++ b/include/net/ipconfig.h @@ -11,12 +11,12 @@ extern int ic_proto_enabled; /* Protocols enabled (see IC_xxx) */ extern int ic_set_manually; /* IPconfig parameters set manually */ -extern u32 ic_myaddr; /* My IP address */ -extern u32 ic_gateway; /* Gateway IP address */ +extern __be32 ic_myaddr; /* My IP address */ +extern __be32 ic_gateway; /* Gateway IP address */ -extern u32 ic_servaddr; /* Boot server IP address */ +extern __be32 ic_servaddr; /* Boot server IP address */ -extern u32 root_server_addr; /* Address of NFS server */ +extern __be32 root_server_addr; /* Address of NFS server */ extern u8 root_server_path[]; /* Path to mount as root */ diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 955a07abb91d..afa60b9a003f 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -101,6 +101,7 @@ #define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers - '3' from resolv.h */ +#define NONE __constant_htonl(INADDR_NONE) /* * Public IP configuration @@ -129,19 +130,19 @@ int ic_proto_enabled __initdata = 0 static int ic_host_name_set __initdata = 0; /* Host name set by us? */ -u32 ic_myaddr = INADDR_NONE; /* My IP address */ -static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */ -u32 ic_gateway = INADDR_NONE; /* Gateway IP address */ +__be32 ic_myaddr = NONE; /* My IP address */ +static __be32 ic_netmask = NONE; /* Netmask for local subnet */ +__be32 ic_gateway = NONE; /* Gateway IP address */ -u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */ +__be32 ic_servaddr = NONE; /* Boot server IP address */ -u32 root_server_addr = INADDR_NONE; /* Address of NFS server */ +__be32 root_server_addr = NONE; /* Address of NFS server */ u8 root_server_path[256] = { 0, }; /* Path to mount as root */ /* Persistent data: */ static int ic_proto_used; /* Protocol used, if any */ -static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ +static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ static u8 ic_domain[64]; /* DNS (not NIS) domain name */ /* @@ -172,7 +173,7 @@ struct ic_device { struct net_device *dev; unsigned short flags; short able; - u32 xid; + __be32 xid; }; static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ @@ -223,7 +224,7 @@ static int __init ic_open_devs(void) d->flags = oflags; d->able = able; if (able & IC_BOOTP) - get_random_bytes(&d->xid, sizeof(u32)); + get_random_bytes(&d->xid, sizeof(__be32)); else d->xid = 0; ic_proto_have_if |= able; @@ -269,7 +270,7 @@ static void __init ic_close_devs(void) */ static inline void -set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port) +set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port) { sin->sin_family = AF_INET; sin->sin_addr.s_addr = addr; @@ -332,7 +333,7 @@ static int __init ic_setup_routes(void) { /* No need to setup device routes, only the default route... */ - if (ic_gateway != INADDR_NONE) { + if (ic_gateway != NONE) { struct rtentry rm; int err; @@ -368,10 +369,10 @@ static int __init ic_defaults(void) if (!ic_host_name_set) sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr)); - if (root_server_addr == INADDR_NONE) + if (root_server_addr == NONE) root_server_addr = ic_servaddr; - if (ic_netmask == INADDR_NONE) { + if (ic_netmask == NONE) { if (IN_CLASSA(ntohl(ic_myaddr))) ic_netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(ic_myaddr))) @@ -420,7 +421,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt { struct arphdr *rarp; unsigned char *rarp_ptr; - u32 sip, tip; + __be32 sip, tip; unsigned char *sha, *tha; /* s for "source", t for "target" */ struct ic_device *d; @@ -485,12 +486,12 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt goto drop_unlock; /* Discard packets which are not from specified server. */ - if (ic_servaddr != INADDR_NONE && ic_servaddr != sip) + if (ic_servaddr != NONE && ic_servaddr != sip) goto drop_unlock; /* We have a winner! */ ic_dev = dev; - if (ic_myaddr == INADDR_NONE) + if (ic_myaddr == NONE) ic_myaddr = tip; ic_servaddr = sip; ic_got_reply = IC_RARP; @@ -530,13 +531,13 @@ struct bootp_pkt { /* BOOTP packet format */ u8 htype; /* HW address type */ u8 hlen; /* HW address length */ u8 hops; /* Used only by gateways */ - u32 xid; /* Transaction ID */ - u16 secs; /* Seconds since we started */ - u16 flags; /* Just what it says */ - u32 client_ip; /* Client's IP address if known */ - u32 your_ip; /* Assigned IP address */ - u32 server_ip; /* (Next, e.g. NFS) Server's IP address */ - u32 relay_ip; /* IP address of BOOTP relay */ + __be32 xid; /* Transaction ID */ + __be16 secs; /* Seconds since we started */ + __be16 flags; /* Just what it says */ + __be32 client_ip; /* Client's IP address if known */ + __be32 your_ip; /* Assigned IP address */ + __be32 server_ip; /* (Next, e.g. NFS) Server's IP address */ + __be32 relay_ip; /* IP address of BOOTP relay */ u8 hw_addr[16]; /* Client's HW address */ u8 serv_name[64]; /* Server host name */ u8 boot_file[128]; /* Name of boot file */ @@ -576,7 +577,7 @@ static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 }; static void __init ic_dhcp_init_options(u8 *options) { - u8 mt = ((ic_servaddr == INADDR_NONE) + u8 mt = ((ic_servaddr == NONE) ? DHCPDISCOVER : DHCPREQUEST); u8 *e = options; @@ -666,7 +667,7 @@ static inline void ic_bootp_init(void) int i; for (i = 0; i < CONF_NAMESERVERS_MAX; i++) - ic_nameservers[i] = INADDR_NONE; + ic_nameservers[i] = NONE; dev_add_pack(&bootp_packet_type); } @@ -708,7 +709,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d h->frag_off = htons(IP_DF); h->ttl = 64; h->protocol = IPPROTO_UDP; - h->daddr = INADDR_BROADCAST; + h->daddr = htonl(INADDR_BROADCAST); h->check = ip_fast_csum((unsigned char *) h, h->ihl); /* Construct UDP header */ @@ -730,8 +731,8 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d b->htype = dev->type; /* can cause undefined behavior */ } b->hlen = dev->addr_len; - b->your_ip = INADDR_NONE; - b->server_ip = INADDR_NONE; + b->your_ip = NONE; + b->server_ip = NONE; memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); b->secs = htons(jiffies_diff / HZ); b->xid = d->xid; @@ -788,11 +789,11 @@ static void __init ic_do_bootp_ext(u8 *ext) switch (*ext++) { case 1: /* Subnet mask */ - if (ic_netmask == INADDR_NONE) + if (ic_netmask == NONE) memcpy(&ic_netmask, ext+1, 4); break; case 3: /* Default gateway */ - if (ic_gateway == INADDR_NONE) + if (ic_gateway == NONE) memcpy(&ic_gateway, ext+1, 4); break; case 6: /* DNS server */ @@ -800,7 +801,7 @@ static void __init ic_do_bootp_ext(u8 *ext) if (servers > CONF_NAMESERVERS_MAX) servers = CONF_NAMESERVERS_MAX; for (i = 0; i < servers; i++) { - if (ic_nameservers[i] == INADDR_NONE) + if (ic_nameservers[i] == NONE) memcpy(&ic_nameservers[i], ext+1+4*i, 4); } break; @@ -917,7 +918,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str #ifdef IPCONFIG_DHCP if (ic_proto_enabled & IC_USE_DHCP) { - u32 server_id = INADDR_NONE; + __be32 server_id = NONE; int mt = 0; ext = &b->exten[4]; @@ -949,7 +950,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str /* While in the process of accepting one offer, * ignore all others. */ - if (ic_myaddr != INADDR_NONE) + if (ic_myaddr != NONE) goto drop_unlock; /* Let's accept that offer. */ @@ -965,7 +966,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str * precedence over the bootp header one if * they are different. */ - if ((server_id != INADDR_NONE) && + if ((server_id != NONE) && (b->server_ip != server_id)) b->server_ip = ic_servaddr; break; @@ -979,8 +980,8 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str default: /* Urque. Forget it*/ - ic_myaddr = INADDR_NONE; - ic_servaddr = INADDR_NONE; + ic_myaddr = NONE; + ic_servaddr = NONE; goto drop_unlock; }; @@ -1004,9 +1005,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str ic_dev = dev; ic_myaddr = b->your_ip; ic_servaddr = b->server_ip; - if (ic_gateway == INADDR_NONE && b->relay_ip) + if (ic_gateway == NONE && b->relay_ip) ic_gateway = b->relay_ip; - if (ic_nameservers[0] == INADDR_NONE) + if (ic_nameservers[0] == NONE) ic_nameservers[0] = ic_servaddr; ic_got_reply = IC_BOOTP; @@ -1150,7 +1151,7 @@ static int __init ic_dynamic(void) #endif if (!ic_got_reply) { - ic_myaddr = INADDR_NONE; + ic_myaddr = NONE; return -1; } @@ -1182,12 +1183,12 @@ static int pnp_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "domain %s\n", ic_domain); for (i = 0; i < CONF_NAMESERVERS_MAX; i++) { - if (ic_nameservers[i] != INADDR_NONE) + if (ic_nameservers[i] != NONE) seq_printf(seq, "nameserver %u.%u.%u.%u\n", NIPQUAD(ic_nameservers[i])); } - if (ic_servaddr != INADDR_NONE) + if (ic_servaddr != NONE) seq_printf(seq, "bootserver %u.%u.%u.%u\n", NIPQUAD(ic_servaddr)); @@ -1213,9 +1214,9 @@ static struct file_operations pnp_seq_fops = { * need to have root_server_addr set _before_ IPConfig gets called as it * can override it. */ -u32 __init root_nfs_parse_addr(char *name) +__be32 __init root_nfs_parse_addr(char *name) { - u32 addr; + __be32 addr; int octets = 0; char *cp, *cq; @@ -1237,7 +1238,7 @@ u32 __init root_nfs_parse_addr(char *name) addr = in_aton(name); memmove(name, cp, strlen(cp) + 1); } else - addr = INADDR_NONE; + addr = NONE; return addr; } @@ -1248,7 +1249,7 @@ u32 __init root_nfs_parse_addr(char *name) static int __init ip_auto_config(void) { - u32 addr; + __be32 addr; #ifdef CONFIG_PROC_FS proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops); @@ -1277,11 +1278,11 @@ static int __init ip_auto_config(void) * interfaces and no default was set), use BOOTP or RARP to get the * missing values. */ - if (ic_myaddr == INADDR_NONE || + if (ic_myaddr == NONE || #ifdef CONFIG_ROOT_NFS (MAJOR(ROOT_DEV) == UNNAMED_MAJOR - && root_server_addr == INADDR_NONE - && ic_servaddr == INADDR_NONE) || + && root_server_addr == NONE + && ic_servaddr == NONE) || #endif ic_first_dev->next) { #ifdef IPCONFIG_DYNAMIC @@ -1334,7 +1335,7 @@ static int __init ip_auto_config(void) } addr = root_nfs_parse_addr(root_server_path); - if (root_server_addr == INADDR_NONE) + if (root_server_addr == NONE) root_server_addr = addr; /* @@ -1461,19 +1462,19 @@ static int __init ip_auto_config_setup(char *addrs) switch (num) { case 0: if ((ic_myaddr = in_aton(ip)) == INADDR_ANY) - ic_myaddr = INADDR_NONE; + ic_myaddr = NONE; break; case 1: if ((ic_servaddr = in_aton(ip)) == INADDR_ANY) - ic_servaddr = INADDR_NONE; + ic_servaddr = NONE; break; case 2: if ((ic_gateway = in_aton(ip)) == INADDR_ANY) - ic_gateway = INADDR_NONE; + ic_gateway = NONE; break; case 3: if ((ic_netmask = in_aton(ip)) == INADDR_ANY) - ic_netmask = INADDR_NONE; + ic_netmask = NONE; break; case 4: if ((dp = strchr(ip, '.'))) { -- cgit v1.2.3-70-g09d2 From d2ecd9ccd0694278a8c1fa179d1d058ee66e2297 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:20:00 -0800 Subject: [IPV6]: annotate inet6_hashtables Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/inet6_hashtables.h | 16 ++++++++-------- net/ipv6/inet6_hashtables.c | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index bc6a71dce984..c28e424f53d9 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -26,11 +26,11 @@ struct inet_hashinfo; /* I have no idea if this is a good hash for v6 or not. -DaveM */ static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport, - const struct in6_addr *faddr, const u16 fport) + const struct in6_addr *faddr, const __be16 fport) { - unsigned int hashent = (lport ^ fport); + unsigned int hashent = (lport ^ (__force u16)fport); - hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); + hashent ^= (__force u32)(laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); hashent ^= hashent >> 16; hashent ^= hashent >> 8; return hashent; @@ -43,7 +43,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk) const struct in6_addr *laddr = &np->rcv_saddr; const struct in6_addr *faddr = &np->daddr; const __u16 lport = inet->num; - const __u16 fport = inet->dport; + const __be16 fport = inet->dport; return inet6_ehashfn(laddr, lport, faddr, fport); } @@ -57,7 +57,7 @@ extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk); */ extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, - const u16 sport, + const __be16 sport, const struct in6_addr *daddr, const u16 hnum, const int dif); @@ -69,7 +69,7 @@ extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, - const u16 sport, + const __be16 sport, const struct in6_addr *daddr, const u16 hnum, const int dif) @@ -83,8 +83,8 @@ static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo, } extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, - const struct in6_addr *saddr, const u16 sport, - const struct in6_addr *daddr, const u16 dport, + const struct in6_addr *saddr, const __be16 sport, + const struct in6_addr *daddr, const __be16 dport, const int dif); #endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */ #endif /* _INET6_HASHTABLES_H */ diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 8accd1fbeeda..b7e5bae0e347 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -57,7 +57,7 @@ EXPORT_SYMBOL(__inet6_hash); */ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, - const u16 sport, + const __be16 sport, const struct in6_addr *daddr, const u16 hnum, const int dif) @@ -146,8 +146,8 @@ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, EXPORT_SYMBOL_GPL(inet6_lookup_listener); struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, - const struct in6_addr *saddr, const u16 sport, - const struct in6_addr *daddr, const u16 dport, + const struct in6_addr *saddr, const __be16 sport, + const struct in6_addr *daddr, const __be16 dport, const int dif) { struct sock *sk; -- cgit v1.2.3-70-g09d2 From 8c689a6eae2d83970e4f34753d513e96fb97a025 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:20:21 -0800 Subject: [XFRM]: misc annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/xfrm.h | 6 +++--- net/ipv4/xfrm4_policy.c | 6 +++--- net/ipv6/xfrm6_policy.c | 2 +- net/ipv6/xfrm6_tunnel.c | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 737fdb2ee8a4..a63e277bacf7 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -951,9 +951,9 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); -extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); -extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); extern int xfrm6_output(struct sk_buff *skb); extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, u8 **prevhdr); @@ -1033,7 +1033,7 @@ static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, switch (family) { default: case AF_INET: - return a->a4 - b->a4; + return (__force __u32)a->a4 - (__force __u32)b->a4; case AF_INET6: return ipv6_addr_cmp((struct in6_addr *)a, (struct in6_addr *)b); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 1bed0cdf53e3..da766234607b 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -72,8 +72,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int struct dst_entry *dst, *dst_prev; struct rtable *rt0 = (struct rtable*)(*dst_p); struct rtable *rt = rt0; - u32 remote = fl->fl4_dst; - u32 local = fl->fl4_src; + __be32 remote = fl->fl4_dst; + __be32 local = fl->fl4_src; struct flowi fl_tunnel = { .nl_u = { .ip4_u = { @@ -203,7 +203,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) case IPPROTO_SCTP: case IPPROTO_DCCP: if (pskb_may_pull(skb, xprth + 4 - skb->data)) { - u16 *ports = (u16 *)xprth; + __be16 *ports = (__be16 *)xprth; fl->fl_ip_sport = ports[0]; fl->fl_ip_dport = ports[1]; diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index d400f8fae129..2fba1f0739aa 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -278,7 +278,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) case IPPROTO_SCTP: case IPPROTO_DCCP: if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { - u16 *ports = (u16 *)exthdr; + __be16 *ports = (__be16 *)exthdr; fl->fl_ip_sport = ports[0]; fl->fl_ip_dport = ports[1]; diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 7931e4f898d4..f26d81b6342c 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -62,7 +62,7 @@ static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) { unsigned h; - h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]; + h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]); h ^= h >> 16; h ^= h >> 8; h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1; @@ -126,7 +126,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) return NULL; } -u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; @@ -196,7 +196,7 @@ out: return spi; } -u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; -- cgit v1.2.3-70-g09d2 From 04ce69093f91547d3a7c4fc815d2868195591340 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:21:01 -0800 Subject: [IPV6]: 'info' argument of ipv6 ->err_handler() is net-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/protocol.h | 2 +- include/net/rawv6.h | 2 +- include/net/xfrm.h | 3 +-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/ipcomp6.c | 2 +- net/ipv6/raw.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/tunnel6.c | 2 +- net/ipv6/udp.c | 2 +- net/ipv6/xfrm6_tunnel.c | 2 +- net/sctp/ipv6.c | 2 +- 14 files changed, 14 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/include/net/protocol.h b/include/net/protocol.h index c643bce64e55..28c4cac3f8a2 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -50,7 +50,7 @@ struct inet6_protocol void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, - __u32 info); + __be32 info); int (*gso_send_check)(struct sk_buff *skb); struct sk_buff *(*gso_segment)(struct sk_buff *skb, diff --git a/include/net/rawv6.h b/include/net/rawv6.h index 14476a71725e..af8960878ef4 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -21,7 +21,7 @@ extern void rawv6_err(struct sock *sk, struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, - int offset, u32 info); + int offset, __be32 info); #endif diff --git a/include/net/xfrm.h b/include/net/xfrm.h index a63e277bacf7..9d30c08b9efc 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -887,8 +887,7 @@ struct xfrm_tunnel { struct xfrm6_tunnel { int (*handler)(struct sk_buff *skb); int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info); - + int type, int code, int offset, __be32 info); struct xfrm6_tunnel *next; int priority; }; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index b0d83e8e4252..2d9e495cf691 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -397,7 +397,7 @@ out: } static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index e78680a9985b..25dcf69cd807 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -256,7 +256,7 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) } static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4ec876066b3f..81bd45b26c98 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -555,7 +555,7 @@ out: icmpv6_xmit_unlock(); } -static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) +static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) { struct in6_addr *saddr, *daddr; struct inet6_protocol *ipprot; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index b9f40290d12a..6a3026dd865a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -391,7 +391,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) static int ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; struct ip6_tnl *t; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 71f59f18ede8..511730b67e97 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -176,7 +176,7 @@ out_ok: } static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { __be32 spi; struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d6dedc4aec77..6bc66552442c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -290,7 +290,7 @@ out: void rawv6_err(struct sock *sk, struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, u32 info) + int type, int code, int offset, __be32 info) { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4c2a7c0cafef..eb6d145ecfd7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -310,7 +310,7 @@ failure: } static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 0ef9a35798d1..918d07dd1219 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -104,7 +104,7 @@ drop: } static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct xfrm6_tunnel *handler; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c83f23e51c46..886300d13a59 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -238,7 +238,7 @@ csum_copy_err: } static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6_pinfo *np; struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index f26d81b6342c..01a5c52a2be3 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -265,7 +265,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) } static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { /* xfrm6_tunnel native err handling */ switch (type) { diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 78071c6e6cf1..3c316c688ade 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -84,7 +84,7 @@ static struct notifier_block sctp_inet6addr_notifier = { /* ICMP error handler. */ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct inet6_dev *idev; struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; -- cgit v1.2.3-70-g09d2 From 8a74ff7770f4795d7580392890fdf06821c78769 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:22:08 -0800 Subject: [IPV6]: annotate ipv6 mcast Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv6/mcast.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3b114e3fa2f8..9055979083b6 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -83,7 +83,7 @@ struct mld2_grec { __u8 grec_type; __u8 grec_auxwords; - __u16 grec_nsrcs; + __be16 grec_nsrcs; struct in6_addr grec_mca; struct in6_addr grec_src[0]; }; @@ -92,8 +92,8 @@ struct mld2_report { __u8 type; __u8 resv1; __u16 csum; - __u16 resv2; - __u16 ngrec; + __be16 resv2; + __be16 ngrec; struct mld2_grec grec[0]; }; @@ -101,8 +101,8 @@ struct mld2_query { __u8 type; __u8 code; __u16 csum; - __u16 mrc; - __u16 resv1; + __be16 mrc; + __be16 resv1; struct in6_addr mca; #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 qrv:3, @@ -116,7 +116,7 @@ struct mld2_query { #error "Please fix " #endif __u8 qqic; - __u16 nsrcs; + __be16 nsrcs; struct in6_addr srcs[0]; }; -- cgit v1.2.3-70-g09d2 From 4806126d78345ad8a99bca1367a8a39c08e19393 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:22:34 -0800 Subject: [SUNRPC]: annotate hash_ip() Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sunrpc/svcauth_unix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index e1bd933629fe..a0a953a430c2 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -101,9 +101,9 @@ static void ip_map_put(struct kref *kref) * IP addresses in reverse-endian (i.e. on a little-endian machine). * So use a trivial but reliable hash instead */ -static inline int hash_ip(unsigned long ip) +static inline int hash_ip(__be32 ip) { - int hash = ip ^ (ip>>16); + int hash = (__force u32)ip ^ ((__force u32)ip>>16); return (hash ^ (hash>>8)) & 0xff; } #endif @@ -284,7 +284,7 @@ static struct ip_map *ip_map_lookup(char *class, struct in_addr addr) ip.m_addr = addr; ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, hash_str(class, IP_HASHBITS) ^ - hash_ip((unsigned long)addr.s_addr)); + hash_ip(addr.s_addr)); if (ch) return container_of(ch, struct ip_map, h); @@ -313,7 +313,7 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex ch = sunrpc_cache_update(&ip_map_cache, &ip.h, &ipm->h, hash_str(ipm->m_class, IP_HASHBITS) ^ - hash_ip((unsigned long)ipm->m_addr.s_addr)); + hash_ip(ipm->m_addr.s_addr)); if (!ch) return -ENOMEM; cache_put(ch, &ip_map_cache); -- cgit v1.2.3-70-g09d2 From d5a0a1e3109339090769e40fdaa62482fcf2a717 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:23:14 -0800 Subject: [IPV4]: encapsulation annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/if_tunnel.h | 8 ++++---- include/linux/xfrm.h | 4 ++-- net/ipv4/ah4.c | 4 ++-- net/ipv4/esp4.c | 4 ++-- net/ipv4/ip_gre.c | 52 +++++++++++++++++++++++------------------------ net/ipv4/ipip.c | 16 +++++++-------- 6 files changed, 44 insertions(+), 44 deletions(-) (limited to 'net') diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index bef9f8fd93b3..8de079ba1107 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -19,10 +19,10 @@ struct ip_tunnel_parm { char name[IFNAMSIZ]; int link; - __u16 i_flags; - __u16 o_flags; - __u32 i_key; - __u32 o_key; + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; struct iphdr iph; }; diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 8ae7f744917b..7907c42bd4e4 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -211,8 +211,8 @@ struct xfrm_user_tmpl { struct xfrm_encap_tmpl { __u16 encap_type; - __u16 encap_sport; - __u16 encap_dport; + __be16 encap_sport; + __be16 encap_dport; xfrm_address_t encap_oa; }; diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 99542977e47e..67a5509e26fc 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -14,7 +14,7 @@ * into IP header for icv calculation. Options are already checked * for validity, so paranoia is not required. */ -static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) +static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr) { unsigned char * optptr = (unsigned char*)(iph+1); int l = iph->ihl*4 - sizeof(struct iphdr); @@ -162,7 +162,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) iph->frag_off = 0; iph->check = 0; if (ihl > sizeof(*iph)) { - u32 dummy; + __be32 dummy; if (ip_clear_mutable_options(iph, &dummy)) goto out; } diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index b5c205b57669..f2c6776ea0e6 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -67,7 +67,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; struct udphdr *uh; - u32 *udpdata32; + __be32 *udpdata32; uh = (struct udphdr *)esph; uh->source = encap->encap_sport; @@ -81,7 +81,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph = (struct ip_esp_hdr *)(uh + 1); break; case UDP_ENCAP_ESPINUDP_NON_IKE: - udpdata32 = (u32 *)(uh + 1); + udpdata32 = (__be32 *)(uh + 1); udpdata32[0] = udpdata32[1] = 0; esph = (struct ip_esp_hdr *)(udpdata32 + 2); break; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d5b5dec075b8..25221146debb 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -144,7 +144,7 @@ static struct net_device *ipgre_fb_tunnel_dev; */ #define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) +#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) static struct ip_tunnel *tunnels[4][HASH_SIZE]; @@ -157,7 +157,7 @@ static DEFINE_RWLOCK(ipgre_lock); /* Given src, dst and key, find appropriate for input tunnel. */ -static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) +static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key) { unsigned h0 = HASH(remote); unsigned h1 = HASH(key); @@ -194,9 +194,9 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t) { - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; - u32 key = t->parms.i_key; + __be32 remote = t->parms.iph.daddr; + __be32 local = t->parms.iph.saddr; + __be32 key = t->parms.i_key; unsigned h = HASH(key); int prio = 0; @@ -236,9 +236,9 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t) static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create) { - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; - u32 key = parms->i_key; + __be32 remote = parms->iph.daddr; + __be32 local = parms->iph.saddr; + __be32 key = parms->i_key; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = HASH(key); @@ -319,12 +319,12 @@ static void ipgre_err(struct sk_buff *skb, u32 info) */ struct iphdr *iph = (struct iphdr*)skb->data; - u16 *p = (u16*)(skb->data+(iph->ihl<<2)); + __be16 *p = (__be16*)(skb->data+(iph->ihl<<2)); int grehlen = (iph->ihl<<2) + 4; int type = skb->h.icmph->type; int code = skb->h.icmph->code; struct ip_tunnel *t; - u16 flags; + __be16 flags; flags = p[0]; if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { @@ -370,7 +370,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) } read_lock(&ipgre_lock); - t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0); + t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0); if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr)) goto out; @@ -388,14 +388,14 @@ out: #else struct iphdr *iph = (struct iphdr*)dp; struct iphdr *eiph; - u16 *p = (u16*)(dp+(iph->ihl<<2)); + __be16 *p = (__be16*)(dp+(iph->ihl<<2)); int type = skb->h.icmph->type; int code = skb->h.icmph->code; int rel_type = 0; int rel_code = 0; __be32 rel_info = 0; __u32 n = 0; - u16 flags; + __be16 flags; int grehlen = (iph->ihl<<2) + 4; struct sk_buff *skb2; struct flowi fl; @@ -556,9 +556,9 @@ static int ipgre_rcv(struct sk_buff *skb) { struct iphdr *iph; u8 *h; - u16 flags; + __be16 flags; u16 csum = 0; - u32 key = 0; + __be32 key = 0; u32 seqno = 0; struct ip_tunnel *tunnel; int offset = 4; @@ -568,7 +568,7 @@ static int ipgre_rcv(struct sk_buff *skb) iph = skb->nh.iph; h = skb->data; - flags = *(u16*)h; + flags = *(__be16*)h; if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { /* - Version must be 0. @@ -592,11 +592,11 @@ static int ipgre_rcv(struct sk_buff *skb) offset += 4; } if (flags&GRE_KEY) { - key = *(u32*)(h + offset); + key = *(__be32*)(h + offset); offset += 4; } if (flags&GRE_SEQ) { - seqno = ntohl(*(u32*)(h + offset)); + seqno = ntohl(*(__be32*)(h + offset)); offset += 4; } } @@ -605,7 +605,7 @@ static int ipgre_rcv(struct sk_buff *skb) if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) { secpath_reset(skb); - skb->protocol = *(u16*)(h + 2); + skb->protocol = *(__be16*)(h + 2); /* WCCP version 1 and 2 protocol decoding. * - Change protocol to IP * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header @@ -673,13 +673,13 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct iphdr *old_iph = skb->nh.iph; struct iphdr *tiph; u8 tos; - u16 df; + __be16 df; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ int gre_hlen; - u32 dst; + __be32 dst; int mtu; if (tunnel->recursion++) { @@ -860,11 +860,11 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); } - ((u16*)(iph+1))[0] = tunnel->parms.o_flags; - ((u16*)(iph+1))[1] = skb->protocol; + ((__be16*)(iph+1))[0] = tunnel->parms.o_flags; + ((__be16*)(iph+1))[1] = skb->protocol; if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { - u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4); + __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4); if (tunnel->parms.o_flags&GRE_SEQ) { ++tunnel->o_seqno; @@ -877,7 +877,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (tunnel->parms.o_flags&GRE_CSUM) { *ptr = 0; - *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); + *(__be16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); } } @@ -1068,7 +1068,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh { struct ip_tunnel *t = netdev_priv(dev); struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); - u16 *p = (u16*)(iph+1); + __be16 *p = (__be16*)(iph+1); memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); p[0] = t->parms.o_flags; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 0c4556529228..9d719d664e5b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -118,7 +118,7 @@ #include #define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) +#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) static int ipip_fb_tunnel_init(struct net_device *dev); static int ipip_tunnel_init(struct net_device *dev); @@ -134,7 +134,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne static DEFINE_RWLOCK(ipip_lock); -static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local) +static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -160,8 +160,8 @@ static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local) static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t) { - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; + __be32 remote = t->parms.iph.daddr; + __be32 local = t->parms.iph.saddr; unsigned h = 0; int prio = 0; @@ -203,8 +203,8 @@ static void ipip_tunnel_link(struct ip_tunnel *t) static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) { - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; + __be32 remote = parms->iph.daddr; + __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = 0; @@ -519,13 +519,13 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; u8 tos = tunnel->parms.iph.tos; - u16 df = tiph->frag_off; + __be16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *old_iph = skb->nh.iph; struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ - u32 dst = tiph->daddr; + __be32 dst = tiph->daddr; int mtu; if (tunnel->recursion++) { -- cgit v1.2.3-70-g09d2 From 5d36b1803d875cf101fdb972ff9c56663e508e39 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:24:06 -0800 Subject: [XFRM]: annotate ->new_mapping() Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++-- net/key/af_key.c | 2 +- net/xfrm/xfrm_state.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 9d30c08b9efc..dbcd2922ff3f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -379,7 +379,7 @@ struct xfrm_mgr int (*notify)(struct xfrm_state *x, struct km_event *c); int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir); - int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); + int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); }; @@ -999,7 +999,7 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, extern void xfrm_init_pmtu(struct dst_entry *dst); extern wait_queue_head_t km_waitq; -extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); +extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); diff --git a/net/key/af_key.c b/net/key/af_key.c index 20ff7cca1d07..4e1830999482 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2938,7 +2938,7 @@ out: return NULL; } -static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) +static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) { struct sk_buff *skb; struct sadb_msg *hdr; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 899de9ed22a6..864962bbda90 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1304,7 +1304,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) } EXPORT_SYMBOL(km_query); -int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) +int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) { int err = -EINVAL; struct xfrm_mgr *km; -- cgit v1.2.3-70-g09d2 From 90bcaf7b4a33bb9b100cc06869f0c033a870d4a0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:25:17 -0800 Subject: [IPV6]: flowlabels are net-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/in6.h | 4 ++-- include/linux/ip6_tunnel.h | 2 +- include/linux/ipv6.h | 2 +- include/net/flow.h | 2 +- include/net/ipv6.h | 4 ++-- net/ipv6/af_inet6.c | 2 +- net/ipv6/datagram.c | 10 +++++----- net/ipv6/ip6_flowlabel.c | 8 ++++---- net/ipv6/ip6_output.c | 4 ++-- net/ipv6/ip6_tunnel.c | 6 +++--- net/ipv6/route.c | 2 +- 11 files changed, 23 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/include/linux/in6.h b/include/linux/in6.h index f28621f638e0..4e8350ae8869 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -54,7 +54,7 @@ extern const struct in6_addr in6addr_loopback; struct sockaddr_in6 { unsigned short int sin6_family; /* AF_INET6 */ __be16 sin6_port; /* Transport layer port # */ - __u32 sin6_flowinfo; /* IPv6 flow information */ + __be32 sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ }; @@ -72,7 +72,7 @@ struct ipv6_mreq { struct in6_flowlabel_req { struct in6_addr flr_dst; - __u32 flr_label; + __be32 flr_label; __u8 flr_action; __u8 flr_share; __u16 flr_flags; diff --git a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h index 5c23aeb104ca..af3f4a70f3df 100644 --- a/include/linux/ip6_tunnel.h +++ b/include/linux/ip6_tunnel.h @@ -25,7 +25,7 @@ struct ip6_tnl_parm { __u8 proto; /* tunnel protocol */ __u8 encap_limit; /* encapsulation limit for tunnel */ __u8 hop_limit; /* hop limit for tunnel */ - __u32 flowinfo; /* traffic class and flowlabel for tunnel */ + __be32 flowinfo; /* traffic class and flowlabel for tunnel */ __u32 flags; /* tunnel flags */ struct in6_addr laddr; /* local tunnel end-point address */ struct in6_addr raddr; /* remote tunnel end-point address */ diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 4f435c59de06..f8241130f5ea 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -274,7 +274,7 @@ struct ipv6_pinfo { struct in6_addr *saddr_cache; #endif - __u32 flow_label; + __be32 flow_label; __u32 frag_size; __s16 hop_limit; __s16 mcast_hops; diff --git a/include/net/flow.h b/include/net/flow.h index 5cda27cd9deb..270d4c1761af 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -27,7 +27,7 @@ struct flowi { struct in6_addr daddr; struct in6_addr saddr; __u32 fwmark; - __u32 flowlabel; + __be32 flowlabel; } ip6_u; struct { diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4953fac1d070..0b8c9b990ac4 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -191,7 +191,7 @@ struct ipv6_txoptions struct ip6_flowlabel { struct ip6_flowlabel *next; - u32 label; + __be32 label; struct in6_addr dst; struct ipv6_txoptions *opt; atomic_t users; @@ -211,7 +211,7 @@ struct ipv6_fl_socklist struct ip6_flowlabel *fl; }; -extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, u32 label); +extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, struct ip6_flowlabel * fl, struct ipv6_txoptions * fopt); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 858cae29581c..92bfccf62cb7 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -678,7 +678,7 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) if (np->rxopt.all) { if ((opt->hop && (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) || - ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && + ((IPV6_FLOWINFO_MASK & *(__be32*)skb->nh.raw) && np->rxopt.bits.rxflow) || (opt->srcrt && (np->rxopt.bits.srcrt || np->rxopt.bits.osrcrt)) || diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 7206747022fc..a67434af691f 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -318,7 +318,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) ipv6_addr_copy(&sin->sin6_addr, (struct in6_addr *)(skb->nh.raw + serr->addr_offset)); if (np->sndflow) - sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; + sin->sin6_flowinfo = *(__be32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) sin->sin6_scope_id = IP6CB(skb)->iif; } else { @@ -401,8 +401,8 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); } - if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { - u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK; + if (np->rxopt.bits.rxflow && (*(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { + __be32 flowinfo = *(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK; put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); } @@ -560,12 +560,12 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, } if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) { - if ((fl->fl6_flowlabel^*(u32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { + if ((fl->fl6_flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { err = -EINVAL; goto exit_f; } } - fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); + fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); break; case IPV6_2292HOPOPTS: diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 6d4533b58dca..624fae251f4e 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -61,7 +61,7 @@ static DEFINE_RWLOCK(ip6_fl_lock); static DEFINE_RWLOCK(ip6_sk_fl_lock); -static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label) +static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label) { struct ip6_flowlabel *fl; @@ -72,7 +72,7 @@ static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label) return NULL; } -static struct ip6_flowlabel * fl_lookup(u32 label) +static struct ip6_flowlabel * fl_lookup(__be32 label) { struct ip6_flowlabel *fl; @@ -153,7 +153,7 @@ static void ip6_fl_gc(unsigned long dummy) write_unlock(&ip6_fl_lock); } -static int fl_intern(struct ip6_flowlabel *fl, __u32 label) +static int fl_intern(struct ip6_flowlabel *fl, __be32 label) { fl->label = label & IPV6_FLOWLABEL_MASK; @@ -182,7 +182,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __u32 label) /* Socket flowlabel lists */ -struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label) +struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label) { struct ipv6_fl_socklist *sfl; struct ipv6_pinfo *np = inet6_sk(sk); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 66716911962e..9ff1be1bc2e7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -217,7 +217,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (tclass < 0) tclass = 0; - *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; + *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; hdr->payload_len = htons(seg_len); hdr->nexthdr = proto; @@ -1311,7 +1311,7 @@ int ip6_push_pending_frames(struct sock *sk) skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); - *(u32*)hdr = fl->fl6_flowlabel | + *(__be32*)hdr = fl->fl6_flowlabel | htonl(0x60000000 | ((int)np->cork.tclass << 20)); if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 6a3026dd865a..4919f9294e2a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -665,9 +665,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) dsfield = ipv6_get_dsfield(ipv6h); if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) - fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK); + fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) - fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK); + fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL) goto tx_err; @@ -735,7 +735,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr)); ipv6h = skb->nh.ipv6h; - *(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); + *(__be32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); dsfield = INET_ECN_encapsulate(0, dsfield); ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b39ae99122d5..e9c1fc5f21b1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -714,7 +714,7 @@ void ip6_route_input(struct sk_buff *skb) #ifdef CONFIG_IPV6_ROUTE_FWMARK .fwmark = skb->nfmark, #endif - .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, + .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, }, }, .proto = iph->nexthdr, -- cgit v1.2.3-70-g09d2 From fede70b9862635ab1bed84ab3d765e9069616b02 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:25:41 -0800 Subject: [IPV6]: annotate inet6_csk_search_req() Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/inet6_connection_sock.h | 2 +- net/ipv6/inet6_connection_sock.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index b33b438bffcc..f13ddc2543b1 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -27,7 +27,7 @@ extern int inet6_csk_bind_conflict(const struct sock *sk, extern struct request_sock *inet6_csk_search_req(const struct sock *sk, struct request_sock ***prevp, - const __u16 rport, + const __be16 rport, const struct in6_addr *raddr, const struct in6_addr *laddr, const int iif); diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 827f41d1478b..e48fb4c53c4f 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); /* * request_sock (formerly open request) hash tables. */ -static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport, +static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, const u32 rnd, const u16 synq_hsize) { u32 a = raddr->s6_addr32[0]; @@ -65,7 +65,7 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport, __jhash_mix(a, b, c); a += raddr->s6_addr32[3]; - b += (u32)rport; + b += (__force u32)rport; __jhash_mix(a, b, c); return c & (synq_hsize - 1); @@ -73,7 +73,7 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport, struct request_sock *inet6_csk_search_req(const struct sock *sk, struct request_sock ***prevp, - const __u16 rport, + const __be16 rport, const struct in6_addr *raddr, const struct in6_addr *laddr, const int iif) -- cgit v1.2.3-70-g09d2 From 3fbd418acc264e7069483d04165633ed3bfad80c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:26:05 -0800 Subject: [LLC]: anotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/llc_pdu.h | 10 +++++----- net/llc/af_llc.c | 2 +- net/llc/llc_input.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h index 8f6306581fa7..aa33a477c3fb 100644 --- a/include/net/llc_pdu.h +++ b/include/net/llc_pdu.h @@ -252,9 +252,9 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type, */ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa) { - if (skb->protocol == ntohs(ETH_P_802_2)) + if (skb->protocol == htons(ETH_P_802_2)) memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN); - else if (skb->protocol == ntohs(ETH_P_TR_802_2)) { + else if (skb->protocol == htons(ETH_P_TR_802_2)) { memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN); *sa &= 0x7F; } @@ -269,9 +269,9 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa) */ static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da) { - if (skb->protocol == ntohs(ETH_P_802_2)) + if (skb->protocol == htons(ETH_P_802_2)) memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN); - else if (skb->protocol == ntohs(ETH_P_TR_802_2)) + else if (skb->protocol == htons(ETH_P_TR_802_2)) memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN); } @@ -345,7 +345,7 @@ static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb, pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST; pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; - if (ev_skb->protocol == ntohs(ETH_P_802_2)) { + if (ev_skb->protocol == htons(ETH_P_802_2)) { struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb); int dsize; diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2652ead96c64..190bb3e05188 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -64,7 +64,7 @@ static inline u16 llc_ui_next_link_no(int sap) * * Given an ARP header type return the corresponding ethernet protocol. */ -static inline u16 llc_proto_type(u16 arphrd) +static inline __be16 llc_proto_type(u16 arphrd) { return arphrd == ARPHRD_IEEE802_TR ? htons(ETH_P_TR_802_2) : htons(ETH_P_802_2); diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 94d2368ade92..db82aff6e40f 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -115,8 +115,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb) skb->h.raw += llc_len; skb_pull(skb, llc_len); if (skb->protocol == htons(ETH_P_802_2)) { - u16 pdulen = eth_hdr(skb)->h_proto, - data_size = ntohs(pdulen) - llc_len; + __be16 pdulen = eth_hdr(skb)->h_proto; + u16 data_size = ntohs(pdulen) - llc_len; if (unlikely(pskb_trim_rcsum(skb, data_size))) return 0; -- cgit v1.2.3-70-g09d2 From 0e11c91e1e912bc4db5b71607d149e7e9a77e756 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:26:29 -0800 Subject: [AF_PACKET]: annotate Weirdness: the third argument of socket() is net-endian here. Oh, well - it's documented in packet(7). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/if_packet.h | 6 ++++-- net/packet/af_packet.c | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index b92558549d27..99393ef3af39 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -1,17 +1,19 @@ #ifndef __LINUX_IF_PACKET_H #define __LINUX_IF_PACKET_H +#include + struct sockaddr_pkt { unsigned short spkt_family; unsigned char spkt_device[14]; - unsigned short spkt_protocol; + __be16 spkt_protocol; }; struct sockaddr_ll { unsigned short sll_family; - unsigned short sll_protocol; + __be16 sll_protocol; int sll_ifindex; unsigned short sll_hatype; unsigned char sll_pkttype; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f4ccb90e6739..271d2eed0699 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -201,7 +201,7 @@ struct packet_sock { spinlock_t bind_lock; char running; /* prot_hook is attached*/ int ifindex; /* bound device */ - unsigned short num; + __be16 num; #ifdef CONFIG_PACKET_MULTICAST struct packet_mclist *mclist; #endif @@ -331,7 +331,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name; struct sk_buff *skb; struct net_device *dev; - unsigned short proto=0; + __be16 proto=0; int err; /* @@ -704,7 +704,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name; struct sk_buff *skb; struct net_device *dev; - unsigned short proto; + __be16 proto; unsigned char *addr; int ifindex, err, reserve = 0; @@ -858,7 +858,7 @@ static int packet_release(struct socket *sock) * Attach a packet hook. */ -static int packet_do_bind(struct sock *sk, struct net_device *dev, int protocol) +static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol) { struct packet_sock *po = pkt_sk(sk); /* @@ -983,6 +983,7 @@ static int packet_create(struct socket *sock, int protocol) { struct sock *sk; struct packet_sock *po; + __be16 proto = (__force __be16)protocol; /* weird, but documented */ int err; if (!capable(CAP_NET_RAW)) @@ -1010,7 +1011,7 @@ static int packet_create(struct socket *sock, int protocol) po = pkt_sk(sk); sk->sk_family = PF_PACKET; - po->num = protocol; + po->num = proto; sk->sk_destruct = packet_sock_destruct; atomic_inc(&packet_socks_nr); @@ -1027,8 +1028,8 @@ static int packet_create(struct socket *sock, int protocol) #endif po->prot_hook.af_packet_priv = sk; - if (protocol) { - po->prot_hook.type = protocol; + if (proto) { + po->prot_hook.type = proto; dev_add_pack(&po->prot_hook); sock_hold(sk); po->running = 1; @@ -1624,7 +1625,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing { char **pg_vec = NULL; struct packet_sock *po = pkt_sk(sk); - int was_running, num, order = 0; + int was_running, order = 0; + __be16 num; int err = 0; if (req->tp_block_nr) { -- cgit v1.2.3-70-g09d2 From 98a4a86128d7179b22365e16bf880e849e20bc7d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:26:51 -0800 Subject: [NETFILTER]: trivial annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink.h | 2 +- include/linux/netfilter/nfnetlink_log.h | 10 +++++----- include/linux/netfilter/nfnetlink_queue.h | 18 +++++++++--------- include/linux/netfilter/xt_conntrack.h | 4 ++-- include/linux/netfilter/xt_policy.h | 2 +- include/linux/types.h | 2 ++ net/netfilter/nfnetlink_log.c | 22 ++++++++++------------ net/netfilter/nfnetlink_queue.c | 9 ++++----- net/netfilter/xt_multiport.c | 4 ++-- 9 files changed, 36 insertions(+), 37 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 6d8e3e5a80e9..1e9c821f152d 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -78,7 +78,7 @@ struct nfattr struct nfgenmsg { u_int8_t nfgen_family; /* AF_xxx */ u_int8_t version; /* nfnetlink version */ - u_int16_t res_id; /* resource id */ + __be16 res_id; /* resource id */ }; #define NFNETLINK_V0 0 diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index 87b92f8b988f..55a2a2b814ed 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -16,20 +16,20 @@ enum nfulnl_msg_types { }; struct nfulnl_msg_packet_hdr { - u_int16_t hw_protocol; /* hw protocol (network order) */ + __be16 hw_protocol; /* hw protocol (network order) */ u_int8_t hook; /* netfilter hook */ u_int8_t _pad; }; struct nfulnl_msg_packet_hw { - u_int16_t hw_addrlen; + __be16 hw_addrlen; u_int16_t _pad; u_int8_t hw_addr[8]; }; struct nfulnl_msg_packet_timestamp { - aligned_u64 sec; - aligned_u64 usec; + aligned_be64 sec; + aligned_be64 usec; }; #define NFULNL_PREFIXLEN 30 /* just like old log target */ @@ -67,7 +67,7 @@ struct nfulnl_msg_config_cmd { } __attribute__ ((packed)); struct nfulnl_msg_config_mode { - u_int32_t copy_range; + __be32 copy_range; u_int8_t copy_mode; u_int8_t _pad; } __attribute__ ((packed)); diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 36af0360b56d..4beea3d6fda8 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -13,20 +13,20 @@ enum nfqnl_msg_types { }; struct nfqnl_msg_packet_hdr { - u_int32_t packet_id; /* unique ID of packet in queue */ - u_int16_t hw_protocol; /* hw protocol (network order) */ + __be32 packet_id; /* unique ID of packet in queue */ + __be16 hw_protocol; /* hw protocol (network order) */ u_int8_t hook; /* netfilter hook */ } __attribute__ ((packed)); struct nfqnl_msg_packet_hw { - u_int16_t hw_addrlen; + __be16 hw_addrlen; u_int16_t _pad; u_int8_t hw_addr[8]; }; struct nfqnl_msg_packet_timestamp { - aligned_u64 sec; - aligned_u64 usec; + aligned_be64 sec; + aligned_be64 usec; }; enum nfqnl_attr_type { @@ -47,8 +47,8 @@ enum nfqnl_attr_type { #define NFQA_MAX (__NFQA_MAX - 1) struct nfqnl_msg_verdict_hdr { - u_int32_t verdict; - u_int32_t id; + __be32 verdict; + __be32 id; }; @@ -63,7 +63,7 @@ enum nfqnl_msg_config_cmds { struct nfqnl_msg_config_cmd { u_int8_t command; /* nfqnl_msg_config_cmds */ u_int8_t _pad; - u_int16_t pf; /* AF_xxx for PF_[UN]BIND */ + __be16 pf; /* AF_xxx for PF_[UN]BIND */ }; enum nfqnl_config_mode { @@ -73,7 +73,7 @@ enum nfqnl_config_mode { }; struct nfqnl_msg_config_params { - u_int32_t copy_range; + __be32 copy_range; u_int8_t copy_mode; /* enum nfqnl_config_mode */ } __attribute__ ((packed)); diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 4c2d9945ca54..70b6f718cf4c 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -29,14 +29,14 @@ struct ip_conntrack_old_tuple { struct { - __u32 ip; + __be32 ip; union { __u16 all; } u; } src; struct { - __u32 ip; + __be32 ip; union { __u16 all; } u; diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h index a8132ec076fb..45654d359a68 100644 --- a/include/linux/netfilter/xt_policy.h +++ b/include/linux/netfilter/xt_policy.h @@ -39,7 +39,7 @@ struct xt_policy_elem union xt_policy_addr smask; union xt_policy_addr daddr; union xt_policy_addr dmask; - u_int32_t spi; + __be32 spi; u_int32_t reqid; u_int8_t proto; u_int8_t mode; diff --git a/include/linux/types.h b/include/linux/types.h index 750f085fa564..9f11fdd2bd72 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -128,6 +128,8 @@ typedef __s64 int64_t; /* this is a special 64bit data type that is 8-byte aligned */ #define aligned_u64 unsigned long long __attribute__((aligned(8))) +#define aligned_be64 __be64 __attribute__((aligned(8))) +#define aligned_le64 __le64 __attribute__((aligned(8))) /** * The type used for indexing onto a disc or disc partition. diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 1e5207b80fe5..856ed0d19974 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -414,7 +414,7 @@ __build_packet_message(struct nfulnl_instance *inst, struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - u_int32_t tmp_uint; + __be32 tmp_uint; UDEBUG("entered\n"); @@ -508,11 +508,9 @@ __build_packet_message(struct nfulnl_instance *inst, if (indev && skb->dev && skb->dev->hard_header_parse) { struct nfulnl_msg_packet_hw phw; - - phw.hw_addrlen = - skb->dev->hard_header_parse((struct sk_buff *)skb, + int len = skb->dev->hard_header_parse((struct sk_buff *)skb, phw.hw_addr); - phw.hw_addrlen = htons(phw.hw_addrlen); + phw.hw_addrlen = htons(len); NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw); } @@ -529,7 +527,7 @@ __build_packet_message(struct nfulnl_instance *inst, if (skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) { - u_int32_t uid = htonl(skb->sk->sk_socket->file->f_uid); + __be32 uid = htonl(skb->sk->sk_socket->file->f_uid); /* need to unlock here since NFA_PUT may goto */ read_unlock_bh(&skb->sk->sk_callback_lock); NFA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid); @@ -882,15 +880,15 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } if (nfula[NFULA_CFG_TIMEOUT-1]) { - u_int32_t timeout = - *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]); + __be32 timeout = + *(__be32 *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]); nfulnl_set_timeout(inst, ntohl(timeout)); } if (nfula[NFULA_CFG_NLBUFSIZ-1]) { - u_int32_t nlbufsiz = - *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]); + __be32 nlbufsiz = + *(__be32 *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]); nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz)); } @@ -903,8 +901,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } if (nfula[NFULA_CFG_FLAGS-1]) { - u_int16_t flags = - *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]); + __be16 flags = + *(__be16 *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]); nfulnl_set_flags(inst, ntohs(flags)); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index e815a9aa6e95..4ab7b1416bb5 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -349,7 +349,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, struct sk_buff *entskb = entry->skb; struct net_device *indev; struct net_device *outdev; - unsigned int tmp_uint; + __be32 tmp_uint; QDEBUG("entered\n"); @@ -489,10 +489,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, && entskb->dev->hard_header_parse) { struct nfqnl_msg_packet_hw phw; - phw.hw_addrlen = - entskb->dev->hard_header_parse(entskb, + int len = entskb->dev->hard_header_parse(entskb, phw.hw_addr); - phw.hw_addrlen = htons(phw.hw_addrlen); + phw.hw_addrlen = htons(len); NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw); } @@ -835,7 +834,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, } if (nfqa[NFQA_MARK-1]) - entry->skb->nfmark = ntohl(*(u_int32_t *) + entry->skb->nfmark = ntohl(*(__be32 *) NFA_DATA(nfqa[NFQA_MARK-1])); issue_verdict(entry, verdict); diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c index d3aefd380930..b4293058c6ff 100644 --- a/net/netfilter/xt_multiport.c +++ b/net/netfilter/xt_multiport.c @@ -104,7 +104,7 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - u16 _ports[2], *pptr; + __be16 _ports[2], *pptr; const struct xt_multiport *multiinfo = matchinfo; if (offset) @@ -135,7 +135,7 @@ match_v1(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - u16 _ports[2], *pptr; + __be16 _ports[2], *pptr; const struct xt_multiport_v1 *multiinfo = matchinfo; if (offset) -- cgit v1.2.3-70-g09d2 From ae08e1f092210619fe49551aa3ed0dc0003d5880 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:27:11 -0800 Subject: [IPV6]: ip6_output annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- net/ipv6/ip6_output.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 85577a4ffa61..7fc9a3aaa1c9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -139,7 +139,7 @@ struct skb_shared_info { /* Warning: this field is not always filled in (UFO)! */ unsigned short gso_segs; unsigned short gso_type; - unsigned int ip6_frag_id; + __be32 ip6_frag_id; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; }; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9ff1be1bc2e7..93330685adfc 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -267,7 +267,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); skb->nh.ipv6h = hdr; - *(u32*)hdr = htonl(0x60000000); + *(__be32*)hdr = htonl(0x60000000); hdr->payload_len = htons(len); hdr->nexthdr = proto; @@ -571,7 +571,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) struct ipv6hdr *tmp_hdr; struct frag_hdr *fh; unsigned int mtu, hlen, left, len; - u32 frag_id = 0; + __be32 frag_id = 0; int ptr, offset = 0, err=0; u8 *prevhdr, nexthdr = 0; -- cgit v1.2.3-70-g09d2 From e41d21697326a38a0a871c515db88fa310177e24 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:27:36 -0800 Subject: [BLUETOOTH] bnep endianness bug: filtering by packet type <= and => don't work well on net-endian... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bluetooth/bnep/core.c | 16 ++++++++-------- net/bluetooth/bnep/netdev.c | 11 ++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 4d3424c2421c..4e822f08b87b 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -117,14 +117,14 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp) static inline void bnep_set_default_proto_filter(struct bnep_session *s) { /* (IPv4, ARP) */ - s->proto_filter[0].start = htons(0x0800); - s->proto_filter[0].end = htons(0x0806); + s->proto_filter[0].start = ETH_P_IP; + s->proto_filter[0].end = ETH_P_ARP; /* (RARP, AppleTalk) */ - s->proto_filter[1].start = htons(0x8035); - s->proto_filter[1].end = htons(0x80F3); + s->proto_filter[1].start = ETH_P_RARP; + s->proto_filter[1].end = ETH_P_AARP; /* (IPX, IPv6) */ - s->proto_filter[2].start = htons(0x8137); - s->proto_filter[2].end = htons(0x86DD); + s->proto_filter[2].start = ETH_P_IPX; + s->proto_filter[2].end = ETH_P_IPV6; } #endif @@ -150,8 +150,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len) int i; for (i = 0; i < n; i++) { - f[i].start = get_unaligned(data++); - f[i].end = get_unaligned(data++); + f[i].start = ntohs(get_unaligned(data++)); + f[i].end = ntohs(get_unaligned(data++)); BT_DBG("proto filter start %d end %d", f[i].start, f[i].end); diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 7f7b27db6a8f..67a002a9751a 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -158,14 +158,15 @@ static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s static inline u16 bnep_net_eth_proto(struct sk_buff *skb) { struct ethhdr *eh = (void *) skb->data; + u16 proto = ntohs(eh->h_proto); - if (ntohs(eh->h_proto) >= 1536) - return eh->h_proto; + if (proto >= 1536) + return proto; - if (get_unaligned((u16 *) skb->data) == 0xFFFF) - return htons(ETH_P_802_3); + if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF)) + return ETH_P_802_3; - return htons(ETH_P_802_2); + return ETH_P_802_2; } static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s) -- cgit v1.2.3-70-g09d2 From 1bc5d4483a83349f143e2bbf23ec144cd7e21e89 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:27:57 -0800 Subject: [BLUETOOTH]: bnep endianness annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bluetooth/bnep/bnep.h | 4 ++-- net/bluetooth/bnep/core.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index bbb1ed7097a9..0b6cd0e2528d 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -95,14 +95,14 @@ struct bnep_setup_conn_req { struct bnep_set_filter_req { __u8 type; __u8 ctrl; - __u16 len; + __be16 len; __u8 list[0]; } __attribute__((packed)); struct bnep_control_rsp { __u8 type; __u8 ctrl; - __u16 resp; + __be16 resp; } __attribute__((packed)); struct bnep_ext_hdr { diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 4e822f08b87b..7ba6470dc507 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -128,7 +128,7 @@ static inline void bnep_set_default_proto_filter(struct bnep_session *s) } #endif -static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len) +static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len) { int n; @@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) if (len < 2) return -EILSEQ; - n = ntohs(get_unaligned((u16 *) data)); + n = ntohs(get_unaligned((__be16 *) data)); data += 2; len -= 2; if (len < n) @@ -332,7 +332,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK])) goto badframe; - s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2)); + s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2)); if (type & BNEP_EXT_HEADER) { if (bnep_rx_extension(s, skb) < 0) @@ -343,7 +343,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) if (ntohs(s->eh.h_proto) == 0x8100) { if (!skb_pull(skb, 4)) goto badframe; - s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2)); + s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2)); } /* We have to alloc new skb and copy data here :(. Because original skb @@ -365,7 +365,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) case BNEP_COMPRESSED_SRC_ONLY: memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN); memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN); - put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2)); + put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); break; case BNEP_COMPRESSED_DST_ONLY: @@ -375,7 +375,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) case BNEP_GENERAL: memcpy(__skb_put(nskb, ETH_ALEN * 2), skb->mac.raw, ETH_ALEN * 2); - put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2)); + put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); break; } -- cgit v1.2.3-70-g09d2 From 6ba9c755e5f044c6a37296481bf6a861e4193a37 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:28:19 -0800 Subject: [BLUETOOTH]: rfcomm endianness annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/bluetooth/rfcomm.h | 4 ++-- net/bluetooth/rfcomm/core.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 89d743cfdfdf..3c563f02907c 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -124,7 +124,7 @@ struct rfcomm_pn { u8 flow_ctrl; u8 priority; u8 ack_timer; - u16 mtu; + __le16 mtu; u8 max_retrans; u8 credits; } __attribute__ ((packed)); @@ -136,7 +136,7 @@ struct rfcomm_rpn { u8 flow_ctrl; u8 xon_char; u8 xoff_char; - u16 param_mask; + __le16 param_mask; } __attribute__ ((packed)); struct rfcomm_rls { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ddc4e9d5963e..f3e5b7e2e04c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1018,7 +1018,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) if (len > 127) { hdr = (void *) skb_push(skb, 4); - put_unaligned(htobs(__len16(len)), (u16 *) &hdr->len); + put_unaligned(htobs(__len16(len)), (__le16 *) &hdr->len); } else { hdr = (void *) skb_push(skb, 3); hdr->len = __len8(len); -- cgit v1.2.3-70-g09d2 From e8db8c99100750ade5a9b4072b9469cab718a5b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:28:44 -0800 Subject: [BLUETOOTH] rfcomm endianness bug: param_mask is little-endian on the wire Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bluetooth/rfcomm/core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index f3e5b7e2e04c..278c8676906a 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -854,7 +854,7 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, rpn->flow_ctrl = flow_ctrl_settings; rpn->xon_char = xon_char; rpn->xoff_char = xoff_char; - rpn->param_mask = param_mask; + rpn->param_mask = cpu_to_le16(param_mask); *ptr = __fcs(buf); ptr++; @@ -1343,7 +1343,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit, * no parity, no flow control lines, normal XON/XOFF chars */ - if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_BITRATE)) { bit_rate = rpn->bit_rate; if (bit_rate != RFCOMM_RPN_BR_115200) { BT_DBG("RPN bit rate mismatch 0x%x", bit_rate); @@ -1352,7 +1352,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_DATA) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_DATA)) { data_bits = __get_rpn_data_bits(rpn->line_settings); if (data_bits != RFCOMM_RPN_DATA_8) { BT_DBG("RPN data bits mismatch 0x%x", data_bits); @@ -1361,7 +1361,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_STOP) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_STOP)) { stop_bits = __get_rpn_stop_bits(rpn->line_settings); if (stop_bits != RFCOMM_RPN_STOP_1) { BT_DBG("RPN stop bits mismatch 0x%x", stop_bits); @@ -1370,7 +1370,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_PARITY)) { parity = __get_rpn_parity(rpn->line_settings); if (parity != RFCOMM_RPN_PARITY_NONE) { BT_DBG("RPN parity mismatch 0x%x", parity); @@ -1379,7 +1379,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_FLOW)) { flow_ctrl = rpn->flow_ctrl; if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) { BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl); @@ -1388,7 +1388,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_XON) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XON)) { xon_char = rpn->xon_char; if (xon_char != RFCOMM_RPN_XON_CHAR) { BT_DBG("RPN XON char mismatch 0x%x", xon_char); @@ -1397,7 +1397,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ } } - if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { + if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XOFF)) { xoff_char = rpn->xoff_char; if (xoff_char != RFCOMM_RPN_XOFF_CHAR) { BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char); -- cgit v1.2.3-70-g09d2 From 6b877699c6f1efede4545bcecc367786a472eedb Mon Sep 17 00:00:00 2001 From: Venkat Yekkirala Date: Wed, 8 Nov 2006 17:04:09 -0600 Subject: SELinux: Return correct context for SO_PEERSEC Fix SO_PEERSEC for tcp sockets to return the security context of the peer (as represented by the SA from the peer) as opposed to the SA used by the local/source socket. Signed-off-by: Venkat Yekkirala Signed-off-by: James Morris --- include/linux/security.h | 16 +++++++++++++++- include/net/request_sock.h | 1 + net/ipv4/tcp_input.c | 2 ++ security/dummy.c | 6 ++++++ security/selinux/hooks.c | 21 +++++++++++++++++---- security/selinux/include/xfrm.h | 12 ++++++------ security/selinux/xfrm.c | 40 +++------------------------------------- 7 files changed, 50 insertions(+), 48 deletions(-) (limited to 'net') diff --git a/include/linux/security.h b/include/linux/security.h index a509329a669b..84cebcdb3f83 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -826,6 +826,8 @@ struct request_sock; * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid. * @inet_csk_clone: * Sets the new child socket's sid to the openreq sid. + * @inet_conn_established: + * Sets the connection's peersid to the secmark on skb. * @req_classify_flow: * Sets the flow's sid to the openreq sid. * @@ -1368,6 +1370,7 @@ struct security_operations { int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb, struct request_sock *req); void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); + void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb); void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); #endif /* CONFIG_SECURITY_NETWORK */ @@ -2961,9 +2964,15 @@ static inline void security_inet_csk_clone(struct sock *newsk, { security_ops->inet_csk_clone(newsk, req); } + +static inline void security_inet_conn_established(struct sock *sk, + struct sk_buff *skb) +{ + security_ops->inet_conn_established(sk, skb); +} #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct socket * sock, - struct socket * other, + struct socket * other, struct sock * newsk) { return 0; @@ -3110,6 +3119,11 @@ static inline void security_inet_csk_clone(struct sock *newsk, const struct request_sock *req) { } + +static inline void security_inet_conn_established(struct sock *sk, + struct sk_buff *skb) +{ +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 8e165ca16bd8..f743a941a4f2 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -54,6 +54,7 @@ struct request_sock { struct request_sock_ops *rsk_ops; struct sock *sk; u32 secid; + u32 peer_secid; }; static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cf06accbe687..4a8c96cdec7d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4230,6 +4230,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, mb(); tcp_set_state(sk, TCP_ESTABLISHED); + security_inet_conn_established(sk, skb); + /* Make sure socket is routed, for correct metrics. */ icsk->icsk_af_ops->rebuild_header(sk); diff --git a/security/dummy.c b/security/dummy.c index 838d8442cf3c..0148d1518dd1 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk, { } +static inline void dummy_inet_conn_established(struct sock *sk, + struct sk_buff *skb) +{ +} + static inline void dummy_req_classify_flow(const struct request_sock *req, struct flowi *fl) { @@ -1108,6 +1113,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, sock_graft); set_to_dummy_if_null(ops, inet_conn_request); set_to_dummy_if_null(ops, inet_csk_clone); + set_to_dummy_if_null(ops, inet_conn_established); set_to_dummy_if_null(ops, req_classify_flow); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 28ee187ed224..5bbd599a4471 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3535,8 +3535,10 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op } else if (isec->sclass == SECCLASS_TCP_SOCKET) { peer_sid = selinux_netlbl_socket_getpeersec_stream(sock); - if (peer_sid == SECSID_NULL) - peer_sid = selinux_socket_getpeer_stream(sock->sk); + if (peer_sid == SECSID_NULL) { + ssec = sock->sk->sk_security; + peer_sid = ssec->peer_sid; + } if (peer_sid == SECSID_NULL) { err = -ENOPROTOOPT; goto out; @@ -3647,11 +3649,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, return 0; } - err = selinux_xfrm_decode_session(skb, &peersid, 0); - BUG_ON(err); + selinux_skb_xfrm_sid(skb, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; + req->peer_secid = 0; return 0; } @@ -3660,6 +3662,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, return err; req->secid = newsid; + req->peer_secid = peersid; return 0; } @@ -3669,6 +3672,7 @@ static void selinux_inet_csk_clone(struct sock *newsk, struct sk_security_struct *newsksec = newsk->sk_security; newsksec->sid = req->secid; + newsksec->peer_sid = req->peer_secid; /* NOTE: Ideally, we should also get the isec->sid for the new socket in sync, but we don't have the isec available yet. So we will wait until sock_graft to do it, by which @@ -3677,6 +3681,14 @@ static void selinux_inet_csk_clone(struct sock *newsk, selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family); } +static void selinux_inet_conn_established(struct sock *sk, + struct sk_buff *skb) +{ + struct sk_security_struct *sksec = sk->sk_security; + + selinux_skb_xfrm_sid(skb, &sksec->peer_sid); +} + static void selinux_req_classify_flow(const struct request_sock *req, struct flowi *fl) { @@ -4739,6 +4751,7 @@ static struct security_operations selinux_ops = { .sock_graft = selinux_sock_graft, .inet_conn_request = selinux_inet_conn_request, .inet_csk_clone = selinux_inet_csk_clone, + .inet_conn_established = selinux_inet_conn_established, .req_classify_flow = selinux_req_classify_flow, #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 8e329ddb5e37..27502365d706 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -39,7 +39,6 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, struct avc_audit_data *ad); int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, struct avc_audit_data *ad); -u32 selinux_socket_getpeer_stream(struct sock *sk); u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); #else @@ -55,11 +54,6 @@ static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, return 0; } -static inline int selinux_socket_getpeer_stream(struct sock *sk) -{ - return SECSID_NULL; -} - static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb) { return SECSID_NULL; @@ -71,4 +65,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int } #endif +static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) +{ + int err = selinux_xfrm_decode_session(skb, sid, 0); + BUG_ON(err); +} + #endif /* _SELINUX_XFRM_H_ */ diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 4d5a043cdfa1..8fef74271f22 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -184,7 +184,8 @@ int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, } /* - * LSM hook implementation that determines the sid for the session. + * LSM hook implementation that checks and/or returns the xfrm sid for the + * incoming packet. */ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) @@ -402,44 +403,9 @@ void selinux_xfrm_state_free(struct xfrm_state *x) kfree(ctx); } -/* - * SELinux internal function to retrieve the context of a connected - * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security - * association used to connect to the remote socket. - * - * Retrieve via getsockopt SO_PEERSEC. - */ -u32 selinux_socket_getpeer_stream(struct sock *sk) -{ - struct dst_entry *dst, *dst_test; - u32 peer_sid = SECSID_NULL; - - if (sk->sk_state != TCP_ESTABLISHED) - goto out; - - dst = sk_dst_get(sk); - if (!dst) - goto out; - - for (dst_test = dst; dst_test != 0; - dst_test = dst_test->child) { - struct xfrm_state *x = dst_test->xfrm; - - if (x && selinux_authorizable_xfrm(x)) { - struct xfrm_sec_ctx *ctx = x->security; - peer_sid = ctx->ctx_sid; - break; - } - } - dst_release(dst); - -out: - return peer_sid; -} - /* * SELinux internal function to retrieve the context of a UDP packet - * based on its security association used to connect to the remote socket. + * based on its security association. * * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message * type SCM_SECURITY. -- cgit v1.2.3-70-g09d2 From 67f83cbf081a70426ff667e8d14f94e13ed3bdca Mon Sep 17 00:00:00 2001 From: Venkat Yekkirala Date: Wed, 8 Nov 2006 17:04:26 -0600 Subject: SELinux: Fix SA selection semantics Fix the selection of an SA for an outgoing packet to be at the same context as the originating socket/flow. This eliminates the SELinux policy's ability to use/sendto SAs with contexts other than the socket's. With this patch applied, the SELinux policy will require one or more of the following for a socket to be able to communicate with/without SAs: 1. To enable a socket to communicate without using labeled-IPSec SAs: allow socket_t unlabeled_t:association { sendto recvfrom } 2. To enable a socket to communicate with labeled-IPSec SAs: allow socket_t self:association { sendto }; allow socket_t peer_sa_t:association { recvfrom }; Signed-off-by: Venkat Yekkirala Signed-off-by: James Morris --- include/linux/security.h | 19 -------- net/xfrm/xfrm_policy.c | 3 +- security/dummy.c | 7 --- security/selinux/hooks.c | 26 +++++++---- security/selinux/include/xfrm.h | 7 +-- security/selinux/xfrm.c | 101 +++++++++++++++++++--------------------- 6 files changed, 70 insertions(+), 93 deletions(-) (limited to 'net') diff --git a/include/linux/security.h b/include/linux/security.h index 84cebcdb3f83..83cdefae9931 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -886,11 +886,6 @@ struct request_sock; * @xp contains the policy to check for a match. * @fl contains the flow to check for a match. * Return 1 if there is a match. - * @xfrm_flow_state_match: - * @fl contains the flow key to match. - * @xfrm points to the xfrm_state to match. - * @xp points to the xfrm_policy to match. - * Return 1 if there is a match. * @xfrm_decode_session: * @skb points to skb to decode. * @secid points to the flow key secid to set. @@ -1388,8 +1383,6 @@ struct security_operations { int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, struct xfrm_policy *xp, struct flowi *fl); - int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm, - struct xfrm_policy *xp); int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); #endif /* CONFIG_SECURITY_NETWORK_XFRM */ @@ -3186,12 +3179,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, return security_ops->xfrm_state_pol_flow_match(x, xp, fl); } -static inline int security_xfrm_flow_state_match(struct flowi *fl, - struct xfrm_state *xfrm, struct xfrm_policy *xp) -{ - return security_ops->xfrm_flow_state_match(fl, xfrm, xp); -} - static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) { return security_ops->xfrm_decode_session(skb, secid, 1); @@ -3255,12 +3242,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, return 1; } -static inline int security_xfrm_flow_state_match(struct flowi *fl, - struct xfrm_state *xfrm, struct xfrm_policy *xp) -{ - return 1; -} - static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) { return 0; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7736b23c3f03..b88b038530c9 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1894,7 +1894,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) return 0; - if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol)) + if (fl && pol && + !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl)) return 0; if (dst->xfrm->km.state != XFRM_STATE_VALID) return 0; diff --git a/security/dummy.c b/security/dummy.c index 0148d1518dd1..558795b237d6 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -886,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x, return 1; } -static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, - struct xfrm_policy *xp) -{ - return 1; -} - static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) { return 0; @@ -1126,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, xfrm_state_delete_security); set_to_dummy_if_null(ops, xfrm_policy_lookup); set_to_dummy_if_null(ops, xfrm_state_pol_flow_match); - set_to_dummy_if_null(ops, xfrm_flow_state_match); set_to_dummy_if_null(ops, xfrm_decode_session); #endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_KEYS diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5bbd599a4471..956137baf3e7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2889,7 +2889,8 @@ static void selinux_task_to_inode(struct task_struct *p, } /* Returns error only if unable to parse addresses */ -static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) +static int selinux_parse_skb_ipv4(struct sk_buff *skb, + struct avc_audit_data *ad, u8 *proto) { int offset, ihlen, ret = -EINVAL; struct iphdr _iph, *ih; @@ -2907,6 +2908,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad ad->u.net.v4info.daddr = ih->daddr; ret = 0; + if (proto) + *proto = ih->protocol; + switch (ih->protocol) { case IPPROTO_TCP: { struct tcphdr _tcph, *th; @@ -2950,7 +2954,8 @@ out: #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /* Returns error only if unable to parse addresses */ -static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad) +static int selinux_parse_skb_ipv6(struct sk_buff *skb, + struct avc_audit_data *ad, u8 *proto) { u8 nexthdr; int ret = -EINVAL, offset; @@ -2971,6 +2976,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad if (offset < 0) goto out; + if (proto) + *proto = nexthdr; + switch (nexthdr) { case IPPROTO_TCP: { struct tcphdr _tcph, *th; @@ -3007,13 +3015,13 @@ out: #endif /* IPV6 */ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, - char **addrp, int *len, int src) + char **addrp, int *len, int src, u8 *proto) { int ret = 0; switch (ad->u.net.family) { case PF_INET: - ret = selinux_parse_skb_ipv4(skb, ad); + ret = selinux_parse_skb_ipv4(skb, ad, proto); if (ret || !addrp) break; *len = 4; @@ -3023,7 +3031,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: - ret = selinux_parse_skb_ipv6(skb, ad); + ret = selinux_parse_skb_ipv6(skb, ad, proto); if (ret || !addrp) break; *len = 16; @@ -3494,7 +3502,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); + err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); if (err) goto out; @@ -3820,6 +3828,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, struct avc_audit_data ad; struct net_device *dev = (struct net_device *)out; struct sk_security_struct *sksec; + u8 proto; sk = skb->sk; if (!sk) @@ -3831,7 +3840,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ad.u.net.netif = dev->name; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 0); + err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); if (err) goto out; @@ -3845,7 +3854,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, if (err) goto out; - err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); + err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); out: return err ? NF_DROP : NF_ACCEPT; } @@ -4764,7 +4773,6 @@ static struct security_operations selinux_ops = { .xfrm_state_delete_security = selinux_xfrm_state_delete, .xfrm_policy_lookup = selinux_xfrm_policy_lookup, .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, - .xfrm_flow_state_match = selinux_xfrm_flow_state_match, .xfrm_decode_session = selinux_xfrm_decode_session, #endif diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 27502365d706..ebd7246a4be5 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -19,9 +19,6 @@ int selinux_xfrm_state_delete(struct xfrm_state *x); int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, struct flowi *fl); -int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, - struct xfrm_policy *xp); - /* * Extract the security blob from the sock (it's actually on the socket) @@ -38,7 +35,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk) int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, struct avc_audit_data *ad); int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad); + struct avc_audit_data *ad, u8 proto); u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); #else @@ -49,7 +46,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, } static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) + struct avc_audit_data *ad, u8 proto) { return 0; } diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 8fef74271f22..9b777140068f 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -115,71 +115,40 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy * struct flowi *fl) { u32 state_sid; - u32 pol_sid; - int err; + int rc; - if (xp->security) { - if (!x->security) - /* unlabeled SA and labeled policy can't match */ - return 0; - else - state_sid = x->security->ctx_sid; - pol_sid = xp->security->ctx_sid; - } else + if (!xp->security) if (x->security) /* unlabeled policy and labeled SA can't match */ return 0; else /* unlabeled policy and unlabeled SA match all flows */ return 1; - - err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__POLMATCH, - NULL); - - if (err) - return 0; - - err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__SENDTO, - NULL)? 0:1; - - return err; -} - -/* - * LSM hook implementation that authorizes that a particular outgoing flow - * can use a given security association. - */ - -int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, - struct xfrm_policy *xp) -{ - int rc = 0; - u32 sel_sid = SECINITSID_UNLABELED; - struct xfrm_sec_ctx *ctx; - - if (!xp->security) - if (!xfrm->security) - return 1; - else - return 0; else - if (!xfrm->security) + if (!x->security) + /* unlabeled SA and labeled policy can't match */ return 0; + else + if (!selinux_authorizable_xfrm(x)) + /* Not a SELinux-labeled SA */ + return 0; - /* Context sid is either set to label or ANY_ASSOC */ - if ((ctx = xfrm->security)) { - if (!selinux_authorizable_ctx(ctx)) - return 0; + state_sid = x->security->ctx_sid; - sel_sid = ctx->ctx_sid; - } + if (fl->secid != state_sid) + return 0; - rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION, + rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, NULL)? 0:1; + /* + * We don't need a separate SA Vs. policy polmatch check + * since the SA is now of the same label as the flow and + * a flow Vs. policy polmatch check had already happened + * in selinux_xfrm_policy_lookup() above. + */ + return rc; } @@ -481,6 +450,13 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, } } + /* + * This check even when there's no association involved is + * intended, according to Trent Jaeger, to make sure a + * process can't engage in non-ipsec communication unless + * explicitly allowed by policy. + */ + rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); @@ -492,10 +468,10 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, * If we have no security association, then we need to determine * whether the socket is allowed to send to an unlabelled destination. * If we do have a authorizable security association, then it has already been - * checked in xfrm_policy_lookup hook. + * checked in the selinux_xfrm_state_pol_flow_match hook above. */ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) + struct avc_audit_data *ad, u8 proto) { struct dst_entry *dst; int rc = 0; @@ -514,6 +490,27 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, } } + switch (proto) { + case IPPROTO_AH: + case IPPROTO_ESP: + case IPPROTO_COMP: + /* + * We should have already seen this packet once before + * it underwent xfrm(s). No need to subject it to the + * unlabeled check. + */ + goto out; + default: + break; + } + + /* + * This check even when there's no association involved is + * intended, according to Trent Jaeger, to make sure a + * process can't engage in non-ipsec communication unless + * explicitly allowed by policy. + */ + rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); out: -- cgit v1.2.3-70-g09d2 From fcc70d5fdc9b0bd3e99c9dacb8198224af2b4b42 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 8 Nov 2006 22:44:35 -0800 Subject: [BLUETOOTH] lockdep: annotate sk_lock nesting in AF_BLUETOOTH ============================================= [ INFO: possible recursive locking detected ] 2.6.18-1.2726.fc6 #1 --- include/net/sock.h | 8 +++++++- net/bluetooth/l2cap.c | 4 ++-- net/core/sock.c | 6 +++--- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/net/sock.h b/include/net/sock.h index 9cdbae2a53a3..35ffbdd35d3e 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -745,7 +745,13 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size) */ #define sock_owned_by_user(sk) ((sk)->sk_lock.owner) -extern void FASTCALL(lock_sock(struct sock *sk)); +extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass)); + +static inline void lock_sock(struct sock *sk) +{ + lock_sock_nested(sk, 0); +} + extern void FASTCALL(release_sock(struct sock *sk)); /* BH context may only use the following locking interface. */ diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index bbf78e6a7bc3..29a8fa4d3728 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -770,7 +770,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl long timeo; int err = 0; - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_state != BT_LISTEN) { err = -EBADFD; @@ -792,7 +792,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl release_sock(sk); timeo = schedule_timeout(timeo); - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_state != BT_LISTEN) { err = -EBADFD; diff --git a/net/core/sock.c b/net/core/sock.c index ee6cd2541d35..32ff1c551d69 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1527,7 +1527,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) atomic_set(&sk->sk_refcnt, 1); } -void fastcall lock_sock(struct sock *sk) +void fastcall lock_sock_nested(struct sock *sk, int subclass) { might_sleep(); spin_lock_bh(&sk->sk_lock.slock); @@ -1538,11 +1538,11 @@ void fastcall lock_sock(struct sock *sk) /* * The sk_lock has mutex_lock() semantics here: */ - mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); + mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); local_bh_enable(); } -EXPORT_SYMBOL(lock_sock); +EXPORT_SYMBOL(lock_sock_nested); void fastcall release_sock(struct sock *sk) { -- cgit v1.2.3-70-g09d2 From 776810217ac558351cdcca01c4c6a9474e4a68c2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 8 Nov 2006 22:46:26 -0800 Subject: [XFRM]: uninline xfrm_selector_match() Six callsites, huge. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/net/xfrm.h | 36 ++---------------------------------- net/xfrm/xfrm_policy.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) (limited to 'net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index dbcd2922ff3f..81c91e8a328f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -506,40 +506,8 @@ __be16 xfrm_flowi_dport(struct flowi *fl) return port; } -static inline int -__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) -{ - return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && - addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && - !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && - !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && - (fl->proto == sel->proto || !sel->proto) && - (fl->oif == sel->ifindex || !sel->ifindex); -} - -static inline int -__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) -{ - return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && - addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) && - !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && - !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && - (fl->proto == sel->proto || !sel->proto) && - (fl->oif == sel->ifindex || !sel->ifindex); -} - -static inline int -xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, - unsigned short family) -{ - switch (family) { - case AF_INET: - return __xfrm4_selector_match(sel, fl); - case AF_INET6: - return __xfrm6_selector_match(sel, fl); - } - return 0; -} +extern int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, + unsigned short family); #ifdef CONFIG_SECURITY_NETWORK_XFRM /* If neither has a context --> match diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b88b038530c9..e5ea1347a4ff 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -50,6 +50,40 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); +static inline int +__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) +{ + return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && + addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && + !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && + !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && + (fl->proto == sel->proto || !sel->proto) && + (fl->oif == sel->ifindex || !sel->ifindex); +} + +static inline int +__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) +{ + return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && + addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) && + !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && + !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && + (fl->proto == sel->proto || !sel->proto) && + (fl->oif == sel->ifindex || !sel->ifindex); +} + +int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, + unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_selector_match(sel, fl); + case AF_INET6: + return __xfrm6_selector_match(sel, fl); + } + return 0; +} + int xfrm_register_type(struct xfrm_type *type, unsigned short family) { struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); -- cgit v1.2.3-70-g09d2 From 0afc46c4683df512eef34a71a85065dc555c2af2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 8 Nov 2006 23:02:19 -0800 Subject: [DECNET]: Don't clear memory twice. When dn_neigh.c was converted from kmalloc to kzalloc in commit 0da974f4f303a6842516b764507e3c0a03f41e5a it was missed that dn_neigh_seq_open was actually clearing the allocation twice was missed. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- net/decnet/dn_neigh.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index ff0ebe99137d..7322bb36e825 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -591,7 +591,6 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file) seq = file->private_data; seq->private = s; - memset(s, 0, sizeof(*s)); out: return rc; out_kfree: -- cgit v1.2.3-70-g09d2 From 82e91ffef60e6eba9848fe149ce1eecd2b5aef12 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:19:14 -0800 Subject: [NET]: Turn nfmark into generic mark nfmark is being used in various subsystems and has become the defacto mark field for all kinds of packets. Therefore it makes sense to rename it to `mark' and remove the dependency on CONFIG_NETFILTER. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- net/bridge/netfilter/ebt_mark.c | 8 ++++---- net/bridge/netfilter/ebt_mark_m.c | 4 ++-- net/bridge/netfilter/ebt_ulog.c | 2 +- net/core/skbuff.c | 4 ++-- net/decnet/dn_route.c | 4 ++-- net/ipv4/ip_output.c | 2 +- net/ipv4/ipvs/ip_vs_proto_tcp.c | 2 +- net/ipv4/ipvs/ip_vs_proto_udp.c | 2 +- net/ipv4/netfilter.c | 2 +- net/ipv4/netfilter/ip_queue.c | 2 +- net/ipv4/netfilter/ipt_REJECT.c | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 2 +- net/ipv4/netfilter/iptable_mangle.c | 6 +++--- net/ipv4/route.c | 10 +++++----- net/ipv6/ip6_output.c | 2 +- net/ipv6/netfilter/ip6_queue.c | 2 +- net/ipv6/netfilter/ip6table_mangle.c | 9 ++++----- net/ipv6/route.c | 2 +- net/netfilter/nfnetlink_log.c | 4 ++-- net/netfilter/nfnetlink_queue.c | 8 ++++---- net/netfilter/xt_CONNMARK.c | 10 +++++----- net/netfilter/xt_MARK.c | 12 ++++++------ net/netfilter/xt_mark.c | 2 +- net/sched/Kconfig | 2 +- net/sched/cls_fw.c | 6 +----- net/sched/cls_u32.c | 2 +- net/sched/em_meta.c | 10 +++------- 28 files changed, 59 insertions(+), 68 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 7fc9a3aaa1c9..e3ae544b3956 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -216,7 +216,7 @@ enum { * @tail: Tail pointer * @end: End pointer * @destructor: Destruct function - * @nfmark: Can be used for communication between hooks + * @mark: Generic packet mark * @nfct: Associated connection, if any * @ipvs_property: skbuff is owned by ipvs * @nfctinfo: Relationship of this skb to the connection @@ -295,7 +295,6 @@ struct sk_buff { #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif - __u32 nfmark; #endif /* CONFIG_NETFILTER */ #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ @@ -310,6 +309,7 @@ struct sk_buff { __u32 secmark; #endif + __u32 mark; /* These elements must be at the end, see alloc_skb() for details. */ unsigned int truesize; diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index b54306a934e5..2458638561cb 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, int action = info->target & -16; if (action == MARK_SET_VALUE) - (*pskb)->nfmark = info->mark; + (*pskb)->mark = info->mark; else if (action == MARK_OR_VALUE) - (*pskb)->nfmark |= info->mark; + (*pskb)->mark |= info->mark; else if (action == MARK_AND_VALUE) - (*pskb)->nfmark &= info->mark; + (*pskb)->mark &= info->mark; else - (*pskb)->nfmark ^= info->mark; + (*pskb)->mark ^= info->mark; return info->target | -16; } diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index a6413e4b4982..025869ee0b68 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c @@ -19,8 +19,8 @@ static int ebt_filter_mark(const struct sk_buff *skb, struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; if (info->bitmask & EBT_MARK_OR) - return !(!!(skb->nfmark & info->mask) ^ info->invert); - return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert); + return !(!!(skb->mark & info->mask) ^ info->invert); + return !(((skb->mark & info->mask) == info->mark) ^ info->invert); } static int ebt_mark_check(const char *tablename, unsigned int hookmask, diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 9f950db3b76f..c1af68b5a29c 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -168,7 +168,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, if (ub->qlen == 1) skb_set_timestamp(ub->skb, &pm->stamp); pm->data_len = copy_len; - pm->mark = skb->nfmark; + pm->mark = skb->mark; pm->hook = hooknr; if (uloginfo->prefix != NULL) strcpy(pm->prefix, uloginfo->prefix); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b8b106358040..b3dea1ef9535 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -473,8 +473,8 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) #endif C(protocol); n->destructor = NULL; + C(mark); #ifdef CONFIG_NETFILTER - C(nfmark); C(nfct); nf_conntrack_get(skb->nfct); C(nfctinfo); @@ -534,8 +534,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->pkt_type = old->pkt_type; new->tstamp = old->tstamp; new->destructor = NULL; + new->mark = old->mark; #ifdef CONFIG_NETFILTER - new->nfmark = old->nfmark; new->nfct = old->nfct; nf_conntrack_get(old->nfct); new->nfctinfo = old->nfctinfo; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 23489f7232d2..3482839af280 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1236,7 +1236,7 @@ static int dn_route_input_slow(struct sk_buff *skb) .saddr = cb->src, .scope = RT_SCOPE_UNIVERSE, #ifdef CONFIG_DECNET_ROUTE_FWMARK - .fwmark = skb->nfmark + .fwmark = skb->mark #endif } }, .iif = skb->dev->ifindex }; @@ -1458,7 +1458,7 @@ int dn_route_input(struct sk_buff *skb) (rt->fl.fld_dst == cb->dst) && (rt->fl.oif == 0) && #ifdef CONFIG_DECNET_ROUTE_FWMARK - (rt->fl.fld_fwmark == skb->nfmark) && + (rt->fl.fld_fwmark == skb->mark) && #endif (rt->fl.iif == cb->iif)) { rt->u.dst.lastuse = jiffies; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fc195a44fc2e..23633bf042ba 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -386,6 +386,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) dst_release(to->dst); to->dst = dst_clone(from->dst); to->dev = from->dev; + to->mark = from->mark; /* Copy the flags to each fragment. */ IPCB(to)->flags = IPCB(from)->flags; @@ -394,7 +395,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->tc_index = from->tc_index; #endif #ifdef CONFIG_NETFILTER - to->nfmark = from->nfmark; /* Connection association is same as pre-frag packet */ nf_conntrack_put(to->nfct); to->nfct = from->nfct; diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index 6ff05c3a32e6..7de385267b33 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -84,7 +84,7 @@ tcp_conn_schedule(struct sk_buff *skb, } if (th->syn && - (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, + (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, skb->nh.iph->daddr, th->dest))) { if (ip_vs_todrop()) { /* diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 691c8b637b29..452cb9c384b3 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -89,7 +89,7 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, return 0; } - if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, + if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, skb->nh.iph->daddr, uh->dest))) { if (ip_vs_todrop()) { /* diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index e2005c6810a4..bfc8d753a23a 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -28,7 +28,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; #ifdef CONFIG_IP_ROUTE_FWMARK - fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark; + fl.nl_u.ip4_u.fwmark = (*pskb)->mark; #endif if (ip_route_output_key(&rt, &fl) != 0) return -1; diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 97556cc2e4e0..cd520df4dcf4 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -243,7 +243,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->data_len = data_len; pmsg->timestamp_sec = entry->skb->tstamp.off_sec; pmsg->timestamp_usec = entry->skb->tstamp.off_usec; - pmsg->mark = entry->skb->nfmark; + pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 264763adc39b..f0319e5ee437 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -76,7 +76,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) /* This packet will not be the same as the other: clear nf fields */ nf_reset(nskb); - nskb->nfmark = 0; + nskb->mark = 0; skb_init_secmark(nskb); tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 2b104ea54f48..dbd34783a64d 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -239,7 +239,7 @@ static void ipt_ulog_packet(unsigned int hooknum, pm->data_len = copy_len; pm->timestamp_sec = skb->tstamp.off_sec; pm->timestamp_usec = skb->tstamp.off_usec; - pm->mark = skb->nfmark; + pm->mark = skb->mark; pm->hook = hooknum; if (prefix != NULL) strncpy(pm->prefix, prefix, sizeof(pm->prefix)); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index b91f3582359b..62d4ccc259ca 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -132,7 +132,7 @@ ipt_local_hook(unsigned int hook, unsigned int ret; u_int8_t tos; __be32 saddr, daddr; - unsigned long nfmark; + u_int32_t mark; /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) @@ -143,7 +143,7 @@ ipt_local_hook(unsigned int hook, } /* Save things which could affect route */ - nfmark = (*pskb)->nfmark; + mark = (*pskb)->mark; saddr = (*pskb)->nh.iph->saddr; daddr = (*pskb)->nh.iph->daddr; tos = (*pskb)->nh.iph->tos; @@ -154,7 +154,7 @@ ipt_local_hook(unsigned int hook, && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr #ifdef CONFIG_IP_ROUTE_FWMARK - || (*pskb)->nfmark != nfmark + || (*pskb)->mark != mark #endif || (*pskb)->nh.iph->tos != tos)) if (ip_route_me_harder(pskb, RTN_UNSPEC)) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 925ee4dfc32c..4de3e38fa1a8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1644,7 +1644,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -1790,7 +1790,7 @@ static inline int __mkroute_input(struct sk_buff *skb, rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -1921,7 +1921,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, .tos = tos, .scope = RT_SCOPE_UNIVERSE, #ifdef CONFIG_IP_ROUTE_FWMARK - .fwmark = skb->nfmark + .fwmark = skb->mark #endif } }, .iif = dev->ifindex }; @@ -2035,7 +2035,7 @@ local_input: rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -2114,7 +2114,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.iif == iif && rth->fl.oif == 0 && #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark == skb->nfmark && + rth->fl.fl4_fwmark == skb->mark && #endif rth->fl.fl4_tos == tos) { rth->u.dst.lastuse = jiffies; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 93330685adfc..1bde3aca3466 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -499,12 +499,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) dst_release(to->dst); to->dst = dst_clone(from->dst); to->dev = from->dev; + to->mark = from->mark; #ifdef CONFIG_NET_SCHED to->tc_index = from->tc_index; #endif #ifdef CONFIG_NETFILTER - to->nfmark = from->nfmark; /* Connection association is same as pre-frag packet */ nf_conntrack_put(to->nfct); to->nfct = from->nfct; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9fec832ee08b..21908c9a10da 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -241,7 +241,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->data_len = data_len; pmsg->timestamp_sec = entry->skb->tstamp.off_sec; pmsg->timestamp_usec = entry->skb->tstamp.off_usec; - pmsg->mark = entry->skb->nfmark; + pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 386ea260e767..6250e86a6ddc 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -149,11 +149,10 @@ ip6t_local_hook(unsigned int hook, int (*okfn)(struct sk_buff *)) { - unsigned long nfmark; unsigned int ret; struct in6_addr saddr, daddr; u_int8_t hop_limit; - u_int32_t flowlabel; + u_int32_t flowlabel, mark; #if 0 /* root is playing with raw sockets. */ @@ -165,10 +164,10 @@ ip6t_local_hook(unsigned int hook, } #endif - /* save source/dest address, nfmark, hoplimit, flowlabel, priority, */ + /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); - nfmark = (*pskb)->nfmark; + mark = (*pskb)->mark; hop_limit = (*pskb)->nh.ipv6h->hop_limit; /* flowlabel and prio (includes version, which shouldn't change either */ @@ -179,7 +178,7 @@ ip6t_local_hook(unsigned int hook, if (ret != NF_DROP && ret != NF_STOLEN && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) - || (*pskb)->nfmark != nfmark + || (*pskb)->mark != mark || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e9c1fc5f21b1..aaabb1fad1cf 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -712,7 +712,7 @@ void ip6_route_input(struct sk_buff *skb) .daddr = iph->daddr, .saddr = iph->saddr, #ifdef CONFIG_IPV6_ROUTE_FWMARK - .fwmark = skb->nfmark, + .fwmark = skb->mark, #endif .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, }, diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 856ed0d19974..bd3ffa6f1a6d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -501,8 +501,8 @@ __build_packet_message(struct nfulnl_instance *inst, #endif } - if (skb->nfmark) { - tmp_uint = htonl(skb->nfmark); + if (skb->mark) { + tmp_uint = htonl(skb->mark); NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 4ab7b1416bb5..82e4454659bf 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -480,8 +480,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, #endif } - if (entskb->nfmark) { - tmp_uint = htonl(entskb->nfmark); + if (entskb->mark) { + tmp_uint = htonl(entskb->mark); NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint); } @@ -834,8 +834,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, } if (nfqa[NFQA_MARK-1]) - entry->skb->nfmark = ntohl(*(__be32 *) - NFA_DATA(nfqa[NFQA_MARK-1])); + entry->skb->mark = ntohl(*(__be32 *) + NFA_DATA(nfqa[NFQA_MARK-1])); issue_verdict(entry, verdict); instance_put(queue); diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index c01524f817f0..67ed53152999 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -42,7 +42,7 @@ target(struct sk_buff **pskb, { const struct xt_connmark_target_info *markinfo = targinfo; u_int32_t diff; - u_int32_t nfmark; + u_int32_t mark; u_int32_t newmark; u_int32_t ctinfo; u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); @@ -62,7 +62,7 @@ target(struct sk_buff **pskb, break; case XT_CONNMARK_SAVE: newmark = (*ctmark & ~markinfo->mask) | - ((*pskb)->nfmark & markinfo->mask); + ((*pskb)->mark & markinfo->mask); if (*ctmark != newmark) { *ctmark = newmark; #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) @@ -73,10 +73,10 @@ target(struct sk_buff **pskb, } break; case XT_CONNMARK_RESTORE: - nfmark = (*pskb)->nfmark; - diff = (*ctmark ^ nfmark) & markinfo->mask; + mark = (*pskb)->mark; + diff = (*ctmark ^ mark) & markinfo->mask; if (diff != 0) - (*pskb)->nfmark = nfmark ^ diff; + (*pskb)->mark = mark ^ diff; break; } } diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index c6e860a7114f..0b48547e8d64 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c @@ -31,8 +31,8 @@ target_v0(struct sk_buff **pskb, { const struct xt_mark_target_info *markinfo = targinfo; - if((*pskb)->nfmark != markinfo->mark) - (*pskb)->nfmark = markinfo->mark; + if((*pskb)->mark != markinfo->mark) + (*pskb)->mark = markinfo->mark; return XT_CONTINUE; } @@ -54,16 +54,16 @@ target_v1(struct sk_buff **pskb, break; case XT_MARK_AND: - mark = (*pskb)->nfmark & markinfo->mark; + mark = (*pskb)->mark & markinfo->mark; break; case XT_MARK_OR: - mark = (*pskb)->nfmark | markinfo->mark; + mark = (*pskb)->mark | markinfo->mark; break; } - if((*pskb)->nfmark != mark) - (*pskb)->nfmark = mark; + if((*pskb)->mark != mark) + (*pskb)->mark = mark; return XT_CONTINUE; } diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index 934dddfbcd23..dfa1ee6914c0 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c @@ -31,7 +31,7 @@ match(const struct sk_buff *skb, { const struct xt_mark_info *info = matchinfo; - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; + return ((skb->mark & info->mask) == info->mark) ^ info->invert; } static int diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8298ea9ffe19..b2437092978c 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -320,7 +320,7 @@ config CLS_U32_PERF config CLS_U32_MARK bool "Netfilter marks support" - depends on NET_CLS_U32 && NETFILTER + depends on NET_CLS_U32 ---help--- Say Y here to be able to use netfilter marks as u32 key. diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index e54acc6bcccd..f59a2c4aa039 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -101,11 +101,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, struct fw_head *head = (struct fw_head*)tp->root; struct fw_filter *f; int r; -#ifdef CONFIG_NETFILTER - u32 id = skb->nfmark & head->mask; -#else - u32 id = 0; -#endif + u32 id = skb->mark & head->mask; if (head != NULL) { for (f=head->ht[fw_hash(id)]; f; f=f->next) { diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 0a6cfa0005be..8b5194801995 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -143,7 +143,7 @@ next_knode: #endif #ifdef CONFIG_CLS_U32_MARK - if ((skb->nfmark & n->mark.mask) != n->mark.val) { + if ((skb->mark & n->mark.mask) != n->mark.val) { n = n->next; goto next_knode; } else { diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 61e3b740ab1a..d3ff3503326a 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -208,13 +208,9 @@ META_COLLECTOR(int_maclen) * Netfilter **************************************************************************/ -META_COLLECTOR(int_nfmark) +META_COLLECTOR(int_mark) { -#ifdef CONFIG_NETFILTER - dst->value = skb->nfmark; -#else - dst->value = 0; -#endif + dst->value = skb->mark; } /************************************************************************** @@ -490,7 +486,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { [META_ID(PKTLEN)] = META_FUNC(int_pktlen), [META_ID(DATALEN)] = META_FUNC(int_datalen), [META_ID(MACLEN)] = META_FUNC(int_maclen), - [META_ID(NFMARK)] = META_FUNC(int_nfmark), + [META_ID(NFMARK)] = META_FUNC(int_mark), [META_ID(TCINDEX)] = META_FUNC(int_tcindex), [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid), [META_ID(RTIIF)] = META_FUNC(int_rtiif), -- cgit v1.2.3-70-g09d2 From 47dcf0cb1005e86d0eea780f2984b2e7490f63cd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:20:38 -0800 Subject: [NET]: Rethink mark field in struct flowi Now that all protocols have been made aware of the mark field it can be moved out of the union thus simplyfing its usage. The config options in the IPv4/IPv6/DECnet subsystems to enable respectively disable mark based routing only obfuscate the code with ifdefs, the cost for the additional comparison in the flow key is insignificant, and most distributions have all these options enabled by default anyway. Therefore it makes sense to remove the config options and enable mark based routing by default. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/flow.h | 7 +------ include/net/ip_mp_alg.h | 4 +--- net/decnet/Kconfig | 8 -------- net/decnet/dn_route.c | 28 ++++++++-------------------- net/decnet/dn_rules.c | 12 +----------- net/ipv4/Kconfig | 7 ------- net/ipv4/fib_frontend.c | 4 ++-- net/ipv4/fib_rules.c | 12 +----------- net/ipv4/netfilter.c | 4 +--- net/ipv4/netfilter/iptable_mangle.c | 2 -- net/ipv4/route.c | 36 +++++++++--------------------------- net/ipv6/Kconfig | 7 ------- net/ipv6/fib6_rules.c | 12 +----------- net/ipv6/route.c | 4 +--- 14 files changed, 26 insertions(+), 121 deletions(-) (limited to 'net') diff --git a/include/net/flow.h b/include/net/flow.h index 270d4c1761af..ce4b10d8b412 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -13,12 +13,12 @@ struct flowi { int oif; int iif; + __u32 mark; union { struct { __be32 daddr; __be32 saddr; - __u32 fwmark; __u8 tos; __u8 scope; } ip4_u; @@ -26,28 +26,23 @@ struct flowi { struct { struct in6_addr daddr; struct in6_addr saddr; - __u32 fwmark; __be32 flowlabel; } ip6_u; struct { __le16 daddr; __le16 saddr; - __u32 fwmark; __u8 scope; } dn_u; } nl_u; #define fld_dst nl_u.dn_u.daddr #define fld_src nl_u.dn_u.saddr -#define fld_fwmark nl_u.dn_u.fwmark #define fld_scope nl_u.dn_u.scope #define fl6_dst nl_u.ip6_u.daddr #define fl6_src nl_u.ip6_u.saddr -#define fl6_fwmark nl_u.ip6_u.fwmark #define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl4_dst nl_u.ip4_u.daddr #define fl4_src nl_u.ip4_u.saddr -#define fl4_fwmark nl_u.ip4_u.fwmark #define fl4_tos nl_u.ip4_u.tos #define fl4_scope nl_u.ip4_u.scope diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h index beffdd66ad74..25b56571e54b 100644 --- a/include/net/ip_mp_alg.h +++ b/include/net/ip_mp_alg.h @@ -88,9 +88,7 @@ static inline int multipath_comparekeys(const struct flowi *flp1, return flp1->fl4_dst == flp2->fl4_dst && flp1->fl4_src == flp2->fl4_src && flp1->oif == flp2->oif && -#ifdef CONFIG_IP_ROUTE_FWMARK - flp1->fl4_fwmark == flp2->fl4_fwmark && -#endif + flp1->mark == flp2->mark && !((flp1->fl4_tos ^ flp2->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK)); } diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig index 36e72cb145b0..7914fd619c5c 100644 --- a/net/decnet/Kconfig +++ b/net/decnet/Kconfig @@ -41,11 +41,3 @@ config DECNET_ROUTER See for more information. -config DECNET_ROUTE_FWMARK - bool "DECnet: use FWMARK value as routing key (EXPERIMENTAL)" - depends on DECNET_ROUTER && NETFILTER - help - If you say Y here, you will be able to specify different routes for - packets with different FWMARK ("firewalling mark") values - (see ipchains(8), "-m" argument). - diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 3482839af280..f759d6f422ea 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -269,9 +269,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | -#ifdef CONFIG_DECNET_ROUTE_FWMARK - (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) | -#endif + (fl1->mark ^ fl2->mark) | (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | (fl1->oif ^ fl2->oif) | (fl1->iif ^ fl2->iif)) == 0; @@ -882,10 +880,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old { .daddr = oldflp->fld_dst, .saddr = oldflp->fld_src, .scope = RT_SCOPE_UNIVERSE, -#ifdef CONFIG_DECNET_ROUTE_FWMARK - .fwmark = oldflp->fld_fwmark -#endif } }, + .mark = oldflp->mark, .iif = loopback_dev.ifindex, .oif = oldflp->oif }; struct dn_route *rt = NULL; @@ -903,7 +899,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old "dn_route_output_slow: dst=%04x src=%04x mark=%d" " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst), dn_ntohs(oldflp->fld_src), - oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); + oldflp->mark, loopback_dev.ifindex, oldflp->oif); /* If we have an output interface, verify its a DECnet device */ if (oldflp->oif) { @@ -1108,9 +1104,7 @@ make_route: rt->fl.fld_dst = oldflp->fld_dst; rt->fl.oif = oldflp->oif; rt->fl.iif = 0; -#ifdef CONFIG_DECNET_ROUTE_FWMARK - rt->fl.fld_fwmark = oldflp->fld_fwmark; -#endif + rt->fl.mark = oldflp->mark; rt->rt_saddr = fl.fld_src; rt->rt_daddr = fl.fld_dst; @@ -1178,9 +1172,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl rt = rcu_dereference(rt->u.rt_next)) { if ((flp->fld_dst == rt->fl.fld_dst) && (flp->fld_src == rt->fl.fld_src) && -#ifdef CONFIG_DECNET_ROUTE_FWMARK - (flp->fld_fwmark == rt->fl.fld_fwmark) && -#endif + (flp->mark == rt->fl.mark) && (rt->fl.iif == 0) && (rt->fl.oif == flp->oif)) { rt->u.dst.lastuse = jiffies; @@ -1235,10 +1227,8 @@ static int dn_route_input_slow(struct sk_buff *skb) { .daddr = cb->dst, .saddr = cb->src, .scope = RT_SCOPE_UNIVERSE, -#ifdef CONFIG_DECNET_ROUTE_FWMARK - .fwmark = skb->mark -#endif } }, + .mark = skb->mark, .iif = skb->dev->ifindex }; struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; int err = -EINVAL; @@ -1385,7 +1375,7 @@ make_route: rt->fl.fld_dst = cb->dst; rt->fl.oif = 0; rt->fl.iif = in_dev->ifindex; - rt->fl.fld_fwmark = fl.fld_fwmark; + rt->fl.mark = fl.mark; rt->u.dst.flags = DST_HOST; rt->u.dst.neighbour = neigh; @@ -1457,9 +1447,7 @@ int dn_route_input(struct sk_buff *skb) if ((rt->fl.fld_src == cb->src) && (rt->fl.fld_dst == cb->dst) && (rt->fl.oif == 0) && -#ifdef CONFIG_DECNET_ROUTE_FWMARK - (rt->fl.fld_fwmark == skb->mark) && -#endif + (rt->fl.mark == skb->mark) && (rt->fl.iif == cb->iif)) { rt->u.dst.lastuse = jiffies; dst_hold(&rt->u.dst); diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 590e0a72495c..a09c09f5572d 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -45,10 +45,8 @@ struct dn_fib_rule __le16 dstmask; __le16 srcmap; u8 flags; -#ifdef CONFIG_DECNET_ROUTE_FWMARK u32 fwmark; u32 fwmask; -#endif }; static struct dn_fib_rule default_rule = { @@ -131,10 +129,8 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) ((daddr ^ r->dst) & r->dstmask)) return 0; -#ifdef CONFIG_DECNET_ROUTE_FWMARK - if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask) + if ((r->fwmark ^ fl->mark) & r->fwmask) return 0; -#endif return 1; } @@ -169,7 +165,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_DST]) r->dst = nla_get_u16(tb[FRA_DST]); -#ifdef CONFIG_DECNET_ROUTE_FWMARK if (tb[FRA_FWMARK]) { r->fwmark = nla_get_u32(tb[FRA_FWMARK]); if (r->fwmark) @@ -181,7 +176,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_FWMASK]) r->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif r->src_len = frh->src_len; r->srcmask = dnet_make_mask(r->src_len); @@ -203,13 +197,11 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->dst_len && (r->dst_len != frh->dst_len)) return 0; -#ifdef CONFIG_DECNET_ROUTE_FWMARK if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK]))) return 0; if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK]))) return 0; -#endif if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) return 0; @@ -248,12 +240,10 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = r->src_len; frh->tos = 0; -#ifdef CONFIG_DECNET_ROUTE_FWMARK if (r->fwmark) NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark); if (r->fwmask || r->fwmark) NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask); -#endif if (r->dst_len) NLA_PUT_U16(skb, FRA_DST, r->dst); if (r->src_len) diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 5572071af735..bc298bcc344e 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -104,13 +104,6 @@ config IP_MULTIPLE_TABLES If unsure, say N. -config IP_ROUTE_FWMARK - bool "IP: use netfilter MARK value as routing key" - depends on IP_MULTIPLE_TABLES && NETFILTER - help - If you say Y here, you will be able to specify different routes for - packets with different mark values (see iptables(8), MARK target). - config IP_ROUTE_MULTIPATH bool "IP: equal cost multipath" depends on IP_ADVANCED_ROUTER diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index af0190d8b6c0..ee8daaebcfaf 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -768,8 +768,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) { struct fib_result res; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, - .fwmark = frn->fl_fwmark, + struct flowi fl = { .mark = frn->fl_fwmark, + .nl_u = { .ip4_u = { .daddr = frn->fl_addr, .tos = frn->fl_tos, .scope = frn->fl_scope } } }; if (tb) { diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 0852b9cd065a..de8d5dd7099b 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -44,10 +44,8 @@ struct fib4_rule __be32 srcmask; __be32 dst; __be32 dstmask; -#ifdef CONFIG_IP_ROUTE_FWMARK u32 fwmark; u32 fwmask; -#endif #ifdef CONFIG_NET_CLS_ROUTE u32 tclassid; #endif @@ -160,10 +158,8 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) if (r->tos && (r->tos != fl->fl4_tos)) return 0; -#ifdef CONFIG_IP_ROUTE_FWMARK - if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask) + if ((r->fwmark ^ fl->mark) & r->fwmask) return 0; -#endif return 1; } @@ -220,7 +216,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_DST]) rule4->dst = nla_get_be32(tb[FRA_DST]); -#ifdef CONFIG_IP_ROUTE_FWMARK if (tb[FRA_FWMARK]) { rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); if (rule4->fwmark) @@ -232,7 +227,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_FWMASK]) rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif #ifdef CONFIG_NET_CLS_ROUTE if (tb[FRA_FLOW]) @@ -264,13 +258,11 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->tos && (rule4->tos != frh->tos)) return 0; -#ifdef CONFIG_IP_ROUTE_FWMARK if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) return 0; if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK]))) return 0; -#endif #ifdef CONFIG_NET_CLS_ROUTE if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW]))) @@ -296,13 +288,11 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = rule4->src_len; frh->tos = rule4->tos; -#ifdef CONFIG_IP_ROUTE_FWMARK if (rule4->fwmark) NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); if (rule4->fwmask || rule4->fwmark) NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask); -#endif if (rule4->dst_len) NLA_PUT_BE32(skb, FRA_DST, rule4->dst); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index bfc8d753a23a..e49441ac3571 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -27,9 +27,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) fl.nl_u.ip4_u.saddr = iph->saddr; fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; -#ifdef CONFIG_IP_ROUTE_FWMARK - fl.nl_u.ip4_u.fwmark = (*pskb)->mark; -#endif + fl.mark = (*pskb)->mark; if (ip_route_output_key(&rt, &fl) != 0) return -1; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 62d4ccc259ca..af2939889444 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -153,9 +153,7 @@ ipt_local_hook(unsigned int hook, if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr -#ifdef CONFIG_IP_ROUTE_FWMARK || (*pskb)->mark != mark -#endif || (*pskb)->nh.iph->tos != tos)) if (ip_route_me_harder(pskb, RTN_UNSPEC)) ret = NF_DROP; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4de3e38fa1a8..d7152b2b2c64 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -568,9 +568,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | -#ifdef CONFIG_IP_ROUTE_FWMARK - (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) | -#endif + (fl1->mark ^ fl2->mark) | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ *(u16 *)&fl2->nl_u.ip4_u.tos) | (fl1->oif ^ fl2->oif) | @@ -1643,9 +1641,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; rth->fl.fl4_tos = tos; -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->mark; -#endif + rth->fl.mark = skb->mark; rth->fl.fl4_src = saddr; rth->rt_src = saddr; #ifdef CONFIG_NET_CLS_ROUTE @@ -1789,9 +1785,7 @@ static inline int __mkroute_input(struct sk_buff *skb, rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; rth->fl.fl4_tos = tos; -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->mark; -#endif + rth->fl.mark = skb->mark; rth->fl.fl4_src = saddr; rth->rt_src = saddr; rth->rt_gateway = daddr; @@ -1920,10 +1914,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, .saddr = saddr, .tos = tos, .scope = RT_SCOPE_UNIVERSE, -#ifdef CONFIG_IP_ROUTE_FWMARK - .fwmark = skb->mark -#endif } }, + .mark = skb->mark, .iif = dev->ifindex }; unsigned flags = 0; u32 itag = 0; @@ -2034,9 +2026,7 @@ local_input: rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; rth->fl.fl4_tos = tos; -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->mark; -#endif + rth->fl.mark = skb->mark; rth->fl.fl4_src = saddr; rth->rt_src = saddr; #ifdef CONFIG_NET_CLS_ROUTE @@ -2113,9 +2103,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.fl4_src == saddr && rth->fl.iif == iif && rth->fl.oif == 0 && -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark == skb->mark && -#endif + rth->fl.mark == skb->mark && rth->fl.fl4_tos == tos) { rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); @@ -2239,9 +2227,7 @@ static inline int __mkroute_output(struct rtable **result, rth->fl.fl4_tos = tos; rth->fl.fl4_src = oldflp->fl4_src; rth->fl.oif = oldflp->oif; -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= oldflp->fl4_fwmark; -#endif + rth->fl.mark = oldflp->mark; rth->rt_dst = fl->fl4_dst; rth->rt_src = fl->fl4_src; rth->rt_iif = oldflp->oif ? : dev_out->ifindex; @@ -2385,10 +2371,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) .scope = ((tos & RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE), -#ifdef CONFIG_IP_ROUTE_FWMARK - .fwmark = oldflp->fl4_fwmark -#endif } }, + .mark = oldflp->mark, .iif = loopback_dev.ifindex, .oif = oldflp->oif }; struct fib_result res; @@ -2583,9 +2567,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) rth->fl.fl4_src == flp->fl4_src && rth->fl.iif == 0 && rth->fl.oif == flp->oif && -#ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark == flp->fl4_fwmark && -#endif + rth->fl.mark == flp->mark && !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK))) { diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 6e48f52e197c..deb4101a2a81 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -196,10 +196,3 @@ config IPV6_SUBTREES If unsure, say N. -config IPV6_ROUTE_FWMARK - bool "IPv6: use netfilter MARK value as routing key" - depends on IPV6_MULTIPLE_TABLES && NETFILTER - ---help--- - If you say Y here, you will be able to specify different routes for - packets with different mark values (see iptables(8), MARK target). - diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 1896ecb52899..89bea64eee1c 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -25,10 +25,8 @@ struct fib6_rule struct fib_rule common; struct rt6key src; struct rt6key dst; -#ifdef CONFIG_IPV6_ROUTE_FWMARK u32 fwmark; u32 fwmask; -#endif u8 tclass; }; @@ -130,10 +128,8 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) return 0; -#ifdef CONFIG_IPV6_ROUTE_FWMARK - if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask) + if ((r->fwmark ^ fl->mark) & r->fwmask) return 0; -#endif return 1; } @@ -177,7 +173,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, nla_memcpy(&rule6->dst.addr, tb[FRA_DST], sizeof(struct in6_addr)); -#ifdef CONFIG_IPV6_ROUTE_FWMARK if (tb[FRA_FWMARK]) { rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); if (rule6->fwmark) { @@ -192,7 +187,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_FWMASK]) rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif rule6->src.plen = frh->src_len; rule6->dst.plen = frh->dst_len; @@ -225,13 +219,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) return 0; -#ifdef CONFIG_IPV6_ROUTE_FWMARK if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) return 0; if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) return 0; -#endif return 1; } @@ -254,13 +246,11 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), &rule6->src.addr); -#ifdef CONFIG_IPV6_ROUTE_FWMARK if (rule6->fwmark) NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); if (rule6->fwmask || rule6->fwmark) NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); -#endif return 0; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aaabb1fad1cf..e3eab1529633 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -711,12 +711,10 @@ void ip6_route_input(struct sk_buff *skb) .ip6_u = { .daddr = iph->daddr, .saddr = iph->saddr, -#ifdef CONFIG_IPV6_ROUTE_FWMARK - .fwmark = skb->mark, -#endif .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, }, }, + .mark = skb->mark, .proto = iph->nexthdr, }; -- cgit v1.2.3-70-g09d2 From 5f300893fdd3b6e30a226c9a848eaa39b99a6431 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:21:41 -0800 Subject: [IPV4] nl_fib_lookup: Rename fl_fwmark to fl_mark For the sake of consistency. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/ip_fib.h | 2 +- net/ipv4/fib_frontend.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 949b932d2f08..36c635ca1aa6 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -115,7 +115,7 @@ struct fib_result { struct fib_result_nl { __be32 fl_addr; /* To be looked up*/ - u32 fl_fwmark; + u32 fl_mark; unsigned char fl_tos; unsigned char fl_scope; unsigned char tb_id_in; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index ee8daaebcfaf..14025345cc56 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -768,7 +768,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) { struct fib_result res; - struct flowi fl = { .mark = frn->fl_fwmark, + struct flowi fl = { .mark = frn->fl_mark, .nl_u = { .ip4_u = { .daddr = frn->fl_addr, .tos = frn->fl_tos, .scope = frn->fl_scope } } }; -- cgit v1.2.3-70-g09d2 From b8964ed9fa727109c9084abc807652ebfb681c18 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:22:18 -0800 Subject: [NET] rules: Protocol independant mark selector Move mark selector currently implemented per protocol into the protocol independant part. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/fib_rules.h | 2 +- include/net/fib_rules.h | 2 ++ net/core/fib_rules.c | 29 +++++++++++++++++++++++++++++ net/decnet/dn_rules.c | 27 --------------------------- net/ipv4/fib_rules.c | 29 ----------------------------- net/ipv6/fib6_rules.c | 32 -------------------------------- 6 files changed, 32 insertions(+), 89 deletions(-) (limited to 'net') diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index 4418c8d9d479..adcdfbdd14d5 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h @@ -34,7 +34,7 @@ enum FRA_UNUSED3, FRA_UNUSED4, FRA_UNUSED5, - FRA_FWMARK, /* netfilter mark */ + FRA_FWMARK, /* mark */ FRA_FLOW, /* flow/class id */ FRA_UNUSED6, FRA_UNUSED7, diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 8e2f473d3e82..68542b565cf7 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -13,6 +13,8 @@ struct fib_rule atomic_t refcnt; int ifindex; char ifname[IFNAMSIZ]; + u32 mark; + u32 mark_mask; u32 pref; u32 flags; u32 table; diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 6b0e63cacd93..da91bf2e6151 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -119,6 +119,9 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, if (rule->ifindex && (rule->ifindex != fl->iif)) continue; + if ((rule->mark ^ fl->mark) & rule->mark_mask) + continue; + if (!ops->match(rule, fl, flags)) continue; @@ -179,6 +182,18 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) rule->ifindex = dev->ifindex; } + if (tb[FRA_FWMARK]) { + rule->mark = nla_get_u32(tb[FRA_FWMARK]); + if (rule->mark) + /* compatibility: if the mark value is non-zero all bits + * are compared unless a mask is explicitly specified. + */ + rule->mark_mask = 0xFFFFFFFF; + } + + if (tb[FRA_FWMASK]) + rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]); + rule->action = frh->action; rule->flags = frh->flags; rule->table = frh_get_table(frh, tb); @@ -250,6 +265,14 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) nla_strcmp(tb[FRA_IFNAME], rule->ifname)) continue; + if (tb[FRA_FWMARK] && + (rule->mark != nla_get_u32(tb[FRA_FWMARK]))) + continue; + + if (tb[FRA_FWMASK] && + (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK]))) + continue; + if (!ops->compare(rule, frh, tb)) continue; @@ -298,6 +321,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, if (rule->pref) NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref); + if (rule->mark) + NLA_PUT_U32(skb, FRA_FWMARK, rule->mark); + + if (rule->mark_mask || rule->mark) + NLA_PUT_U32(skb, FRA_FWMASK, rule->mark_mask); + if (ops->fill(rule, skb, nlh, frh) < 0) goto nla_put_failure; diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index a09c09f5572d..1f5d23c96681 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -45,8 +45,6 @@ struct dn_fib_rule __le16 dstmask; __le16 srcmap; u8 flags; - u32 fwmark; - u32 fwmask; }; static struct dn_fib_rule default_rule = { @@ -129,9 +127,6 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) ((daddr ^ r->dst) & r->dstmask)) return 0; - if ((r->fwmark ^ fl->mark) & r->fwmask) - return 0; - return 1; } @@ -165,18 +160,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_DST]) r->dst = nla_get_u16(tb[FRA_DST]); - if (tb[FRA_FWMARK]) { - r->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (r->fwmark) - /* compatibility: if the mark value is non-zero all bits - * are compared unless a mask is explicitly specified. - */ - r->fwmask = 0xFFFFFFFF; - } - - if (tb[FRA_FWMASK]) - r->fwmask = nla_get_u32(tb[FRA_FWMASK]); - r->src_len = frh->src_len; r->srcmask = dnet_make_mask(r->src_len); r->dst_len = frh->dst_len; @@ -197,12 +180,6 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->dst_len && (r->dst_len != frh->dst_len)) return 0; - if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; - if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) return 0; @@ -240,10 +217,6 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = r->src_len; frh->tos = 0; - if (r->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark); - if (r->fwmask || r->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask); if (r->dst_len) NLA_PUT_U16(skb, FRA_DST, r->dst); if (r->src_len) diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index de8d5dd7099b..d2a190a35d65 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -44,8 +44,6 @@ struct fib4_rule __be32 srcmask; __be32 dst; __be32 dstmask; - u32 fwmark; - u32 fwmask; #ifdef CONFIG_NET_CLS_ROUTE u32 tclassid; #endif @@ -158,9 +156,6 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) if (r->tos && (r->tos != fl->fl4_tos)) return 0; - if ((r->fwmark ^ fl->mark) & r->fwmask) - return 0; - return 1; } @@ -216,18 +211,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, if (tb[FRA_DST]) rule4->dst = nla_get_be32(tb[FRA_DST]); - if (tb[FRA_FWMARK]) { - rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (rule4->fwmark) - /* compatibility: if the mark value is non-zero all bits - * are compared unless a mask is explicitly specified. - */ - rule4->fwmask = 0xFFFFFFFF; - } - - if (tb[FRA_FWMASK]) - rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]); - #ifdef CONFIG_NET_CLS_ROUTE if (tb[FRA_FLOW]) rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); @@ -258,12 +241,6 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->tos && (rule4->tos != frh->tos)) return 0; - if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; - #ifdef CONFIG_NET_CLS_ROUTE if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW]))) return 0; @@ -288,12 +265,6 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->src_len = rule4->src_len; frh->tos = rule4->tos; - if (rule4->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); - - if (rule4->fwmask || rule4->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask); - if (rule4->dst_len) NLA_PUT_BE32(skb, FRA_DST, rule4->dst); diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 89bea64eee1c..26374cbe2bc2 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -25,8 +25,6 @@ struct fib6_rule struct fib_rule common; struct rt6key src; struct rt6key dst; - u32 fwmark; - u32 fwmask; u8 tclass; }; @@ -128,9 +126,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) return 0; - if ((r->fwmark ^ fl->mark) & r->fwmask) - return 0; - return 1; } @@ -173,21 +168,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, nla_memcpy(&rule6->dst.addr, tb[FRA_DST], sizeof(struct in6_addr)); - if (tb[FRA_FWMARK]) { - rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (rule6->fwmark) { - /* - * if the mark value is non-zero, - * all bits are compared by default - * unless a mask is explicitly specified. - */ - rule6->fwmask = 0xFFFFFFFF; - } - } - - if (tb[FRA_FWMASK]) - rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); - rule6->src.plen = frh->src_len; rule6->dst.plen = frh->dst_len; rule6->tclass = frh->tos; @@ -219,12 +199,6 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) return 0; - if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; - return 1; } @@ -246,12 +220,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), &rule6->src.addr); - if (rule6->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); - - if (rule6->fwmask || rule6->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); - return 0; nla_put_failure: -- cgit v1.2.3-70-g09d2 From 1f6c9557e8206757c91b5737bb8dbd5b1ae3a773 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:22:48 -0800 Subject: [NET] rules: Share common attribute validation policy Move the attribute policy for the non-specific attributes into net/fib_rules.h and include it in the respective protocols. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/fib_rules.h | 7 +++++++ net/decnet/dn_rules.c | 6 +----- net/ipv4/fib_rules.c | 6 +----- net/ipv6/fib6_rules.c | 6 +----- 4 files changed, 10 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 68542b565cf7..e4ba781d289f 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -59,6 +59,13 @@ struct fib_rules_ops struct module *owner; }; +#define FRA_GENERIC_POLICY \ + [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \ + [FRA_PRIORITY] = { .type = NLA_U32 }, \ + [FRA_FWMARK] = { .type = NLA_U32 }, \ + [FRA_FWMASK] = { .type = NLA_U32 }, \ + [FRA_TABLE] = { .type = NLA_U32 } + static inline void fib_rule_get(struct fib_rule *rule) { atomic_inc(&rule->refcnt); diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 1f5d23c96681..e32d0c3d5a96 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -108,13 +108,9 @@ errout: } static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, + FRA_GENERIC_POLICY, [FRA_SRC] = { .type = NLA_U16 }, [FRA_DST] = { .type = NLA_U16 }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, }; static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index d2a190a35d65..fd4a8cd4c06e 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -170,14 +170,10 @@ static struct fib_table *fib_empty_table(void) } static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, + FRA_GENERIC_POLICY, [FRA_SRC] = { .type = NLA_U32 }, [FRA_DST] = { .type = NLA_U32 }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, [FRA_FLOW] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, }; static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 26374cbe2bc2..8377477b2c19 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -130,13 +130,9 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) } static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, + FRA_GENERIC_POLICY, [FRA_SRC] = { .len = sizeof(struct in6_addr) }, [FRA_DST] = { .len = sizeof(struct in6_addr) }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, }; static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, -- cgit v1.2.3-70-g09d2 From 3dfbcc411e461db51a1ac1aa1c6ebe2c5a0275a0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:23:20 -0800 Subject: [NET] rules: Add support to invert selectors Introduces a new flag FIB_RULE_INVERT causing rules to apply if the specified selector doesn't match. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/fib_rules.h | 1 + net/core/fib_rules.c | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index adcdfbdd14d5..8270aac2aa5d 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h @@ -6,6 +6,7 @@ /* rule is permanent, and cannot be deleted */ #define FIB_RULE_PERMANENT 1 +#define FIB_RULE_INVERT 2 struct fib_rule_hdr { diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index da91bf2e6151..4148e274a204 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -107,6 +107,22 @@ out: EXPORT_SYMBOL_GPL(fib_rules_unregister); +static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, + struct flowi *fl, int flags) +{ + int ret = 0; + + if (rule->ifindex && (rule->ifindex != fl->iif)) + goto out; + + if ((rule->mark ^ fl->mark) & rule->mark_mask) + goto out; + + ret = ops->match(rule, fl, flags); +out: + return (rule->flags & FIB_RULE_INVERT) ? !ret : ret; +} + int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, int flags, struct fib_lookup_arg *arg) { @@ -116,13 +132,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, rcu_read_lock(); list_for_each_entry_rcu(rule, ops->rules_list, list) { - if (rule->ifindex && (rule->ifindex != fl->iif)) - continue; - - if ((rule->mark ^ fl->mark) & rule->mark_mask) - continue; - - if (!ops->match(rule, fl, flags)) + if (!fib_rule_match(rule, ops, fl, flags)) continue; err = ops->action(rule, fl, flags, arg); -- cgit v1.2.3-70-g09d2 From 3c62f75aac7348ee262b1295cfcfeb3473f76815 Mon Sep 17 00:00:00 2001 From: David Kimdon Date: Thu, 9 Nov 2006 16:16:21 -0800 Subject: [PKT_SCHED]: Make sch_fifo.o available when CONFIG_NET_SCHED is not set. Based on patch by Patrick McHardy. Add a new option, NET_SCH_FIFO, which provides a simple fifo qdisc without requiring CONFIG_NET_SCHED. The d80211 stack needs a generic fifo qdisc for WME. At present it uses net/d80211/fifo_qdisc.c which is functionally equivalent to sch_fifo.c. This patch will allow the d80211 stack to remove net/d80211/fifo_qdisc.c and use sch_fifo.c instead. Signed-off-by: David Kimdon Signed-off-by: David S. Miller --- net/sched/Kconfig | 4 ++++ net/sched/Makefile | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sched/Kconfig b/net/sched/Kconfig index b2437092978c..f4544dd86476 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -6,6 +6,7 @@ menu "QoS and/or fair queueing" config NET_SCHED bool "QoS and/or fair queueing" + select NET_SCH_FIFO ---help--- When the kernel has several packets to send out over a network device, it has to decide which ones to send first, which ones to @@ -40,6 +41,9 @@ config NET_SCHED The available schedulers are listed in the following questions; you can say Y to as many as you like. If unsure, say N now. +config NET_SCH_FIFO + bool + if NET_SCHED choice diff --git a/net/sched/Makefile b/net/sched/Makefile index 0f06aec66094..ff2d6e5e282c 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -4,7 +4,7 @@ obj-y := sch_generic.o -obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o +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 @@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o +obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o -- cgit v1.2.3-70-g09d2 From 72a3effaf633bcae9034b7e176bdbd78d64a71db Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 16 Nov 2006 02:30:37 -0800 Subject: [NET]: Size listen hash tables using backlog hint We currently allocate a fixed size (TCP_SYNQ_HSIZE=512) slots hash table for each LISTEN socket, regardless of various parameters (listen backlog for example) On x86_64, this means order-1 allocations (might fail), even for 'small' sockets, expecting few connections. On the contrary, a huge server wanting a backlog of 50000 is slowed down a bit because of this fixed limit. This patch makes the sizing of listen hash table a dynamic parameter, depending of : - net.core.somaxconn tunable (default is 128) - net.ipv4.tcp_max_syn_backlog tunable (default : 256, 1024 or 128) - backlog value given by user application (2nd parameter of listen()) For large allocations (bigger than PAGE_SIZE), we use vmalloc() instead of kmalloc(). We still limit memory allocation with the two existing tunables (somaxconn & tcp_max_syn_backlog). So for standard setups, this patch actually reduce RAM usage. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/request_sock.h | 8 ++++---- include/net/tcp.h | 1 - net/core/request_sock.c | 35 +++++++++++++++++++++++++---------- net/dccp/ipv4.c | 2 +- net/dccp/proto.c | 6 +++--- net/ipv4/af_inet.c | 2 +- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/tcp_ipv4.c | 6 +++--- net/ipv6/tcp_ipv6.c | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-) (limited to 'net') diff --git a/include/net/request_sock.h b/include/net/request_sock.h index f743a941a4f2..b5b023e79e5f 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -28,8 +28,8 @@ struct proto; struct request_sock_ops { int family; - kmem_cache_t *slab; int obj_size; + kmem_cache_t *slab; int (*rtx_syn_ack)(struct sock *sk, struct request_sock *req, struct dst_entry *dst); @@ -51,13 +51,13 @@ struct request_sock { u32 rcv_wnd; /* rcv_wnd offered first time */ u32 ts_recent; unsigned long expires; - struct request_sock_ops *rsk_ops; + const struct request_sock_ops *rsk_ops; struct sock *sk; u32 secid; u32 peer_secid; }; -static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) +static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops) { struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC); @@ -121,7 +121,7 @@ struct request_sock_queue { }; extern int reqsk_queue_alloc(struct request_sock_queue *queue, - const int nr_table_entries); + unsigned int nr_table_entries); static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue) { diff --git a/include/net/tcp.h b/include/net/tcp.h index 7a093d0aa0fe..246916c2321e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -138,7 +138,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define MAX_TCP_SYNCNT 127 #define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */ -#define TCP_SYNQ_HSIZE 512 /* Size of SYNACK hash table */ #define TCP_PAWS_24DAYS (60 * 60 * 24 * 24) #define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 79ebd75fbe4d..5f0818d815e6 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -29,22 +30,31 @@ * it is absolutely not enough even at 100conn/sec. 256 cures most * of problems. This value is adjusted to 128 for very small machines * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb). - * Further increasing requires to change hash table size. + * Note : Dont forget somaxconn that may limit backlog too. */ int sysctl_max_syn_backlog = 256; int reqsk_queue_alloc(struct request_sock_queue *queue, - const int nr_table_entries) + unsigned int nr_table_entries) { - const int lopt_size = sizeof(struct listen_sock) + - nr_table_entries * sizeof(struct request_sock *); - struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL); - + size_t lopt_size = sizeof(struct listen_sock); + struct listen_sock *lopt; + + nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); + nr_table_entries = max_t(u32, nr_table_entries, 8); + nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); + lopt_size += nr_table_entries * sizeof(struct request_sock *); + if (lopt_size > PAGE_SIZE) + lopt = __vmalloc(lopt_size, + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, + PAGE_KERNEL); + else + lopt = kzalloc(lopt_size, GFP_KERNEL); if (lopt == NULL) return -ENOMEM; - for (lopt->max_qlen_log = 6; - (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; + for (lopt->max_qlen_log = 3; + (1 << lopt->max_qlen_log) < nr_table_entries; lopt->max_qlen_log++); get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); @@ -65,9 +75,11 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) { /* make all the listen_opt local to us */ struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); + size_t lopt_size = sizeof(struct listen_sock) + + lopt->nr_table_entries * sizeof(struct request_sock *); if (lopt->qlen != 0) { - int i; + unsigned int i; for (i = 0; i < lopt->nr_table_entries; i++) { struct request_sock *req; @@ -81,7 +93,10 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) } BUG_TRAP(lopt->qlen == 0); - kfree(lopt); + if (lopt_size > PAGE_SIZE) + vfree(lopt); + else + kfree(lopt); } EXPORT_SYMBOL(reqsk_queue_destroy); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index e08e7688a263..0a5d68dbb418 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1022,7 +1022,7 @@ static void dccp_v4_reqsk_destructor(struct request_sock *req) kfree(inet_rsk(req)->opt); } -static struct request_sock_ops dccp_request_sock_ops = { +static struct request_sock_ops dccp_request_sock_ops _read_mostly = { .family = PF_INET, .obj_size = sizeof(struct dccp_request_sock), .rtx_syn_ack = dccp_v4_send_response, diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 72cbdcfc2c65..047d170a363a 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -262,12 +262,12 @@ int dccp_destroy_sock(struct sock *sk) EXPORT_SYMBOL_GPL(dccp_destroy_sock); -static inline int dccp_listen_start(struct sock *sk) +static inline int dccp_listen_start(struct sock *sk, int backlog) { struct dccp_sock *dp = dccp_sk(sk); dp->dccps_role = DCCP_ROLE_LISTEN; - return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); + return inet_csk_listen_start(sk, backlog); } int dccp_disconnect(struct sock *sk, int flags) @@ -788,7 +788,7 @@ int inet_dccp_listen(struct socket *sock, int backlog) * FIXME: here it probably should be sk->sk_prot->listen_start * see tcp_listen_start */ - err = dccp_listen_start(sk); + err = dccp_listen_start(sk, backlog); if (err) goto out; } diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index edcf0932ac6d..4a81d54a7569 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -204,7 +204,7 @@ int inet_listen(struct socket *sock, int backlog) * we can only allow the backlog to be adjusted. */ if (old_state != TCP_LISTEN) { - err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); + err = inet_csk_listen_start(sk, backlog); if (err) goto out; } diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 96bbe2a0aa1b..9d68837888d3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -343,7 +343,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, EXPORT_SYMBOL_GPL(inet_csk_route_req); static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, - const u32 rnd, const u16 synq_hsize) + const u32 rnd, const u32 synq_hsize) { return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 22ef8bd26620..5fbf96552cac 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -715,7 +715,7 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, return dopt; } -struct request_sock_ops tcp_request_sock_ops = { +struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), .rtx_syn_ack = tcp_v4_send_synack, @@ -1385,7 +1385,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) if (st->state == TCP_SEQ_STATE_OPENREQ) { struct request_sock *req = cur; - icsk = inet_csk(st->syn_wait_sk); + icsk = inet_csk(st->syn_wait_sk); req = req->dl_next; while (1) { while (req) { @@ -1395,7 +1395,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) } req = req->dl_next; } - if (++st->sbucket >= TCP_SYNQ_HSIZE) + if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries) break; get_req: req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index eb6d145ecfd7..1a3c46c139f8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -526,7 +526,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static struct request_sock_ops tcp6_request_sock_ops = { +static struct request_sock_ops tcp6_request_sock_ops _read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), .rtx_syn_ack = tcp_v6_send_synack, -- cgit v1.2.3-70-g09d2 From 494b4e7d819246bad67c40897b9eeaf0ce18d5ff Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Nov 2006 16:23:22 -0800 Subject: [DCCP]: Fix typo _read_mostly --> __read_mostly. Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 0a5d68dbb418..de64e6c7f93d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1022,7 +1022,7 @@ static void dccp_v4_reqsk_destructor(struct request_sock *req) kfree(inet_rsk(req)->opt); } -static struct request_sock_ops dccp_request_sock_ops _read_mostly = { +static struct request_sock_ops dccp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct dccp_request_sock), .rtx_syn_ack = dccp_v4_send_response, -- cgit v1.2.3-70-g09d2 From 9ec75fe85c58471db958386c1604e5006a2e2f69 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Nov 2006 16:26:09 -0800 Subject: [IPV6] tcp: Fix typo _read_mostly --> __read_mostly. Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1a3c46c139f8..06b536b47f97 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -526,7 +526,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static struct request_sock_ops tcp6_request_sock_ops _read_mostly = { +static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), .rtx_syn_ack = tcp_v6_send_synack, -- cgit v1.2.3-70-g09d2 From b68dbcab1dc70938fa5516d0ee82c0bf94e9a768 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 9 Nov 2006 16:29:57 -0800 Subject: [SCTP]: Fix warning An alternate solution would be to make the digest a pointer, allocate it in sctp_endpoint_init() and free it in sctp_endpoint_destroy(). I guess I should have originally done it this way... CC [M] net/sctp/sm_make_chunk.o net/sctp/sm_make_chunk.c: In function 'sctp_unpack_cookie': net/sctp/sm_make_chunk.c:1358: warning: initialization discards qualifiers from pointer target type The reason is that sctp_unpack_cookie() takes a const struct sctp_endpoint and modifies the digest in it (digest being embedded in the struct, not a pointer). Make digest a pointer to fix this warning. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/endpointola.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c6d93bb0dcd2..5596f5d97ed2 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1270,7 +1270,7 @@ struct sctp_endpoint { * this here so we pre-allocate this once and can re-use * on every receive. */ - __u8 digest[SCTP_SIGNATURE_SIZE]; + __u8 *digest; /* sendbuf acct. policy. */ __u32 sndbuf_policy; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 9b6b394b66f6..090f2b2a0cab 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -72,6 +72,10 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, { memset(ep, 0, sizeof(struct sctp_endpoint)); + ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); + if (!ep->digest) + return NULL; + /* Initialize the base structure. */ /* What type of endpoint are we? */ ep->base.type = SCTP_EP_TYPE_SOCKET; @@ -182,6 +186,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) /* Free up the HMAC transform. */ crypto_free_hash(sctp_sk(ep->base.sk)->hmac); + /* Free the digest buffer */ + kfree(ep->digest); + /* Cleanup. */ sctp_inq_free(&ep->base.inqueue); sctp_bind_addr_free(&ep->base.bind_addr); -- cgit v1.2.3-70-g09d2 From 3ff825b28d3345ef381eceae22bf9d92231f23dc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 9 Nov 2006 16:32:06 -0800 Subject: [TCP]: Add tcp_available_congestion_control sysctl. Create /proc/sys/net/ipv4/tcp_available_congestion_control that reflects currently available TCP choices. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/sysctl.h | 1 + include/net/tcp.h | 4 ++++ net/ipv4/sysctl_net_ipv4.c | 24 ++++++++++++++++++++++++ net/ipv4/tcp_cong.c | 16 ++++++++++++++++ 5 files changed, 51 insertions(+) (limited to 'net') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index fd3c0c012351..db4280856588 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -351,10 +351,16 @@ tcp_frto - BOOLEAN where packet loss is typically due to random radio interference rather than intermediate router congestion. +tcp_available_congestion_control - STRING + Shows the available congestion control choices that are registered. + More congestion control algorithms may be available as modules, + but not loaded. + tcp_congestion_control - STRING Set the congestion control algorithm to be used for new connections. The algorithm "reno" is always available, but additional choices may be available based on kernel configuration. + Default is set as part of kernel configuration. somaxconn - INTEGER Limit of socket listen() backlog, known in userspace as SOMAXCONN. diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index d98562f1df76..28a48279654d 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -426,6 +426,7 @@ enum NET_CIPSOV4_CACHE_BUCKET_SIZE=119, NET_CIPSOV4_RBM_OPTFMT=120, NET_CIPSOV4_RBM_STRICTVALID=121, + NET_TCP_AVAIL_CONG_CONTROL=122, }; enum { diff --git a/include/net/tcp.h b/include/net/tcp.h index 246916c2321e..6af4baf5b769 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -620,6 +620,9 @@ enum tcp_ca_event { * Interface for adding new TCP congestion control handlers */ #define TCP_CA_NAME_MAX 16 +#define TCP_CA_MAX 128 +#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX) + struct tcp_congestion_ops { struct list_head list; @@ -659,6 +662,7 @@ extern void tcp_init_congestion_control(struct sock *sk); extern void tcp_cleanup_congestion_control(struct sock *sk); extern int tcp_set_default_congestion_control(const char *name); extern void tcp_get_default_congestion_control(char *name); +extern void tcp_get_available_congestion_control(char *buf, size_t len); extern int tcp_set_congestion_control(struct sock *sk, const char *name); extern void tcp_slow_start(struct tcp_sock *tp); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 15061b314411..2e770f45d829 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -129,6 +129,23 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, return ret; } +static int proc_tcp_available_congestion_control(ctl_table *ctl, + int write, struct file * filp, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, }; + int ret; + + tbl.data = kmalloc(tbl.maxlen, GFP_USER); + if (!tbl.data) + return -ENOMEM; + tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX); + ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos); + kfree(tbl.data); + return ret; +} + ctl_table ipv4_table[] = { { .ctl_name = NET_IPV4_TCP_TIMESTAMPS, @@ -731,6 +748,13 @@ ctl_table ipv4_table[] = { .proc_handler = &proc_dointvec, }, #endif /* CONFIG_NETLABEL */ + { + .ctl_name = NET_TCP_AVAIL_CONG_CONTROL, + .procname = "tcp_available_congestion_control", + .maxlen = TCP_CA_BUF_MAX, + .mode = 0444, + .proc_handler = &proc_tcp_available_congestion_control, + }, { .ctl_name = 0 } }; diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 1e2982f4acd4..d846d7b95e1f 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -139,6 +139,22 @@ static int __init tcp_congestion_default(void) late_initcall(tcp_congestion_default); +/* Build string with list of available congestion control values */ +void tcp_get_available_congestion_control(char *buf, size_t maxlen) +{ + struct tcp_congestion_ops *ca; + size_t offs = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(ca, &tcp_cong_list, list) { + offs += snprintf(buf + offs, maxlen - offs, + "%s%s", + offs == 0 ? "" : " ", ca->name); + + } + rcu_read_unlock(); +} + /* Get current default congestion control */ void tcp_get_default_congestion_control(char *name) { -- cgit v1.2.3-70-g09d2 From ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 9 Nov 2006 16:35:15 -0800 Subject: [TCP]: Restrict congestion control choices. Allow normal users to only choose among a restricted set of congestion control choices. The default is reno and what ever has been configured as default. But the policy can be changed by administrator at any time. For example, to allow any choice: cp /proc/sys/net/ipv4/tcp_available_congestion_control \ /proc/sys/net/ipv4/tcp_allowed_congestion_control Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++ include/linux/sysctl.h | 1 + include/net/tcp.h | 3 ++ net/ipv4/sysctl_net_ipv4.c | 52 ++++++++++++++++++++++++++++ net/ipv4/tcp_cong.c | 63 ++++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+) (limited to 'net') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index db4280856588..bbcc8deda172 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -351,6 +351,12 @@ tcp_frto - BOOLEAN where packet loss is typically due to random radio interference rather than intermediate router congestion. +tcp_allowed_congestion_control - STRING + Show/set the congestion control choices available to non-privileged + processes. The list is a subset of those listed in + tcp_available_congestion_control. + Default is "reno" and the default setting (tcp_congestion_control). + tcp_available_congestion_control - STRING Shows the available congestion control choices that are registered. More congestion control algorithms may be available as modules, diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 28a48279654d..0725441621d0 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -427,6 +427,7 @@ enum NET_CIPSOV4_RBM_OPTFMT=120, NET_CIPSOV4_RBM_STRICTVALID=121, NET_TCP_AVAIL_CONG_CONTROL=122, + NET_TCP_ALLOWED_CONG_CONTROL=123, }; enum { diff --git a/include/net/tcp.h b/include/net/tcp.h index 6af4baf5b769..e1a5d29d0a1f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -625,6 +625,7 @@ enum tcp_ca_event { struct tcp_congestion_ops { struct list_head list; + int non_restricted; /* initialize private data (optional) */ void (*init)(struct sock *sk); @@ -663,6 +664,8 @@ extern void tcp_cleanup_congestion_control(struct sock *sk); extern int tcp_set_default_congestion_control(const char *name); extern void tcp_get_default_congestion_control(char *name); extern void tcp_get_available_congestion_control(char *buf, size_t len); +extern void tcp_get_allowed_congestion_control(char *buf, size_t len); +extern int tcp_set_allowed_congestion_control(char *allowed); extern int tcp_set_congestion_control(struct sock *sk, const char *name); extern void tcp_slow_start(struct tcp_sock *tp); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 2e770f45d829..dfcf47f10f88 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -146,6 +146,50 @@ static int proc_tcp_available_congestion_control(ctl_table *ctl, return ret; } +static int proc_allowed_congestion_control(ctl_table *ctl, + int write, struct file * filp, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX }; + int ret; + + tbl.data = kmalloc(tbl.maxlen, GFP_USER); + if (!tbl.data) + return -ENOMEM; + + tcp_get_allowed_congestion_control(tbl.data, tbl.maxlen); + ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos); + if (write && ret == 0) + ret = tcp_set_allowed_congestion_control(tbl.data); + kfree(tbl.data); + return ret; +} + +static int strategy_allowed_congestion_control(ctl_table *table, int __user *name, + int nlen, void __user *oldval, + size_t __user *oldlenp, + void __user *newval, size_t newlen, + void **context) +{ + ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX }; + int ret; + + tbl.data = kmalloc(tbl.maxlen, GFP_USER); + if (!tbl.data) + return -ENOMEM; + + tcp_get_available_congestion_control(tbl.data, tbl.maxlen); + ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen, + context); + if (ret == 0 && newval && newlen) + ret = tcp_set_allowed_congestion_control(tbl.data); + kfree(tbl.data); + + return ret; + +} + ctl_table ipv4_table[] = { { .ctl_name = NET_IPV4_TCP_TIMESTAMPS, @@ -755,6 +799,14 @@ ctl_table ipv4_table[] = { .mode = 0444, .proc_handler = &proc_tcp_available_congestion_control, }, + { + .ctl_name = NET_TCP_ALLOWED_CONG_CONTROL, + .procname = "tcp_allowed_congestion_control", + .maxlen = TCP_CA_BUF_MAX, + .mode = 0644, + .proc_handler = &proc_allowed_congestion_control, + .strategy = &strategy_allowed_congestion_control, + }, { .ctl_name = 0 } }; diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index d846d7b95e1f..343d6197c92e 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -123,6 +123,7 @@ int tcp_set_default_congestion_control(const char *name) #endif if (ca) { + ca->non_restricted = 1; /* default is always allowed */ list_move(&ca->list, &tcp_cong_list); ret = 0; } @@ -168,6 +169,64 @@ void tcp_get_default_congestion_control(char *name) rcu_read_unlock(); } +/* Built list of non-restricted congestion control values */ +void tcp_get_allowed_congestion_control(char *buf, size_t maxlen) +{ + struct tcp_congestion_ops *ca; + size_t offs = 0; + + *buf = '\0'; + rcu_read_lock(); + list_for_each_entry_rcu(ca, &tcp_cong_list, list) { + if (!ca->non_restricted) + continue; + offs += snprintf(buf + offs, maxlen - offs, + "%s%s", + offs == 0 ? "" : " ", ca->name); + + } + rcu_read_unlock(); +} + +/* Change list of non-restricted congestion control */ +int tcp_set_allowed_congestion_control(char *val) +{ + struct tcp_congestion_ops *ca; + char *clone, *name; + int ret = 0; + + clone = kstrdup(val, GFP_USER); + if (!clone) + return -ENOMEM; + + spin_lock(&tcp_cong_list_lock); + /* pass 1 check for bad entries */ + while ((name = strsep(&clone, " ")) && *name) { + ca = tcp_ca_find(name); + if (!ca) { + ret = -ENOENT; + goto out; + } + } + + /* pass 2 clear */ + list_for_each_entry_rcu(ca, &tcp_cong_list, list) + ca->non_restricted = 0; + + /* pass 3 mark as allowed */ + while ((name = strsep(&val, " ")) && *name) { + ca = tcp_ca_find(name); + WARN_ON(!ca); + if (ca) + ca->non_restricted = 1; + } +out: + spin_unlock(&tcp_cong_list_lock); + + return ret; +} + + /* Change congestion control for socket */ int tcp_set_congestion_control(struct sock *sk, const char *name) { @@ -183,6 +242,9 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) if (!ca) err = -ENOENT; + else if (!(ca->non_restricted || capable(CAP_NET_ADMIN))) + err = -EPERM; + else if (!try_module_get(ca->owner)) err = -EBUSY; @@ -284,6 +346,7 @@ EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd); struct tcp_congestion_ops tcp_reno = { .name = "reno", + .non_restricted = 1, .owner = THIS_MODULE, .ssthresh = tcp_reno_ssthresh, .cong_avoid = tcp_reno_cong_avoid, -- cgit v1.2.3-70-g09d2 From 35bfbc94070e480f350c868abc4ff9f77e7f2051 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 9 Nov 2006 16:36:36 -0800 Subject: [TCP]: Allow autoloading of congestion control via setsockopt. If user has permision to load modules, then autoload then attempt autoload of TCP congestion module. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv4/tcp_cong.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 343d6197c92e..5ca7723d0798 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -113,7 +113,7 @@ int tcp_set_default_congestion_control(const char *name) spin_lock(&tcp_cong_list_lock); ca = tcp_ca_find(name); #ifdef CONFIG_KMOD - if (!ca) { + if (!ca && capable(CAP_SYS_MODULE)) { spin_unlock(&tcp_cong_list_lock); request_module("tcp_%s", name); @@ -236,9 +236,19 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) rcu_read_lock(); ca = tcp_ca_find(name); + /* no change asking for existing value */ if (ca == icsk->icsk_ca_ops) goto out; +#ifdef CONFIG_KMOD + /* not found attempt to autoload module */ + if (!ca && capable(CAP_SYS_MODULE)) { + rcu_read_unlock(); + request_module("tcp_%s", name); + rcu_read_lock(); + ca = tcp_ca_find(name); + } +#endif if (!ca) err = -ENOENT; -- cgit v1.2.3-70-g09d2 From 931731123a103cfb3f70ac4b7abfc71d94ba1f03 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Nov 2006 19:58:25 -0800 Subject: [TCP]: Don't set SKB owner in tcp_transmit_skb(). The data itself is already charged to the SKB, doing the skb_set_owner_w() just generates a lot of noise and extra atomics we don't really need. Lmbench improvements on lat_tcp are minimal: before: TCP latency using localhost: 23.2701 microseconds TCP latency using localhost: 23.1994 microseconds TCP latency using localhost: 23.2257 microseconds after: TCP latency using localhost: 22.8380 microseconds TCP latency using localhost: 22.9465 microseconds TCP latency using localhost: 22.8462 microseconds Signed-off-by: David S. Miller --- include/net/inet6_connection_sock.h | 2 +- include/net/inet_connection_sock.h | 3 ++- include/net/ip.h | 2 +- net/dccp/output.c | 4 ++-- net/ipv4/ip_output.c | 3 +-- net/ipv4/tcp_output.c | 3 +-- net/ipv6/inet6_connection_sock.c | 3 +-- net/sctp/protocol.c | 2 +- 8 files changed, 10 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index f13ddc2543b1..16aa96a6a53b 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -38,5 +38,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok); +extern int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 0bcf9f237e1f..fd3f1d8cdc4a 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -36,7 +36,8 @@ struct tcp_congestion_ops; * (i.e. things that depend on the address family) */ struct inet_connection_sock_af_ops { - int (*queue_xmit)(struct sk_buff *skb, int ipfragok); + int (*queue_xmit)(struct sk_buff *skb, struct sock *sk, + int ipfragok); void (*send_check)(struct sock *sk, int len, struct sk_buff *skb); int (*rebuild_header)(struct sock *sk); diff --git a/include/net/ip.h b/include/net/ip.h index b6d95e553401..949fa8683626 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -97,7 +97,7 @@ extern int ip_mc_output(struct sk_buff *skb); extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); extern int ip_do_nat(struct sk_buff *skb); extern void ip_send_check(struct iphdr *ip); -extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); +extern int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok); extern void ip_init(void); extern int ip_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, diff --git a/net/dccp/output.c b/net/dccp/output.c index 7102e3aed4ca..2cc4f4b2a9dd 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -125,7 +125,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) DCCP_INC_STATS(DCCP_MIB_OUTSEGS); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - err = icsk->icsk_af_ops->queue_xmit(skb, 0); + err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0); if (err <= 0) return err; @@ -426,7 +426,7 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) code); if (skb != NULL) { memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0); + err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0); if (err == NET_XMIT_CN) err = 0; } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 23633bf042ba..def32d8d3b06 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -288,9 +288,8 @@ int ip_output(struct sk_buff *skb) !(IPCB(skb)->flags & IPSKB_REROUTED)); } -int ip_queue_xmit(struct sk_buff *skb, int ipfragok) +int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok) { - struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ip_options *opt = inet->opt; struct rtable *rt; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ca406157724c..f63e99aac2d5 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -426,7 +426,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, th = (struct tcphdr *) skb_push(skb, tcp_header_size); skb->h.th = th; - skb_set_owner_w(skb, sk); /* Build TCP header and checksum it. */ th->source = inet->sport; @@ -479,7 +478,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) TCP_INC_STATS(TCP_MIB_OUTSEGS); - err = icsk->icsk_af_ops->queue_xmit(skb, 0); + err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0); if (likely(err <= 0)) return err; diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index e48fb4c53c4f..c598962eaa40 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -139,9 +139,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); -int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) +int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok) { - struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct flowi fl; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5b4f82fd98f8..c107d45f6e65 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -808,7 +808,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, NIPQUAD(((struct rtable *)skb->dst)->rt_dst)); SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); - return ip_queue_xmit(skb, ipfragok); + return ip_queue_xmit(skb, skb->sk, ipfragok); } static struct sctp_af sctp_ipv4_specific; -- cgit v1.2.3-70-g09d2 From 60361be1be7854cbffb6dc268d1bc094da33431c Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 02:13:56 -0200 Subject: [DCCP]: set safe upper bound for option length This is a re-send from http://www.mail-archive.com/dccp@vger.kernel.org/msg00553.html It is the same patch as before, but I have built in Arnaldo's suggestions pointed out in that posting. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/dccp.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 272e8584564e..9f00dd807e04 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -40,12 +40,18 @@ extern void dccp_tw_deschedule(struct inet_timewait_sock *tw); extern void dccp_time_wait(struct sock *sk, int state, int timeo); -/* FIXME: Right size this */ -#define DCCP_MAX_OPT_LEN 128 - -#define DCCP_MAX_PACKET_HDR 32 - -#define MAX_DCCP_HEADER (DCCP_MAX_PACKET_HDR + DCCP_MAX_OPT_LEN + MAX_HEADER) +/* + * Set safe upper bounds for header and option length. Since Data Offset is 8 + * bits (RFC 4340, sec. 5.1), the total header length can never be more than + * 4 * 255 = 1020 bytes. The largest possible header length is 28 bytes (X=1): + * - DCCP-Response with ACK Subheader and 4 bytes of Service code OR + * - DCCP-Reset with ACK Subheader and 4 bytes of Reset Code fields + * Hence a safe upper bound for the maximum option length is 1020-28 = 992 + */ +#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(int)) +#define DCCP_MAX_PACKET_HDR 28 +#define DCCP_MAX_OPT_LEN (MAX_DCCP_SPECIFIC_HEADER - DCCP_MAX_PACKET_HDR) +#define MAX_DCCP_HEADER (MAX_DCCP_SPECIFIC_HEADER + MAX_HEADER) #define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT * state, about 60 seconds */ -- cgit v1.2.3-70-g09d2 From 89e7e57778ecd8744fee97491300f05a9fb1388a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 11:13:33 -0200 Subject: [DCCPv6]: Add a FIXME for missing IPV6_PKTOPTIONS This refers to the possible memory leak pointed out in http://www.mail-archive.com/dccp@vger.kernel.org/msg00574.html, fixed by David Miller in http://www.mail-archive.com/netdev@vger.kernel.org/msg24881.html and adds a FIXME to point out where code is missing. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv6.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index fc4242c0767c..6f1c2ad88608 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -990,13 +990,17 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) --ANK (980728) */ if (np->rxopt.all) + /* + * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below + * (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example. + */ opt_skb = skb_clone(skb, GFP_ATOMIC); if (sk->sk_state == DCCP_OPEN) { /* Fast path */ if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len)) goto reset; if (opt_skb) { - /* This is where we would goto ipv6_pktoptions. */ + /* XXX This is where we would goto ipv6_pktoptions. */ __kfree_skb(opt_skb); } return 0; @@ -1024,7 +1028,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len)) goto reset; if (opt_skb) { - /* This is where we would goto ipv6_pktoptions. */ + /* XXX This is where we would goto ipv6_pktoptions. */ __kfree_skb(opt_skb); } return 0; -- cgit v1.2.3-70-g09d2 From 9b42078ed6edfe04e9dc9a59b946ad912aeef717 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 11:22:32 -0200 Subject: [DCCP]: Combine allocating & zeroing header space on skb This is a code simplification: it combines three often recurring operations into one inline function, * allocate `len' bytes header space in skb * fill these `len' bytes with zeroes * cast the start of this header space as dccp_hdr Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 7 +++++++ net/dccp/ipv4.c | 9 ++------- net/dccp/ipv6.c | 8 ++------ net/dccp/output.c | 14 +++----------- 4 files changed, 14 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 53553c99cad6..90d04ffddae8 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -256,6 +256,13 @@ static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb) return (struct dccp_hdr *)skb->h.raw; } +static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen) +{ + skb->h.raw = skb_push(skb, headlen); + memset(skb->h.raw, 0, headlen); + return dccp_hdr(skb); +} + static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb) { return (struct dccp_hdr_ext *)(skb->h.raw + sizeof(struct dccp_hdr)); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index de64e6c7f93d..ce8eed32dbeb 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -212,12 +212,9 @@ static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb, /* Reserve space for headers. */ skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header); - skb->dst = dst_clone(rxskb->dst); - skb->h.raw = skb_push(skb, dccp_hdr_ack_len); - dh = dccp_hdr(skb); - memset(dh, 0, dccp_hdr_ack_len); + dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len); /* Build DCCP header and checksum it. */ dh->dccph_type = DCCP_PKT_ACK; @@ -720,9 +717,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header); skb->dst = dst_clone(dst); - skb->h.raw = skb_push(skb, dccp_hdr_reset_len); - dh = dccp_hdr(skb); - memset(dh, 0, dccp_hdr_reset_len); + dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len); /* Build DCCP header and checksum it. */ dh->dccph_type = DCCP_PKT_RESET; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6f1c2ad88608..116bddb64b80 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -537,9 +537,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header); - skb->h.raw = skb_push(skb, dccp_hdr_reset_len); - dh = dccp_hdr(skb); - memset(dh, 0, dccp_hdr_reset_len); + dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len); /* Swap the send and the receive. */ dh->dccph_type = DCCP_PKT_RESET; @@ -601,9 +599,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header); - skb->h.raw = skb_push(skb, dccp_hdr_ack_len); - dh = dccp_hdr(skb); - memset(dh, 0, dccp_hdr_ack_len); + dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len); /* Build DCCP header and checksum it. */ dh->dccph_type = DCCP_PKT_ACK; diff --git a/net/dccp/output.c b/net/dccp/output.c index 2cc4f4b2a9dd..1ae2248557c6 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -88,11 +88,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) return -EPROTO; } - skb->h.raw = skb_push(skb, dccp_header_size); - dh = dccp_hdr(skb); /* Build DCCP header and checksum it. */ - memset(dh, 0, dccp_header_size); + dh = dccp_zeroed_hdr(skb, dccp_header_size); dh->dccph_type = dcb->dccpd_type; dh->dccph_sport = inet->sport; dh->dccph_dport = inet->dport; @@ -340,10 +338,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, return NULL; } - skb->h.raw = skb_push(skb, dccp_header_size); - - dh = dccp_hdr(skb); - memset(dh, 0, dccp_header_size); + dh = dccp_zeroed_hdr(skb, dccp_header_size); dh->dccph_sport = inet_sk(sk)->sport; dh->dccph_dport = inet_rsk(req)->rmt_port; @@ -392,10 +387,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, return NULL; } - skb->h.raw = skb_push(skb, dccp_header_size); - - dh = dccp_hdr(skb); - memset(dh, 0, dccp_header_size); + dh = dccp_zeroed_hdr(skb, dccp_header_size); dh->dccph_sport = inet_sk(sk)->sport; dh->dccph_dport = inet_sk(sk)->dport; -- cgit v1.2.3-70-g09d2 From d23c7107bfbaac955289685c522c7ff99dad3780 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 11:46:34 -0200 Subject: [DCCP]: Simplify jump labels in dccp_v{4,6}_rcv This is a code simplification and was singled out from the DCCPv6 Oops patch on http://www.mail-archive.com/dccp@vger.kernel.org/msg00600.html It mainly makes the code consistent between ipv{4,6}.c for the functions dccp_v4_rcv dccp_v6_rcv and removes the do_time_wait label to simplify code somewhat. Commiter note: fixed up a compile problem, trivial. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv4.c | 15 ++++----------- net/dccp/ipv6.c | 22 ++++++++++------------ 2 files changed, 14 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ce8eed32dbeb..7107885ada7e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -910,8 +910,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) dccp_pr_debug_cat("\n"); } else { DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb); - dccp_pr_debug_cat(", ack=%llu\n", - (unsigned long long) + dccp_pr_debug_cat(", ack=%llu\n", (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq); } @@ -940,11 +939,10 @@ static int dccp_v4_rcv(struct sk_buff *skb) * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ - if (sk->sk_state == DCCP_TIME_WAIT) { - dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: " - "do_time_wait\n"); - goto do_time_wait; + dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n"); + inet_twsk_put(inet_twsk(sk)); + goto no_dccp_socket; } if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) @@ -968,17 +966,12 @@ no_dccp_socket: } discard_it: - /* Discard frame. */ kfree_skb(skb); return 0; discard_and_relse: sock_put(sk); goto discard_it; - -do_time_wait: - inet_twsk_put(inet_twsk(sk)); - goto no_dccp_socket; } static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 116bddb64b80..dee085301576 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1071,8 +1071,11 @@ static int dccp_v6_rcv(struct sk_buff **pskb) * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ - if (sk == NULL) + if (sk == NULL) { + dccp_pr_debug("failed to look up flow ID in table and " + "get corresponding socket\n"); goto no_dccp_socket; + } /* * Step 2: @@ -1080,8 +1083,11 @@ static int dccp_v6_rcv(struct sk_buff **pskb) * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ - if (sk->sk_state == DCCP_TIME_WAIT) - goto do_time_wait; + if (sk->sk_state == DCCP_TIME_WAIT) { + dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n"); + inet_twsk_put(inet_twsk(sk)); + goto no_dccp_socket; + } if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; @@ -1101,22 +1107,14 @@ no_dccp_socket: DCCP_RESET_CODE_NO_CONNECTION; dccp_v6_ctl_send_reset(skb); } -discard_it: - - /* - * Discard frame - */ +discard_it: kfree_skb(skb); return 0; discard_and_relse: sock_put(sk); goto discard_it; - -do_time_wait: - inet_twsk_put(inet_twsk(sk)); - goto no_dccp_socket; } static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { -- cgit v1.2.3-70-g09d2 From f6484f7c7ad22e4bb018875c386d6a7aaa441426 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 10 Nov 2006 12:01:52 -0200 Subject: [DCCP] timewait: Remove leftover extern declarations Gerrit Renker noticed dccp_tw_deschedule and submitted a patch with a FIXME, but as he suggests in the same patch the best thing is to just ditch this declaration, while doing that also noticed that tcp_tw_count is as well not defined anywhere, so ditch it too. Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/dccp.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 9f00dd807e04..8964b188aba3 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -35,8 +35,6 @@ extern int dccp_debug; extern struct inet_hashinfo dccp_hashinfo; extern atomic_t dccp_orphan_count; -extern int dccp_tw_count; -extern void dccp_tw_deschedule(struct inet_timewait_sock *tw); extern void dccp_time_wait(struct sock *sk, int state, int timeo); -- cgit v1.2.3-70-g09d2 From 8a73cd09d96aa01743316657fc4e6864fe79b703 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 12:32:01 -0200 Subject: [DCCP]: calling dccp_v{4,6}_reqsk_send_ack is a BUG This patch removes two functions, the send_ack functions of request_sock, which are not called/used by the DCCP code. It is correct that these functions are not called, below is a justification why calling these functions (on a passive socket in the LISTEN/RESPOND state) would mean a DCCP protocol violation. A) Background: using request_sock in TCP: --- net/dccp/dccp.h | 2 ++ net/dccp/ipv4.c | 48 +------------------------------------------ net/dccp/ipv6.c | 57 +--------------------------------------------------- net/dccp/minisocks.c | 10 +++++++++ 4 files changed, 14 insertions(+), 103 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 8964b188aba3..3d4b4a908d11 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -131,6 +131,8 @@ extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); extern void dccp_send_ack(struct sock *sk); extern void dccp_send_delayed_ack(struct sock *sk); +extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk); + extern void dccp_send_sync(struct sock *sk, const u64 seq, const enum dccp_pkt_type pkt_type); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 7107885ada7e..8dd9f5aa27a2 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -193,52 +193,6 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, } /* else let the usual retransmit timer handle it */ } -static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb, - struct request_sock *req) -{ - int err; - struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; - const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) + - sizeof(struct dccp_hdr_ext) + - sizeof(struct dccp_hdr_ack_bits); - struct sk_buff *skb; - - if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) - return; - - skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC); - if (skb == NULL) - return; - - /* Reserve space for headers. */ - skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header); - skb->dst = dst_clone(rxskb->dst); - - dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len); - - /* Build DCCP header and checksum it. */ - dh->dccph_type = DCCP_PKT_ACK; - dh->dccph_sport = rxdh->dccph_dport; - dh->dccph_dport = rxdh->dccph_sport; - dh->dccph_doff = dccp_hdr_ack_len / 4; - dh->dccph_x = 1; - - dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), - DCCP_SKB_CB(rxskb)->dccpd_seq); - - bh_lock_sock(dccp_v4_ctl_socket->sk); - err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, - rxskb->nh.iph->daddr, - rxskb->nh.iph->saddr, NULL); - bh_unlock_sock(dccp_v4_ctl_socket->sk); - - if (err == NET_XMIT_CN || err == 0) { - DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); - DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); - } -} - static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, struct dst_entry *dst) { @@ -1014,7 +968,7 @@ static struct request_sock_ops dccp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct dccp_request_sock), .rtx_syn_ack = dccp_v4_send_response, - .send_ack = dccp_v4_reqsk_send_ack, + .send_ack = dccp_reqsk_send_ack, .destructor = dccp_v4_reqsk_destructor, .send_reset = dccp_v4_ctl_send_reset, }; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index dee085301576..718509dcb24d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -37,8 +37,6 @@ static struct socket *dccp_v6_ctl_socket; static void dccp_v6_ctl_send_reset(struct sk_buff *skb); -static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, - struct request_sock *req); static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb); static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); @@ -493,7 +491,7 @@ static struct request_sock_ops dccp6_request_sock_ops = { .family = AF_INET6, .obj_size = sizeof(struct dccp6_request_sock), .rtx_syn_ack = dccp_v6_send_response, - .send_ack = dccp_v6_reqsk_send_ack, + .send_ack = dccp_reqsk_send_ack, .destructor = dccp_v6_reqsk_destructor, .send_reset = dccp_v6_ctl_send_reset, }; @@ -582,59 +580,6 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) kfree_skb(skb); } -static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, - struct request_sock *req) -{ - struct flowi fl; - struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; - const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) + - sizeof(struct dccp_hdr_ext) + - sizeof(struct dccp_hdr_ack_bits); - struct sk_buff *skb; - - skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header, - GFP_ATOMIC); - if (skb == NULL) - return; - - skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header); - - dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len); - - /* Build DCCP header and checksum it. */ - dh->dccph_type = DCCP_PKT_ACK; - dh->dccph_sport = rxdh->dccph_dport; - dh->dccph_dport = rxdh->dccph_sport; - dh->dccph_doff = dccp_hdr_ack_len / 4; - dh->dccph_x = 1; - - dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), - DCCP_SKB_CB(rxskb)->dccpd_seq); - - memset(&fl, 0, sizeof(fl)); - ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr); - ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr); - - /* FIXME: calculate checksum, IPv4 also should... */ - - fl.proto = IPPROTO_DCCP; - fl.oif = inet6_iif(rxskb); - fl.fl_ip_dport = dh->dccph_dport; - fl.fl_ip_sport = dh->dccph_sport; - security_req_classify_flow(req, &fl); - - if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { - if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { - ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); - DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); - return; - } - } - - kfree_skb(skb); -} - static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 9045438d6b36..5f3e1a4c036b 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -283,3 +284,12 @@ int dccp_child_process(struct sock *parent, struct sock *child, } EXPORT_SYMBOL_GPL(dccp_child_process); + +void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk) +{ + pr_info(KERN_WARNING "DCCP: ACK packets are never sent in " + "LISTEN/RESPOND state\n"); + dump_stack(); +} + +EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); -- cgit v1.2.3-70-g09d2 From 3d2fe62b8d8522722c4fe46b8af13520b73848c4 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 12:52:36 -0200 Subject: [DCCPv4]: remove forward declarations in ipv4.c This relates to Arnaldo's announcement in http://www.mail-archive.com/dccp@vger.kernel.org/msg00604.html Originally this had been part of the Oops fix and is a revised variant of http://www.mail-archive.com/dccp@vger.kernel.org/msg00598.html No code change, merely reshuffling, with the particular objective of having all request_sock_ops close(r) together for more clarity. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv4.c | 266 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 132 insertions(+), 134 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 8dd9f5aa27a2..ed6202652bcc 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -193,37 +193,6 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, } /* else let the usual retransmit timer handle it */ } -static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, - struct dst_entry *dst) -{ - int err = -1; - struct sk_buff *skb; - - /* First, grab a route. */ - - if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL) - goto out; - - skb = dccp_make_response(sk, dst, req); - if (skb != NULL) { - const struct inet_request_sock *ireq = inet_rsk(req); - struct dccp_hdr *dh = dccp_hdr(skb); - - dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr, - ireq->rmt_addr); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, - ireq->rmt_addr, - ireq->opt); - if (err == NET_XMIT_CN) - err = 0; - } - -out: - dst_release(dst); - return err; -} - /* * This routine is called by the ICMP module when it gets some sort of error * condition. If err < 0 then the socket should be closed and the error @@ -400,95 +369,6 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk, dccp_hdr(skb)->dccph_sport); } -static struct request_sock_ops dccp_request_sock_ops; - -int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) -{ - struct inet_request_sock *ireq; - struct dccp_sock dp; - struct request_sock *req; - struct dccp_request_sock *dreq; - const __be32 saddr = skb->nh.iph->saddr; - const __be32 daddr = skb->nh.iph->daddr; - const __be32 service = dccp_hdr_request(skb)->dccph_req_service; - struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); - __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; - - /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ - if (((struct rtable *)skb->dst)->rt_flags & - (RTCF_BROADCAST | RTCF_MULTICAST)) { - reset_code = DCCP_RESET_CODE_NO_CONNECTION; - goto drop; - } - - if (dccp_bad_service_code(sk, service)) { - reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; - goto drop; - } - /* - * TW buckets are converted to open requests without - * limitations, they conserve resources and peer is - * evidently real one. - */ - if (inet_csk_reqsk_queue_is_full(sk)) - goto drop; - - /* - * Accept backlog is full. If we have already queued enough - * of warm entries in syn queue, drop request. It is better than - * clogging syn queue with openreqs with exponentially increasing - * timeout. - */ - if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) - goto drop; - - req = reqsk_alloc(&dccp_request_sock_ops); - if (req == NULL) - goto drop; - - if (dccp_parse_options(sk, skb)) - goto drop_and_free; - - dccp_openreq_init(req, &dp, skb); - - if (security_inet_conn_request(sk, skb, req)) - goto drop_and_free; - - ireq = inet_rsk(req); - ireq->loc_addr = daddr; - ireq->rmt_addr = saddr; - req->rcv_wnd = dccp_feat_default_sequence_window; - ireq->opt = NULL; - - /* - * Step 3: Process LISTEN state - * - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie - * - * In fact we defer setting S.GSR, S.SWL, S.SWH to - * dccp_create_openreq_child. - */ - dreq = dccp_rsk(req); - dreq->dreq_isr = dcb->dccpd_seq; - dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); - dreq->dreq_service = service; - - if (dccp_v4_send_response(sk, req, NULL)) - goto drop_and_free; - - inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); - return 0; - -drop_and_free: - reqsk_free(req); -drop: - DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); - dcb->dccpd_reset_code = reset_code; - return -1; -} - -EXPORT_SYMBOL_GPL(dccp_v4_conn_request); - /* * The three way handshake has completed - we got a valid ACK or DATAACK - * now create the new socket. @@ -640,6 +520,37 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk, return &rt->u.dst; } +static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, + struct dst_entry *dst) +{ + int err = -1; + struct sk_buff *skb; + + /* First, grab a route. */ + + if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL) + goto out; + + skb = dccp_make_response(sk, dst, req); + if (skb != NULL) { + const struct inet_request_sock *ireq = inet_rsk(req); + struct dccp_hdr *dh = dccp_hdr(skb); + + dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr, + ireq->rmt_addr); + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, + ireq->rmt_addr, + ireq->opt); + if (err == NET_XMIT_CN) + err = 0; + } + +out: + dst_release(dst); + return err; +} + static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) { int err; @@ -708,6 +619,107 @@ out: dst_release(dst); } +static void dccp_v4_reqsk_destructor(struct request_sock *req) +{ + kfree(inet_rsk(req)->opt); +} + +static struct request_sock_ops dccp_request_sock_ops __read_mostly = { + .family = PF_INET, + .obj_size = sizeof(struct dccp_request_sock), + .rtx_syn_ack = dccp_v4_send_response, + .send_ack = dccp_reqsk_send_ack, + .destructor = dccp_v4_reqsk_destructor, + .send_reset = dccp_v4_ctl_send_reset, +}; + +int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) +{ + struct inet_request_sock *ireq; + struct dccp_sock dp; + struct request_sock *req; + struct dccp_request_sock *dreq; + const __be32 saddr = skb->nh.iph->saddr; + const __be32 daddr = skb->nh.iph->daddr; + const __be32 service = dccp_hdr_request(skb)->dccph_req_service; + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); + __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; + + /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ + if (((struct rtable *)skb->dst)->rt_flags & + (RTCF_BROADCAST | RTCF_MULTICAST)) { + reset_code = DCCP_RESET_CODE_NO_CONNECTION; + goto drop; + } + + if (dccp_bad_service_code(sk, service)) { + reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; + goto drop; + } + /* + * TW buckets are converted to open requests without + * limitations, they conserve resources and peer is + * evidently real one. + */ + if (inet_csk_reqsk_queue_is_full(sk)) + goto drop; + + /* + * Accept backlog is full. If we have already queued enough + * of warm entries in syn queue, drop request. It is better than + * clogging syn queue with openreqs with exponentially increasing + * timeout. + */ + if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) + goto drop; + + req = reqsk_alloc(&dccp_request_sock_ops); + if (req == NULL) + goto drop; + + if (dccp_parse_options(sk, skb)) + goto drop_and_free; + + dccp_openreq_init(req, &dp, skb); + + if (security_inet_conn_request(sk, skb, req)) + goto drop_and_free; + + ireq = inet_rsk(req); + ireq->loc_addr = daddr; + ireq->rmt_addr = saddr; + req->rcv_wnd = dccp_feat_default_sequence_window; + ireq->opt = NULL; + + /* + * Step 3: Process LISTEN state + * + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie + * + * In fact we defer setting S.GSR, S.SWL, S.SWH to + * dccp_create_openreq_child. + */ + dreq = dccp_rsk(req); + dreq->dreq_isr = dcb->dccpd_seq; + dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); + dreq->dreq_service = service; + + if (dccp_v4_send_response(sk, req, NULL)) + goto drop_and_free; + + inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); + return 0; + +drop_and_free: + reqsk_free(req); +drop: + DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + dcb->dccpd_reset_code = reset_code; + return -1; +} + +EXPORT_SYMBOL_GPL(dccp_v4_conn_request); + int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) { struct dccp_hdr *dh = dccp_hdr(skb); @@ -959,20 +971,6 @@ static int dccp_v4_init_sock(struct sock *sk) return err; } -static void dccp_v4_reqsk_destructor(struct request_sock *req) -{ - kfree(inet_rsk(req)->opt); -} - -static struct request_sock_ops dccp_request_sock_ops __read_mostly = { - .family = PF_INET, - .obj_size = sizeof(struct dccp_request_sock), - .rtx_syn_ack = dccp_v4_send_response, - .send_ack = dccp_reqsk_send_ack, - .destructor = dccp_v4_reqsk_destructor, - .send_reset = dccp_v4_ctl_send_reset, -}; - static struct timewait_sock_ops dccp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct inet_timewait_sock), }; -- cgit v1.2.3-70-g09d2 From 73c9e02c22e35e29db6d0fdec994d261fcfd82c0 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 13:01:31 -0200 Subject: [DCCPv6]: remove forward declarations in ipv6.c This does the same for ipv6.c as the preceding one does for ipv4.c: Only the inet_connection_sock_af_ops forward declarations remain, since at least dccp_ipv6_mapped has a circular dependency to dccp_v6_request_recv_sock. No code change, merely re-ordering. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv6.c | 385 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 190 insertions(+), 195 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 718509dcb24d..ed4a50263802 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -36,11 +36,6 @@ /* Socket used for sending RSTs and ACKs */ static struct socket *dccp_v6_ctl_socket; -static void dccp_v6_ctl_send_reset(struct sk_buff *skb); -static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb); - -static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); - static struct inet_connection_sock_af_ops dccp_ipv6_mapped; static struct inet_connection_sock_af_ops dccp_ipv6_af_ops; @@ -87,183 +82,6 @@ static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) dh->dccph_sport); } -static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, - int addr_len) -{ - struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr; - struct inet_connection_sock *icsk = inet_csk(sk); - struct inet_sock *inet = inet_sk(sk); - struct ipv6_pinfo *np = inet6_sk(sk); - struct dccp_sock *dp = dccp_sk(sk); - struct in6_addr *saddr = NULL, *final_p = NULL, final; - struct flowi fl; - struct dst_entry *dst; - int addr_type; - int err; - - dp->dccps_role = DCCP_ROLE_CLIENT; - - if (addr_len < SIN6_LEN_RFC2133) - return -EINVAL; - - if (usin->sin6_family != AF_INET6) - return -EAFNOSUPPORT; - - memset(&fl, 0, sizeof(fl)); - - if (np->sndflow) { - fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK; - IP6_ECN_flow_init(fl.fl6_flowlabel); - if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) { - struct ip6_flowlabel *flowlabel; - flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); - if (flowlabel == NULL) - return -EINVAL; - ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); - fl6_sock_release(flowlabel); - } - } - /* - * connect() to INADDR_ANY means loopback (BSD'ism). - */ - if (ipv6_addr_any(&usin->sin6_addr)) - usin->sin6_addr.s6_addr[15] = 1; - - addr_type = ipv6_addr_type(&usin->sin6_addr); - - if (addr_type & IPV6_ADDR_MULTICAST) - return -ENETUNREACH; - - if (addr_type & IPV6_ADDR_LINKLOCAL) { - if (addr_len >= sizeof(struct sockaddr_in6) && - usin->sin6_scope_id) { - /* If interface is set while binding, indices - * must coincide. - */ - if (sk->sk_bound_dev_if && - sk->sk_bound_dev_if != usin->sin6_scope_id) - return -EINVAL; - - sk->sk_bound_dev_if = usin->sin6_scope_id; - } - - /* Connect to link-local address requires an interface */ - if (!sk->sk_bound_dev_if) - return -EINVAL; - } - - ipv6_addr_copy(&np->daddr, &usin->sin6_addr); - np->flow_label = fl.fl6_flowlabel; - - /* - * DCCP over IPv4 - */ - if (addr_type == IPV6_ADDR_MAPPED) { - u32 exthdrlen = icsk->icsk_ext_hdr_len; - struct sockaddr_in sin; - - SOCK_DEBUG(sk, "connect: ipv4 mapped\n"); - - if (__ipv6_only_sock(sk)) - return -ENETUNREACH; - - sin.sin_family = AF_INET; - sin.sin_port = usin->sin6_port; - sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3]; - - icsk->icsk_af_ops = &dccp_ipv6_mapped; - sk->sk_backlog_rcv = dccp_v4_do_rcv; - - err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); - if (err) { - icsk->icsk_ext_hdr_len = exthdrlen; - icsk->icsk_af_ops = &dccp_ipv6_af_ops; - sk->sk_backlog_rcv = dccp_v6_do_rcv; - goto failure; - } else { - ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), - inet->saddr); - ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF), - inet->rcv_saddr); - } - - return err; - } - - if (!ipv6_addr_any(&np->rcv_saddr)) - saddr = &np->rcv_saddr; - - fl.proto = IPPROTO_DCCP; - ipv6_addr_copy(&fl.fl6_dst, &np->daddr); - ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr); - fl.oif = sk->sk_bound_dev_if; - fl.fl_ip_dport = usin->sin6_port; - fl.fl_ip_sport = inet->sport; - security_sk_classify_flow(sk, &fl); - - if (np->opt != NULL && np->opt->srcrt != NULL) { - const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - - ipv6_addr_copy(&final, &fl.fl6_dst); - ipv6_addr_copy(&fl.fl6_dst, rt0->addr); - final_p = &final; - } - - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) - goto failure; - - if (final_p) - ipv6_addr_copy(&fl.fl6_dst, final_p); - - err = xfrm_lookup(&dst, &fl, sk, 0); - if (err < 0) - goto failure; - - if (saddr == NULL) { - saddr = &fl.fl6_src; - ipv6_addr_copy(&np->rcv_saddr, saddr); - } - - /* set the source address */ - ipv6_addr_copy(&np->saddr, saddr); - inet->rcv_saddr = LOOPBACK4_IPV6; - - __ip6_dst_store(sk, dst, NULL, NULL); - - icsk->icsk_ext_hdr_len = 0; - if (np->opt != NULL) - icsk->icsk_ext_hdr_len = (np->opt->opt_flen + - np->opt->opt_nflen); - - inet->dport = usin->sin6_port; - - dccp_set_state(sk, DCCP_REQUESTING); - err = inet6_hash_connect(&dccp_death_row, sk); - if (err) - goto late_failure; - /* FIXME */ -#if 0 - dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32, - np->daddr.s6_addr32, - inet->sport, - inet->dport); -#endif - err = dccp_connect(sk); - if (err) - goto late_failure; - - return 0; - -late_failure: - dccp_set_state(sk, DCCP_CLOSED); - __sk_dst_reset(sk); -failure: - inet->dport = 0; - sk->sk_route_caps = 0; - return err; -} - static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __be32 info) { @@ -487,19 +305,6 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static struct request_sock_ops dccp6_request_sock_ops = { - .family = AF_INET6, - .obj_size = sizeof(struct dccp6_request_sock), - .rtx_syn_ack = dccp_v6_send_response, - .send_ack = dccp_reqsk_send_ack, - .destructor = dccp_v6_reqsk_destructor, - .send_reset = dccp_v6_ctl_send_reset, -}; - -static struct timewait_sock_ops dccp6_timewait_sock_ops = { - .twsk_obj_size = sizeof(struct dccp6_timewait_sock), -}; - static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) { struct ipv6_pinfo *np = inet6_sk(sk); @@ -580,6 +385,15 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) kfree_skb(skb); } +static struct request_sock_ops dccp6_request_sock_ops = { + .family = AF_INET6, + .obj_size = sizeof(struct dccp6_request_sock), + .rtx_syn_ack = dccp_v6_send_response, + .send_ack = dccp_reqsk_send_ack, + .destructor = dccp_v6_reqsk_destructor, + .send_reset = dccp_v6_ctl_send_reset, +}; + static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); @@ -1062,6 +876,183 @@ discard_and_relse: goto discard_it; } +static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + int addr_len) +{ + struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr; + struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); + struct in6_addr *saddr = NULL, *final_p = NULL, final; + struct flowi fl; + struct dst_entry *dst; + int addr_type; + int err; + + dp->dccps_role = DCCP_ROLE_CLIENT; + + if (addr_len < SIN6_LEN_RFC2133) + return -EINVAL; + + if (usin->sin6_family != AF_INET6) + return -EAFNOSUPPORT; + + memset(&fl, 0, sizeof(fl)); + + if (np->sndflow) { + fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK; + IP6_ECN_flow_init(fl.fl6_flowlabel); + if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) { + struct ip6_flowlabel *flowlabel; + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); + if (flowlabel == NULL) + return -EINVAL; + ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); + fl6_sock_release(flowlabel); + } + } + /* + * connect() to INADDR_ANY means loopback (BSD'ism). + */ + if (ipv6_addr_any(&usin->sin6_addr)) + usin->sin6_addr.s6_addr[15] = 1; + + addr_type = ipv6_addr_type(&usin->sin6_addr); + + if (addr_type & IPV6_ADDR_MULTICAST) + return -ENETUNREACH; + + if (addr_type & IPV6_ADDR_LINKLOCAL) { + if (addr_len >= sizeof(struct sockaddr_in6) && + usin->sin6_scope_id) { + /* If interface is set while binding, indices + * must coincide. + */ + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != usin->sin6_scope_id) + return -EINVAL; + + sk->sk_bound_dev_if = usin->sin6_scope_id; + } + + /* Connect to link-local address requires an interface */ + if (!sk->sk_bound_dev_if) + return -EINVAL; + } + + ipv6_addr_copy(&np->daddr, &usin->sin6_addr); + np->flow_label = fl.fl6_flowlabel; + + /* + * DCCP over IPv4 + */ + if (addr_type == IPV6_ADDR_MAPPED) { + u32 exthdrlen = icsk->icsk_ext_hdr_len; + struct sockaddr_in sin; + + SOCK_DEBUG(sk, "connect: ipv4 mapped\n"); + + if (__ipv6_only_sock(sk)) + return -ENETUNREACH; + + sin.sin_family = AF_INET; + sin.sin_port = usin->sin6_port; + sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3]; + + icsk->icsk_af_ops = &dccp_ipv6_mapped; + sk->sk_backlog_rcv = dccp_v4_do_rcv; + + err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); + if (err) { + icsk->icsk_ext_hdr_len = exthdrlen; + icsk->icsk_af_ops = &dccp_ipv6_af_ops; + sk->sk_backlog_rcv = dccp_v6_do_rcv; + goto failure; + } else { + ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), + inet->saddr); + ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF), + inet->rcv_saddr); + } + + return err; + } + + if (!ipv6_addr_any(&np->rcv_saddr)) + saddr = &np->rcv_saddr; + + fl.proto = IPPROTO_DCCP; + ipv6_addr_copy(&fl.fl6_dst, &np->daddr); + ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr); + fl.oif = sk->sk_bound_dev_if; + fl.fl_ip_dport = usin->sin6_port; + fl.fl_ip_sport = inet->sport; + security_sk_classify_flow(sk, &fl); + + if (np->opt != NULL && np->opt->srcrt != NULL) { + const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; + + ipv6_addr_copy(&final, &fl.fl6_dst); + ipv6_addr_copy(&fl.fl6_dst, rt0->addr); + final_p = &final; + } + + err = ip6_dst_lookup(sk, &dst, &fl); + if (err) + goto failure; + + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + + err = xfrm_lookup(&dst, &fl, sk, 0); + if (err < 0) + goto failure; + + if (saddr == NULL) { + saddr = &fl.fl6_src; + ipv6_addr_copy(&np->rcv_saddr, saddr); + } + + /* set the source address */ + ipv6_addr_copy(&np->saddr, saddr); + inet->rcv_saddr = LOOPBACK4_IPV6; + + __ip6_dst_store(sk, dst, NULL, NULL); + + icsk->icsk_ext_hdr_len = 0; + if (np->opt != NULL) + icsk->icsk_ext_hdr_len = (np->opt->opt_flen + + np->opt->opt_nflen); + + inet->dport = usin->sin6_port; + + dccp_set_state(sk, DCCP_REQUESTING); + err = inet6_hash_connect(&dccp_death_row, sk); + if (err) + goto late_failure; + /* FIXME */ +#if 0 + dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32, + np->daddr.s6_addr32, + inet->sport, + inet->dport); +#endif + err = dccp_connect(sk); + if (err) + goto late_failure; + + return 0; + +late_failure: + dccp_set_state(sk, DCCP_CLOSED); + __sk_dst_reset(sk); +failure: + inet->dport = 0; + sk->sk_route_caps = 0; + return err; +} + static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { .queue_xmit = inet6_csk_xmit, .send_check = dccp_v6_send_check, @@ -1122,6 +1113,10 @@ static int dccp_v6_destroy_sock(struct sock *sk) return inet6_destroy_sock(sk); } +static struct timewait_sock_ops dccp6_timewait_sock_ops = { + .twsk_obj_size = sizeof(struct dccp6_timewait_sock), +}; + static struct proto dccp_v6_prot = { .name = "DCCPv6", .owner = THIS_MODULE, -- cgit v1.2.3-70-g09d2 From fec5b80e4924f638418c21b09165dce8b79fee86 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Fri, 10 Nov 2006 13:04:52 -0200 Subject: [DCCP]: Fix DCCP Probe Typo Fixes a typo in Kconfig, patch is by Ian McDonald and is re-sent from http://www.mail-archive.com/dccp@vger.kernel.org/msg00579.html Signed-off-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index ef8919cca74b..2fc5e55d2a8d 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig @@ -49,7 +49,7 @@ config NET_DCCPPROBE DCCP congestion avoidance modules. If you don't understand what was just said, you don't need it: say N. - Documentation on how to use the packet generator can be found + Documentation on how to use DCCP connection probing can be found at http://linux-net.osdl.org/index.php/DccpProbe To compile this code as a module, choose M here: the -- cgit v1.2.3-70-g09d2 From f45b3ec481581f24719d8ab0bc812c02fcedc2bc Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Fri, 10 Nov 2006 13:09:10 -0200 Subject: [DCCP]: Fix logfile overflow This patch fixes data being spewed into the logs continually. As the code stood if there was a large queue and long delays timeo would go down to zero and never get reset. This fixes it by resetting timeo. Put constant into header as well. Signed-off-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/dccp.h | 2 ++ net/dccp/output.c | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 3d4b4a908d11..7b859a723826 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -62,6 +62,8 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); #define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */ +#define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */ + /* is seq1 < seq2 ? */ static inline int before48(const u64 seq1, const u64 seq2) { diff --git a/net/dccp/output.c b/net/dccp/output.c index 1ae2248557c6..51654975e8ea 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -249,8 +249,8 @@ void dccp_write_xmit(struct sock *sk, int block) { struct dccp_sock *dp = dccp_sk(sk); struct sk_buff *skb; - long timeo = 30000; /* If a packet is taking longer than 2 secs - we have other issues */ + long timeo = DCCP_XMIT_TIMEO; /* If a packet is taking longer than + this we have other issues */ while ((skb = skb_peek(&sk->sk_write_queue))) { int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, @@ -261,8 +261,10 @@ void dccp_write_xmit(struct sock *sk, int block) sk_reset_timer(sk, &dp->dccps_xmit_timer, msecs_to_jiffies(err)+jiffies); break; - } else + } else { err = dccp_wait_for_ccid(sk, skb, &timeo); + timeo = DCCP_XMIT_TIMEO; + } if (err) { printk(KERN_CRIT "%s:err at dccp_wait_for_ccid" " %d\n", __FUNCTION__, err); -- cgit v1.2.3-70-g09d2 From cf557926f6955b4c3fa55e81fdb3675e752e8eed Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 16:08:37 -0200 Subject: [DCCP]: tidy up dccp_v{4,6}_conn_request This is a code simplification to remove reduplicated code by concentrating and abstracting shared code. Detailed Changes: --- net/dccp/dccp.h | 13 +------------ net/dccp/ipv4.c | 9 +++------ net/dccp/ipv6.c | 7 +++---- net/dccp/minisocks.c | 9 +++++++++ 4 files changed, 16 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 7b859a723826..2990bfb12587 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -155,18 +155,7 @@ extern const char *dccp_state_name(const int state); extern void dccp_set_state(struct sock *sk, const int state); extern void dccp_done(struct sock *sk); -static inline void dccp_openreq_init(struct request_sock *req, - struct dccp_sock *dp, - struct sk_buff *skb) -{ - /* - * FIXME: fill in the other req fields from the DCCP options - * received - */ - inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; - inet_rsk(req)->acked = 0; - req->rcv_wnd = 0; -} +extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb); extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ed6202652bcc..d75ce8c7e488 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -636,11 +636,8 @@ static struct request_sock_ops dccp_request_sock_ops __read_mostly = { int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) { struct inet_request_sock *ireq; - struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; - const __be32 saddr = skb->nh.iph->saddr; - const __be32 daddr = skb->nh.iph->daddr; const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; @@ -680,14 +677,14 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (dccp_parse_options(sk, skb)) goto drop_and_free; - dccp_openreq_init(req, &dp, skb); + dccp_reqsk_init(req, skb); if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; ireq = inet_rsk(req); - ireq->loc_addr = daddr; - ireq->rmt_addr = saddr; + ireq->loc_addr = skb->nh.iph->daddr; + ireq->rmt_addr = skb->nh.iph->saddr; req->rcv_wnd = dccp_feat_default_sequence_window; ireq->opt = NULL; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index ed4a50263802..19a4f763099d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -427,7 +427,6 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) { - struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; struct inet6_request_sock *ireq6; @@ -459,9 +458,10 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (req == NULL) goto drop; - /* FIXME: process options */ + if (dccp_parse_options(sk, skb)) + goto drop_and_free; - dccp_openreq_init(req, &dp, skb); + dccp_reqsk_init(req, skb); if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; @@ -469,7 +469,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq6 = inet6_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr); - req->rcv_wnd = dccp_feat_default_sequence_window; ireq6->pktopts = NULL; if (ipv6_opt_accepted(sk, skb) || diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 5f3e1a4c036b..0f228ab5169d 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -293,3 +293,12 @@ void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk) } EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); + +void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb) +{ + inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; + inet_rsk(req)->acked = 0; + req->rcv_wnd = dccp_feat_default_sequence_window; +} + +EXPORT_SYMBOL_GPL(dccp_reqsk_init); -- cgit v1.2.3-70-g09d2 From d83ca5accb256de1b44835cd222bfdc3207bd7dc Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 16:29:14 -0200 Subject: [DCCP]: Update code comments for Step 2/3 Sorts out the comments for processing steps 2,3 in section 8.5 of RFC 4340. All comments have been updated against this document, and the reference to step 2 has been made consistent throughout the files. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/input.c | 38 +++++++++++++++++--------------------- net/dccp/ipv4.c | 38 ++++++++++++++++++-------------------- net/dccp/ipv6.c | 33 ++++++++++++++++++++++++++++----- net/dccp/minisocks.c | 10 +++++----- 4 files changed, 68 insertions(+), 51 deletions(-) (limited to 'net') diff --git a/net/dccp/input.c b/net/dccp/input.c index 1d24881ac0ab..97ccdc30fd89 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -431,29 +431,25 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* * Step 3: Process LISTEN state - * (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv) * * If S.state == LISTEN, - * If P.type == Request or P contains a valid Init Cookie - * option, - * * Must scan the packet's options to check for an Init - * Cookie. Only the Init Cookie is processed here, - * however; other options are processed in Step 8. This - * scan need only be performed if the endpoint uses Init - * Cookies * - * * Generate a new socket and switch to that socket * - * Set S := new socket for this port pair - * S.state = RESPOND - * Choose S.ISS (initial seqno) or set from Init Cookie - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie - * Continue with S.state == RESPOND - * * A Response packet will be generated in Step 11 * - * Otherwise, - * Generate Reset(No Connection) unless P.type == Reset - * Drop packet and return - * - * NOTE: the check for the packet types is done in - * dccp_rcv_state_process + * If P.type == Request or P contains a valid Init Cookie option, + * (* Must scan the packet's options to check for Init + * Cookies. Only Init Cookies are processed here, + * however; other options are processed in Step 8. This + * scan need only be performed if the endpoint uses Init + * Cookies *) + * (* Generate a new socket and switch to that socket *) + * Set S := new socket for this port pair + * S.state = RESPOND + * Choose S.ISS (initial seqno) or set from Init Cookies + * Initialize S.GAR := S.ISS + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init + * Cookies Continue with S.state == RESPOND + * (* A Response packet will be generated in Step 11 *) + * Otherwise, + * Generate Reset(No Connection) unless P.type == Reset + * Drop packet and return */ if (sk->sk_state == DCCP_LISTEN) { if (dh->dccph_type == DCCP_PKT_REQUEST) { diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index d75ce8c7e488..91bffaa761a6 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -729,24 +729,23 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) /* * Step 3: Process LISTEN state - * If S.state == LISTEN, - * If P.type == Request or P contains a valid Init Cookie - * option, - * * Must scan the packet's options to check for an Init - * Cookie. Only the Init Cookie is processed here, - * however; other options are processed in Step 8. This - * scan need only be performed if the endpoint uses Init - * Cookies * - * * Generate a new socket and switch to that socket * - * Set S := new socket for this port pair - * S.state = RESPOND - * Choose S.ISS (initial seqno) or set from Init Cookie - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie - * Continue with S.state == RESPOND - * * A Response packet will be generated in Step 11 * - * Otherwise, - * Generate Reset(No Connection) unless P.type == Reset - * Drop packet and return + * If P.type == Request or P contains a valid Init Cookie option, + * (* Must scan the packet's options to check for Init + * Cookies. Only Init Cookies are processed here, + * however; other options are processed in Step 8. This + * scan need only be performed if the endpoint uses Init + * Cookies *) + * (* Generate a new socket and switch to that socket *) + * Set S := new socket for this port pair + * S.state = RESPOND + * Choose S.ISS (initial seqno) or set from Init Cookies + * Initialize S.GAR := S.ISS + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies + * Continue with S.state == RESPOND + * (* A Response packet will be generated in Step 11 *) + * Otherwise, + * Generate Reset(No Connection) unless P.type == Reset + * Drop packet and return * * NOTE: the check for the packet types is done in * dccp_rcv_state_process @@ -887,8 +886,6 @@ static int dccp_v4_rcv(struct sk_buff *skb) /* * Step 2: * If no socket ... - * Generate Reset(No Connection) unless P.type == Reset - * Drop packet and return */ if (sk == NULL) { dccp_pr_debug("failed to look up flow ID in table and " @@ -919,6 +916,7 @@ no_dccp_socket: goto discard_it; /* * Step 2: + * If no socket ... * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 19a4f763099d..201801e1532d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -487,10 +487,10 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) /* * Step 3: Process LISTEN state * - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie * - * In fact we defer setting S.GSR, S.SWL, S.SWH to - * dccp_create_openreq_child. + * In fact we defer setting S.GSR, S.SWL, S.SWH to + * dccp_create_openreq_child. */ dreq = dccp_rsk(req); dreq->dreq_isr = dcb->dccpd_seq; @@ -760,6 +760,30 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; } + /* + * Step 3: Process LISTEN state + * If S.state == LISTEN, + * If P.type == Request or P contains a valid Init Cookie option, + * (* Must scan the packet's options to check for Init + * Cookies. Only Init Cookies are processed here, + * however; other options are processed in Step 8. This + * scan need only be performed if the endpoint uses Init + * Cookies *) + * (* Generate a new socket and switch to that socket *) + * Set S := new socket for this port pair + * S.state = RESPOND + * Choose S.ISS (initial seqno) or set from Init Cookies + * Initialize S.GAR := S.ISS + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies + * Continue with S.state == RESPOND + * (* A Response packet will be generated in Step 11 *) + * Otherwise, + * Generate Reset(No Connection) unless P.type == Reset + * Drop packet and return + * + * NOTE: the check for the packet types is done in + * dccp_rcv_state_process + */ if (sk->sk_state == DCCP_LISTEN) { struct sock *nsk = dccp_v6_hnd_req(sk, skb); @@ -826,8 +850,6 @@ static int dccp_v6_rcv(struct sk_buff **pskb) /* * Step 2: * If no socket ... - * Generate Reset(No Connection) unless P.type == Reset - * Drop packet and return */ if (sk == NULL) { dccp_pr_debug("failed to look up flow ID in table and " @@ -857,6 +879,7 @@ no_dccp_socket: goto discard_it; /* * Step 2: + * If no socket ... * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 0f228ab5169d..d3de696fe4bf 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -98,8 +98,8 @@ struct sock *dccp_create_openreq_child(struct sock *sk, /* * Step 3: Process LISTEN state * - * // Generate a new socket and switch to that socket - * Set S := new socket for this port pair + * (* Generate a new socket and switch to that socket *) + * Set S := new socket for this port pair */ struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC); @@ -148,9 +148,9 @@ out_free: /* * Step 3: Process LISTEN state * - * Choose S.ISS (initial seqno) or set from Init Cookie - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init - * Cookie + * Choose S.ISS (initial seqno) or set from Init Cookies + * Initialize S.GAR := S.ISS + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies */ /* See dccp_v4_conn_request */ -- cgit v1.2.3-70-g09d2 From 33e93c9699981024cc99fb23a0545fb19d23847d Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 14 Oct 2006 02:00:56 +0900 Subject: [IPV6] ROUTE: Use macros to format /proc/net/ipv6_route. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/route.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e3eab1529633..c86ee3adddcc 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2246,7 +2246,6 @@ struct rt6_proc_arg static int rt6_info_route(struct rt6_info *rt, void *p_arg) { struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg; - int i; if (arg->skip < arg->offset / RT6_INFO_LEN) { arg->skip++; @@ -2256,38 +2255,28 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) if (arg->len >= arg->length) return 0; - for (i=0; i<16; i++) { - sprintf(arg->buffer + arg->len, "%02x", - rt->rt6i_dst.addr.s6_addr[i]); - arg->len += 2; - } - arg->len += sprintf(arg->buffer + arg->len, " %02x ", + arg->len += sprintf(arg->buffer + arg->len, + NIP6_SEQFMT " %02x ", + NIP6(rt->rt6i_dst.addr), rt->rt6i_dst.plen); #ifdef CONFIG_IPV6_SUBTREES - for (i=0; i<16; i++) { - sprintf(arg->buffer + arg->len, "%02x", - rt->rt6i_src.addr.s6_addr[i]); - arg->len += 2; - } - arg->len += sprintf(arg->buffer + arg->len, " %02x ", + arg->len += sprintf(arg->buffer + arg->len, + NIP6_SEQFMT " %02x ", + NIP6(rt->rt6i_src.addr), rt->rt6i_src.plen); #else - sprintf(arg->buffer + arg->len, - "00000000000000000000000000000000 00 "); - arg->len += 36; + arg->len += sprintf(arg->buffer + arg->len, + "00000000000000000000000000000000 00 "); #endif if (rt->rt6i_nexthop) { - for (i=0; i<16; i++) { - sprintf(arg->buffer + arg->len, "%02x", - rt->rt6i_nexthop->primary_key[i]); - arg->len += 2; - } + arg->len += sprintf(arg->buffer + arg->len, + NIP6_SEQFMT, + NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key))); } else { - sprintf(arg->buffer + arg->len, - "00000000000000000000000000000000"); - arg->len += 32; + arg->len += sprintf(arg->buffer + arg->len, + "00000000000000000000000000000000"); } arg->len += sprintf(arg->buffer + arg->len, " %08x %08x %08x %08x %8s\n", -- cgit v1.2.3-70-g09d2 From 40aa7b90a9b41a2162c829fd6cd34a09056a7ddb Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Thu, 19 Oct 2006 13:50:09 +0900 Subject: [IPV6] ROUTE: Use &rt->u.dst instead of cast. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/fib6_rules.c | 2 +- net/ipv6/route.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 8377477b2c19..25804cb69cf0 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -63,7 +63,7 @@ struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, fib_rule_put(arg.rule); if (arg.result) - return (struct dst_entry *) arg.result; + return arg.result; dst_hold(&ip6_null_entry.u.dst); return &ip6_null_entry.u.dst; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c86ee3adddcc..eb78b5252248 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -940,7 +940,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, fib6_force_start_gc(); out: - return (struct dst_entry *)rt; + return &rt->u.dst; } int ndisc_dst_gc(int *more) @@ -1223,7 +1223,7 @@ out: if (idev) in6_dev_put(idev); if (rt) - dst_free((struct dst_entry *) rt); + dst_free(&rt->u.dst); return err; } @@ -1822,7 +1822,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, rt->rt6i_flags |= RTF_LOCAL; rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); if (rt->rt6i_nexthop == NULL) { - dst_free((struct dst_entry *) rt); + dst_free(&rt->u.dst); return ERR_PTR(-ENOMEM); } -- cgit v1.2.3-70-g09d2 From 7a3025b1b3a0173be5de6ced18754b909da27b38 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Fri, 13 Oct 2006 16:17:25 +0900 Subject: [IPV6]: Introduce ip6_dst_idev() to get inet6_dev{} stored in dst_entry{}. Otherwise, we will see a lot of casts... Signed-off-by: YOSHIFUJI Hideaki --- include/net/ip6_fib.h | 5 +++++ net/ipv6/addrconf.c | 2 +- net/ipv6/ip6_input.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index e4438de3bd6b..f9cde44f93b4 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -107,6 +107,11 @@ struct rt6_info u8 rt6i_protocol; }; +static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) +{ + return ((struct rt6_info *)dst)->rt6i_idev; +} + struct fib6_walker_t { struct fib6_walker_t *prev, *next; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b312a5f7a759..6a98f68348cb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1164,7 +1164,7 @@ record_it: int ipv6_get_saddr(struct dst_entry *dst, struct in6_addr *daddr, struct in6_addr *saddr) { - return ipv6_dev_get_saddr(dst ? ((struct rt6_info *)dst)->rt6i_idev->dev : NULL, daddr, saddr); + return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 6b8e6d76a58b..ebf54ae90a0c 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -84,7 +84,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt * arrived via the sending interface (ethX), because of the * nature of scoping architecture. --yoshfuji */ - IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; + IP6CB(skb)->iif = skb->dst ? ip6_dst_idev(skb->dst)->dev->ifindex : dev->ifindex; if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) goto err; -- cgit v1.2.3-70-g09d2 From a11d206d0f88e092419877c7f706cafb5e1c2e57 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 4 Nov 2006 20:11:37 +0900 Subject: [IPV6]: Per-interface statistics support. For IP MIB (RFC4293). Signed-off-by: YOSHIFUJI Hideaki --- include/net/if_inet6.h | 1 + include/net/ipv6.h | 21 ++++++++++++--- net/ipv6/exthdrs.c | 57 ++++++++++++++++++++++++++-------------- net/ipv6/icmp.c | 3 ++- net/ipv6/ip6_input.c | 40 +++++++++++++++++++--------- net/ipv6/ip6_output.c | 71 +++++++++++++++++++++++++++++--------------------- net/ipv6/mcast.c | 20 +++++++++----- net/ipv6/ndisc.c | 8 +++--- net/ipv6/netfilter.c | 2 +- net/ipv6/proc.c | 7 +++++ net/ipv6/raw.c | 4 +-- net/ipv6/reassembly.c | 65 +++++++++++++++++++++++++++------------------ net/ipv6/route.c | 4 +-- 13 files changed, 195 insertions(+), 108 deletions(-) (limited to 'net') diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 34489c13c119..3ec7d07346d6 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -152,6 +152,7 @@ struct ifacaddr6 struct ipv6_devstat { struct proc_dir_entry *proc_dir_entry; + DEFINE_SNMP_STAT(struct ipstats_mib, ipv6); DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); }; diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0b8c9b990ac4..3c266ad99a02 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -113,9 +113,24 @@ extern int sysctl_mld_max_msf; /* MIBs */ DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); -#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field) -#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field) -#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field) +#define IP6_INC_STATS(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS(_idev->stats.ipv6, field); \ + SNMP_INC_STATS(ipv6_statistics, field); \ +}) +#define IP6_INC_STATS_BH(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS_BH(_idev->stats.ipv6, field); \ + SNMP_INC_STATS_BH(ipv6_statistics, field); \ +}) +#define IP6_INC_STATS_USER(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS_USER(_idev->stats.ipv6, field); \ + SNMP_INC_STATS_USER(ipv6_statistics, field); \ +}) DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); #define ICMP6_INC_STATS(idev, field) ({ \ struct inet6_dev *_idev = (idev); \ diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 88c96b10684c..27829cc4ce88 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) #ifdef CONFIG_IPV6_MIP6 __u16 dstbuf; #endif + struct dst_entry *dst; if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) dstbuf = opt->dst1; #endif + dst = dst_clone(skb->dst); if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { + dst_release(dst); skb = *skbp; skb->h.raw += ((skb->h.raw[1]+1)<<3); opt = IP6CB(skb); @@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) return 1; } - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); + dst_release(dst); return -1; } @@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || skb->pkt_type != PACKET_HOST) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -388,7 +395,8 @@ looped_back: * processed by own */ if (!addr) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -410,7 +418,8 @@ looped_back: switch (hdr->type) { case IPV6_SRCRT_TYPE_0: if (hdr->hdrlen & 0x01) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); return -1; } @@ -419,14 +428,16 @@ looped_back: case IPV6_SRCRT_TYPE_2: /* Silently discard invalid RTH type 2 */ if (hdr->hdrlen != 2 || hdr->segments_left != 1) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } break; #endif default: - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); return -1; } @@ -439,7 +450,8 @@ looped_back: n = hdr->hdrlen >> 1; if (hdr->segments_left > n) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); return -1; } @@ -449,12 +461,14 @@ looped_back: */ if (skb_cloned(skb)) { struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); - kfree_skb(skb); /* the copy is a forwarded packet */ if (skb2 == NULL) { - IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); return -1; } + kfree_skb(skb); *skbp = skb = skb2; opt = IP6CB(skb2); hdr = (struct ipv6_rt_hdr *) skb2->h.raw; @@ -475,12 +489,14 @@ looped_back: if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, (xfrm_address_t *)&skb->nh.ipv6h->saddr, IPPROTO_ROUTING) < 0) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } if (!ipv6_chk_home_addr(addr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -491,7 +507,8 @@ looped_back: } if (ipv6_addr_is_multicast(addr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -510,7 +527,8 @@ looped_back: if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->nh.ipv6h->hop_limit <= 1) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); kfree_skb(skb); @@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]); - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); goto drop; } pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); if (pkt_len <= IPV6_MAXPLEN) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); return 0; } if (skb->nh.ipv6h->payload_len) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); return 0; } if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 81bd45b26c98..52cca93ff2f8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -177,7 +177,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, */ dst = ip6_route_output(sk, fl); if (dst->error) { - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(dst), + IPSTATS_MIB_OUTNOROUTES); } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { res = 1; } else { diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index ebf54ae90a0c..ad0b8abcdf4b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -60,14 +60,22 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt { struct ipv6hdr *hdr; u32 pkt_len; + struct inet6_dev *idev; - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; + if (skb->pkt_type == PACKET_OTHERHOST) { + kfree_skb(skb); + return 0; + } + + rcu_read_lock(); - IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); + idev = __in6_dev_get(skb->dev); + + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); + rcu_read_unlock(); goto out; } @@ -104,7 +112,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); goto drop; } hdr = skb->nh.ipv6h; @@ -112,17 +120,21 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->nexthdr == NEXTHDR_HOP) { if (ipv6_parse_hopopts(&skb) < 0) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); + rcu_read_unlock(); return 0; } } + rcu_read_unlock(); + return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); truncated: - IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); err: - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); drop: + rcu_read_unlock(); kfree_skb(skb); out: return 0; @@ -140,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) unsigned int nhoff; int nexthdr; u8 hash; + struct inet6_dev *idev; /* * Parse extension headers @@ -147,6 +160,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) rcu_read_lock(); resubmit: + idev = ip6_dst_idev(skb->dst); if (!pskb_pull(skb, skb->h.raw - skb->data)) goto discard; nhoff = IP6CB(skb)->nhoff; @@ -185,24 +199,24 @@ resubmit: if (ret > 0) goto resubmit; else if (ret == 0) - IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); } else { if (!raw_sk) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_UNK_NEXTHDR, nhoff, skb->dev); } } else - IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); kfree_skb(skb); } rcu_read_unlock(); return 0; discard: - IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); rcu_read_unlock(); kfree_skb(skb); return 0; @@ -219,7 +233,7 @@ int ip6_mc_input(struct sk_buff *skb) struct ipv6hdr *hdr; int deliver; - IP6_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = skb->nh.ipv6h; deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 1bde3aca3466..85f889270492 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb) } else if (dst->neighbour) return dst->neighbour->output(skb); - IP6_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); return -EINVAL; @@ -118,6 +118,7 @@ static int ip6_output2(struct sk_buff *skb) if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; + struct inet6_dev *idev = ip6_dst_idev(skb->dst); if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, @@ -133,13 +134,13 @@ static int ip6_output2(struct sk_buff *skb) ip6_dev_loopback_xmit); if (skb->nh.ipv6h->hop_limit == 0) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return 0; } } - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); @@ -182,12 +183,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (skb_headroom(skb) < head_room) { struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); - kfree_skb(skb); - skb = skb2; - if (skb == NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + if (skb2 == NULL) { + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); return -ENOBUFS; } + kfree_skb(skb); + skb = skb2; if (sk) skb_set_owner_w(skb, sk); } @@ -230,7 +233,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, mtu = dst_mtu(dst); if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTREQUESTS); return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); } @@ -239,7 +243,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } @@ -373,7 +377,7 @@ int ip6_forward(struct sk_buff *skb) goto error; if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } @@ -406,7 +410,7 @@ int ip6_forward(struct sk_buff *skb) skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -ETIMEDOUT; @@ -419,13 +423,13 @@ int ip6_forward(struct sk_buff *skb) if (proxied > 0) return ip6_input(skb); else if (proxied < 0) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } } if (!xfrm6_route_forward(skb)) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } dst = skb->dst; @@ -464,14 +468,14 @@ int ip6_forward(struct sk_buff *skb) /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); - IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS); - IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } if (skb_cow(skb, dst->dev->hard_header_len)) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); goto drop; } @@ -481,11 +485,11 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; - IP6_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); error: - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); drop: kfree_skb(skb); return -EINVAL; @@ -622,7 +626,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) tmp_hdr = kmalloc(hlen, GFP_ATOMIC); if (!tmp_hdr) { - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } @@ -643,7 +647,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb->data_len = first_len - skb_headlen(skb); skb->len = first_len; skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); - + + dst_hold(&rt->u.dst); for (;;) { /* Prepare header of the next frame, @@ -667,7 +672,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) err = output(skb); if(!err) - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES); if (err || !frag) break; @@ -680,7 +685,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) kfree(tmp_hdr); if (err == 0) { - IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS); + dst_release(&rt->u.dst); return 0; } @@ -690,7 +696,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) frag = skb; } - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS); + dst_release(&rt->u.dst); return err; } @@ -723,7 +730,8 @@ slow_path: if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGFAILS); err = -ENOMEM; goto fail; } @@ -784,15 +792,17 @@ slow_path: if (err) goto fail; - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES); } + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGOKS); kfree_skb(skb); - IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); return err; fail: + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); return err; } @@ -1265,7 +1275,7 @@ alloc_new_skb: return 0; error: inet->cork.length -= length; - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; } @@ -1326,7 +1336,7 @@ int ip6_push_pending_frames(struct sock *sk) skb->priority = sk->sk_priority; skb->dst = dst_clone(&rt->u.dst); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); if (err) { if (err > 0) @@ -1357,7 +1367,8 @@ void ip6_flush_pending_frames(struct sock *sk) struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9055979083b6..c006d02be8bc 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb) struct inet6_dev *idev = in6_dev_get(skb->dev); int err; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - sizeof(struct ipv6hdr); mldlen = skb->tail - skb->h.raw; @@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb) mld_dev_queue_xmit); if (!err) { ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } else - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); if (likely(idev != NULL)) in6_dev_put(idev); @@ -1763,7 +1763,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_PADN, 0 }; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + rcu_read_lock(); + IP6_INC_STATS(__in6_dev_get(dev), + IPSTATS_MIB_OUTREQUESTS); + rcu_read_unlock(); snd_addr = addr; if (type == ICMPV6_MGM_REDUCTION) { snd_addr = &all_routers; @@ -1777,7 +1780,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); if (skb == NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + rcu_read_lock(); + IP6_INC_STATS(__in6_dev_get(dev), + IPSTATS_MIB_OUTDISCARDS); + rcu_read_unlock(); return; } @@ -1816,9 +1822,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) else ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } else - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); if (likely(idev != NULL)) in6_dev_put(idev); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 89d527ebd7f6..1342be8b4cdc 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -515,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); @@ -601,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, /* send it! */ skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); @@ -676,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, /* send it! */ skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); @@ -1512,7 +1512,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, buff->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 580b1aba6722..646a47456fd4 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -31,7 +31,7 @@ int ip6_route_me_harder(struct sk_buff *skb) #endif if (dst->error) { - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); dst_release(dst); return -EINVAL; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index efee7a6301a8..4158d386b0aa 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -161,6 +161,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) if (idev) { seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); + snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); } else { snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); @@ -281,6 +282,9 @@ int snmp6_alloc_dev(struct inet6_dev *idev) if (!idev || !idev->dev) return -EINVAL; + if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), + __alignof__(struct ipstats_mib)) < 0) + goto err_ip; if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), __alignof__(struct icmpv6_mib)) < 0) goto err_icmp; @@ -288,12 +292,15 @@ int snmp6_alloc_dev(struct inet6_dev *idev) return 0; err_icmp: + snmp6_mib_free((void **)idev->stats.ipv6); +err_ip: return err; } int snmp6_free_dev(struct inet6_dev *idev) { snmp6_mib_free((void **)idev->stats.icmpv6); + snmp6_mib_free((void **)idev->stats.ipv6); return 0; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6bc66552442c..18a90075f942 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -586,7 +586,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, if (err) goto error_fault; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) @@ -600,7 +600,7 @@ error_fault: err = -EFAULT; kfree_skb(skb); error: - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f39bbedd1327..3af0d5a6ceeb 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -257,7 +258,7 @@ static __inline__ void fq_kill(struct frag_queue *fq) } } -static void ip6_evictor(void) +static void ip6_evictor(struct inet6_dev *idev) { struct frag_queue *fq; struct list_head *tmp; @@ -284,14 +285,14 @@ static void ip6_evictor(void) spin_unlock(&fq->lock); fq_put(fq, &work); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); } } static void ip6_frag_expire(unsigned long data) { struct frag_queue *fq = (struct frag_queue *) data; - struct net_device *dev; + struct net_device *dev = NULL; spin_lock(&fq->lock); @@ -300,17 +301,19 @@ static void ip6_frag_expire(unsigned long data) fq_kill(fq); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + dev = dev_get_by_index(fq->iif); + if (!dev) + goto out; + + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + rcu_read_unlock(); /* Don't send error if the first segment did not arrive. */ if (!(fq->last_in&FIRST_IN) || !fq->fragments) goto out; - dev = dev_get_by_index(fq->iif); - if (!dev) - goto out; - /* But use as source device on which LAST ARRIVED segment was received. And do not use fq->dev @@ -318,8 +321,9 @@ static void ip6_frag_expire(unsigned long data) */ fq->fragments->dev = dev; icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); - dev_put(dev); out: + if (dev) + dev_put(dev); spin_unlock(&fq->lock); fq_put(fq, NULL); } @@ -366,7 +370,8 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) static struct frag_queue * -ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) +ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst, + struct inet6_dev *idev) { struct frag_queue *fq; @@ -386,12 +391,13 @@ ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) return ip6_frag_intern(fq); oom: - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); return NULL; } static __inline__ struct frag_queue * -fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) +fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst, + struct inet6_dev *idev) { struct frag_queue *fq; struct hlist_node *n; @@ -410,7 +416,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) } read_unlock(&ip6_frag_lock); - return ip6_frag_create(id, src, dst); + return ip6_frag_create(id, src, dst, idev); } @@ -428,7 +434,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); if ((unsigned int)end > IPV6_MAXPLEN) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); return; } @@ -455,7 +462,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, /* RFC2460 says always send parameter problem in * this case. -DaveM */ - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, offsetof(struct ipv6hdr, payload_len)); return; @@ -571,7 +579,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, return; err: - IP6_INC_STATS(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); } @@ -665,7 +673,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, if (head->ip_summed == CHECKSUM_COMPLETE) head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); + rcu_read_unlock(); fq->fragments = NULL; return 1; @@ -677,7 +687,9 @@ out_oom: if (net_ratelimit()) printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); out_fail: - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + rcu_read_unlock(); return -1; } @@ -691,16 +703,16 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) hdr = skb->nh.ipv6h; - IP6_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); /* Jumbo payload inhibits frag. header */ if (hdr->payload_len==0) { - IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); return -1; } if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { - IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); return -1; } @@ -711,16 +723,17 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) if (!(fhdr->frag_off & htons(0xFFF9))) { /* It is not a fragmented frame */ skb->h.raw += sizeof(struct frag_hdr); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; return 1; } if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) - ip6_evictor(); + ip6_evictor(ip6_dst_idev(skb->dst)); - if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) { + if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, + ip6_dst_idev(skb->dst))) != NULL) { int ret = -1; spin_lock(&fq->lock); @@ -736,7 +749,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) return ret; } - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index eb78b5252248..0ad07c9087a7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1749,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) { int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) - IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); kfree_skb(skb); return 0; -- cgit v1.2.3-70-g09d2 From 6f4e5fff1e4d46714ea554fd83e44eab534e8b11 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 17:43:06 -0200 Subject: [DCCP]: Support for partial checksums (RFC 4340, sec. 9.2) This patch does the following: a) introduces variable-length checksums as specified in [RFC 4340, sec. 9.2] b) provides necessary socket options and documentation as to how to use them c) basic support and infrastructure for the Minimum Checksum Coverage feature [RFC 4340, sec. 9.2.1]: acceptability tests, user notification and user interface In addition, it (1) fixes two bugs in the DCCPv4 checksum computation: * pseudo-header used checksum_len instead of skb->len * incorrect checksum coverage calculation based on dccph_x (2) removes dccp_v4_verify_checksum() since it reduplicates code of the checksum computation; code calling this function is updated accordingly. (3) now uses skb_checksum(), which is safer than checksum_partial() if the sk_buff has is a non-linear buffer (has pages attached to it). (4) fixes an outstanding TODO item: * If P.CsCov is too large for the packet size, drop packet and return. The code has been tested with applications, the latest version of tcpdump now comes with support for partial DCCP checksums. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/networking/dccp.txt | 16 ++++++ include/linux/dccp.h | 7 +++ net/dccp/dccp.h | 29 +++++++++-- net/dccp/ipv4.c | 105 +++++++++++++++++++------------------- net/dccp/ipv6.c | 74 +++++++++++++++++---------- net/dccp/output.c | 13 ++--- net/dccp/proto.c | 26 ++++++++-- 7 files changed, 173 insertions(+), 97 deletions(-) (limited to 'net') diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index 74563b38ffd9..a8142a81038a 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -47,6 +47,22 @@ the socket will fall back to 0 (which means that no meaningful service code is present). Connecting sockets set at most one service option; for listening sockets, multiple service codes can be specified. +DCCP_SOCKOPT_SEND_CSCOV and DCCP_SOCKOPT_RECV_CSCOV are used for setting the +partial checksum coverage (RFC 4340, sec. 9.2). The default is that checksums +always cover the entire packet and that only fully covered application data is +accepted by the receiver. Hence, when using this feature on the sender, it must +be enabled at the receiver, too with suitable choice of CsCov. + +DCCP_SOCKOPT_SEND_CSCOV sets the sender checksum coverage. Values in the + range 0..15 are acceptable. The default setting is 0 (full coverage), + values between 1..15 indicate partial coverage. +DCCP_SOCKOPT_SEND_CSCOV is for the receiver and has a different meaning: it + sets a threshold, where again values 0..15 are acceptable. The default + of 0 means that all packets with a partial coverage will be discarded. + Values in the range 1..15 indicate that packets with minimally such a + coverage value are also acceptable. The higher the number, the more + restrictive this setting (see [RFC 4340, sec. 9.2.1]). + Notes ===== diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 90d04ffddae8..0502dfa7f32c 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -183,6 +183,7 @@ enum { DCCPF_ACK_RATIO = 5, DCCPF_SEND_ACK_VECTOR = 6, DCCPF_SEND_NDP_COUNT = 7, + DCCPF_MIN_CSUM_COVER = 8, /* 10-127 reserved */ DCCPF_MIN_CCID_SPECIFIC = 128, DCCPF_MAX_CCID_SPECIFIC = 255, @@ -200,6 +201,8 @@ struct dccp_so_feat { #define DCCP_SOCKOPT_SERVICE 2 #define DCCP_SOCKOPT_CHANGE_L 3 #define DCCP_SOCKOPT_CHANGE_R 4 +#define DCCP_SOCKOPT_SEND_CSCOV 10 +#define DCCP_SOCKOPT_RECV_CSCOV 11 #define DCCP_SOCKOPT_CCID_RX_INFO 128 #define DCCP_SOCKOPT_CCID_TX_INFO 192 @@ -450,6 +453,8 @@ struct dccp_ackvec; * @dccps_timestamp_echo - latest timestamp received on a TIMESTAMP option * @dccps_packet_size - Set thru setsockopt * @dccps_role - Role of this sock, one of %dccp_role + * @dccps_pcslen - sender partial checksum coverage (via sockopt) + * @dccps_pcrlen - receiver partial checksum coverage (via sockopt) * @dccps_ndp_count - number of Non Data Packets since last data packet * @dccps_hc_rx_ackvec - rx half connection ack vector * @dccps_xmit_timer - timer for when CCID is not ready to send @@ -474,6 +479,8 @@ struct dccp_sock { __u32 dccps_packet_size; __u16 dccps_l_ack_ratio; __u16 dccps_r_ack_ratio; + __u16 dccps_pcslen; + __u16 dccps_pcrlen; unsigned long dccps_ndp_count; __u32 dccps_mss_cache; struct dccp_minisock dccps_minisock; diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 2990bfb12587..d5c414bf7819 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -129,6 +129,30 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); #define DCCP_ADD_STATS_USER(field, val) \ SNMP_ADD_STATS_USER(dccp_statistics, field, val) +/* + * Checksumming routines + */ +static inline int dccp_csum_coverage(const struct sk_buff *skb) +{ + const struct dccp_hdr* dh = dccp_hdr(skb); + + if (dh->dccph_cscov == 0) + return skb->len; + return (dh->dccph_doff + dh->dccph_cscov - 1) * sizeof(u32); +} + +static inline void dccp_csum_outgoing(struct sk_buff *skb) +{ + int cov = dccp_csum_coverage(skb); + + if (cov >= skb->len) + dccp_hdr(skb)->dccph_cscov = 0; + + skb->csum = skb_checksum(skb, 0, (cov > skb->len)? skb->len : cov, 0); +} + +extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); + extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); extern void dccp_send_ack(struct sock *sk); @@ -214,14 +238,9 @@ extern void dccp_shutdown(struct sock *sk, int how); extern int inet_dccp_listen(struct socket *sock, int backlog); extern unsigned int dccp_poll(struct file *file, struct socket *sock, poll_table *wait); -extern void dccp_v4_send_check(struct sock *sk, int len, - struct sk_buff *skb); extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); -extern int dccp_v4_checksum(const struct sk_buff *skb, - const __be32 saddr, const __be32 daddr); - extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code); extern void dccp_send_close(struct sock *sk, const int active); extern int dccp_invalid_packet(struct sk_buff *skb); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 91bffaa761a6..496112080f3d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -349,13 +349,19 @@ out: sock_put(sk); } -/* This routine computes an IPv4 DCCP checksum. */ -void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) +static inline u16 dccp_v4_csum_finish(struct sk_buff *skb, + __be32 src, __be32 dst) +{ + return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum); +} + +void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb) { const struct inet_sock *inet = inet_sk(sk); struct dccp_hdr *dh = dccp_hdr(skb); - dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr); + dccp_csum_outgoing(skb); + dh->dccph_checksum = dccp_v4_csum_finish(skb, inet->saddr, inet->daddr); } EXPORT_SYMBOL_GPL(dccp_v4_send_check); @@ -454,47 +460,6 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr, - const __be32 daddr) -{ - const struct dccp_hdr* dh = dccp_hdr(skb); - int checksum_len; - u32 tmp; - - if (dh->dccph_cscov == 0) - checksum_len = skb->len; - else { - checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32); - checksum_len = checksum_len < skb->len ? checksum_len : - skb->len; - } - - tmp = csum_partial((unsigned char *)dh, checksum_len, 0); - return csum_tcpudp_magic(saddr, daddr, checksum_len, - IPPROTO_DCCP, tmp); -} - -EXPORT_SYMBOL_GPL(dccp_v4_checksum); - -static int dccp_v4_verify_checksum(struct sk_buff *skb, - const __be32 saddr, const __be32 daddr) -{ - struct dccp_hdr *dh = dccp_hdr(skb); - int checksum_len; - u32 tmp; - - if (dh->dccph_cscov == 0) - checksum_len = skb->len; - else { - checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32); - checksum_len = checksum_len < skb->len ? checksum_len : - skb->len; - } - tmp = csum_partial((unsigned char *)dh, checksum_len, 0); - return csum_tcpudp_magic(saddr, daddr, checksum_len, - IPPROTO_DCCP, tmp) == 0 ? 0 : -1; -} - static struct dst_entry* dccp_v4_route_skb(struct sock *sk, struct sk_buff *skb) { @@ -536,8 +501,8 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, const struct inet_request_sock *ireq = inet_rsk(req); struct dccp_hdr *dh = dccp_hdr(skb); - dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr, - ireq->rmt_addr); + dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr, + ireq->rmt_addr); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, @@ -602,8 +567,9 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); - dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, - rxskb->nh.iph->daddr); + dccp_csum_outgoing(skb); + dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr, + rxskb->nh.iph->daddr); bh_lock_sock(dccp_v4_ctl_socket->sk); err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, @@ -779,6 +745,7 @@ EXPORT_SYMBOL_GPL(dccp_v4_do_rcv); int dccp_invalid_packet(struct sk_buff *skb) { const struct dccp_hdr *dh; + unsigned int cscov; if (skb->pkt_type != PACKET_HOST) return 1; @@ -830,6 +797,22 @@ int dccp_invalid_packet(struct sk_buff *skb) return 1; } + /* + * If P.CsCov is too large for the packet size, drop packet and return. + * This must come _before_ checksumming (not as RFC 4340 suggests). + */ + cscov = dccp_csum_coverage(skb); + if (cscov > skb->len) { + LIMIT_NETDEBUG(KERN_WARNING + "DCCP: P.CsCov %u exceeds packet length %d\n", + dh->dccph_cscov, skb->len); + return 1; + } + + /* If header checksum is incorrect, drop packet and return. + * (This step is completed in the AF-dependent functions.) */ + skb->csum = skb_checksum(skb, 0, cscov, 0); + return 0; } @@ -840,16 +823,17 @@ static int dccp_v4_rcv(struct sk_buff *skb) { const struct dccp_hdr *dh; struct sock *sk; + int min_cov; - /* Step 1: Check header basics: */ + /* Step 1: Check header basics */ if (dccp_invalid_packet(skb)) goto discard_it; - /* If the header checksum is incorrect, drop packet and return */ - if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr, - skb->nh.iph->daddr) < 0) { - LIMIT_NETDEBUG(KERN_WARNING "%s: incorrect header checksum\n", + /* Step 1: If header checksum is incorrect, drop packet and return */ + if (dccp_v4_csum_finish(skb, skb->nh.iph->saddr, skb->nh.iph->daddr)) { + LIMIT_NETDEBUG(KERN_WARNING + "%s: dropped packet with invalid checksum\n", __FUNCTION__); goto discard_it; } @@ -905,6 +889,21 @@ static int dccp_v4_rcv(struct sk_buff *skb) goto no_dccp_socket; } + /* + * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage + * o if MinCsCov = 0, only packets with CsCov = 0 are accepted + * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov + */ + min_cov = dccp_sk(sk)->dccps_pcrlen; + if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) { + dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n", + dh->dccph_cscov, min_cov); + /* FIXME: "Such packets SHOULD be reported using Data Dropped + * options (Section 11.7) with Drop Code 0, Protocol + * Constraints." */ + goto discard_and_relse; + } + if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; nf_reset(skb); diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 201801e1532d..193b946fd039 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -58,12 +58,22 @@ static void dccp_v6_hash(struct sock *sk) } } -static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len, - struct in6_addr *saddr, - struct in6_addr *daddr, - unsigned long base) +/* add pseudo-header to DCCP checksum stored in skb->csum */ +static inline u16 dccp_v6_csum_finish(struct sk_buff *skb, + struct in6_addr *saddr, + struct in6_addr *daddr) { - return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base); + return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); +} + +static inline void dccp_v6_send_check(struct sock *sk, int unused_value, + struct sk_buff *skb) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + struct dccp_hdr *dh = dccp_hdr(skb); + + dccp_csum_outgoing(skb); + dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); } static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) @@ -280,12 +290,9 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, if (skb != NULL) { struct dccp_hdr *dh = dccp_hdr(skb); - dh->dccph_checksum = dccp_v6_check(dh, skb->len, - &ireq6->loc_addr, - &ireq6->rmt_addr, - csum_partial((char *)dh, - skb->len, - skb->csum)); + dh->dccph_checksum = dccp_v6_csum_finish(skb, + &ireq6->loc_addr, + &ireq6->rmt_addr); ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); err = ip6_xmit(sk, skb, &fl, opt, 0); if (err == NET_XMIT_CN) @@ -305,18 +312,6 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) -{ - struct ipv6_pinfo *np = inet6_sk(sk); - struct dccp_hdr *dh = dccp_hdr(skb); - - dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr, - len, IPPROTO_DCCP, - csum_partial((char *)dh, - dh->dccph_doff << 2, - skb->csum)); -} - static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) { struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; @@ -360,12 +355,14 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); + dccp_csum_outgoing(skb); + dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr, + &rxskb->nh.ipv6h->daddr); + memset(&fl, 0, sizeof(fl)); ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr); ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr); - dh->dccph_checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, - sizeof(*dh), IPPROTO_DCCP, - skb->csum); + fl.proto = IPPROTO_DCCP; fl.oif = inet6_iif(rxskb); fl.fl_ip_dport = dh->dccph_dport; @@ -825,12 +822,22 @@ static int dccp_v6_rcv(struct sk_buff **pskb) const struct dccp_hdr *dh; struct sk_buff *skb = *pskb; struct sock *sk; + int min_cov; - /* Step 1: Check header basics: */ + /* Step 1: Check header basics */ if (dccp_invalid_packet(skb)) goto discard_it; + /* Step 1: If header checksum is incorrect, drop packet and return. */ + if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr)) { + LIMIT_NETDEBUG(KERN_WARNING + "%s: dropped packet with invalid checksum\n", + __FUNCTION__); + goto discard_it; + } + dh = dccp_hdr(skb); DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); @@ -869,6 +876,19 @@ static int dccp_v6_rcv(struct sk_buff **pskb) goto no_dccp_socket; } + /* + * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage + * o if MinCsCov = 0, only packets with CsCov = 0 are accepted + * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov + */ + min_cov = dccp_sk(sk)->dccps_pcrlen; + if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) { + dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n", + dh->dccph_cscov, min_cov); + /* FIXME: send Data Dropped option (see also dccp_v4_rcv) */ + goto discard_and_relse; + } + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; diff --git a/net/dccp/output.c b/net/dccp/output.c index 51654975e8ea..992caedd7725 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -96,6 +96,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) dh->dccph_dport = inet->dport; dh->dccph_doff = (dccp_header_size + dcb->dccpd_opt_len) / 4; dh->dccph_ccval = dcb->dccpd_ccval; + dh->dccph_cscov = dp->dccps_pcslen; /* XXX For now we're using only 48 bits sequence numbers */ dh->dccph_x = 1; @@ -115,7 +116,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) break; } - icsk->icsk_af_ops->send_check(sk, skb->len, skb); + icsk->icsk_af_ops->send_check(sk, 0, skb); if (set_ack) dccp_event_ack_sent(sk); @@ -329,7 +330,6 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, skb_reserve(skb, sk->sk_prot->max_header); skb->dst = dst_clone(dst); - skb->csum = 0; dreq = dccp_rsk(req); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; @@ -352,6 +352,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; + dccp_csum_outgoing(skb); + DCCP_INC_STATS(DCCP_MIB_OUTSEGS); return skb; } @@ -376,7 +378,6 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, skb_reserve(skb, sk->sk_prot->max_header); skb->dst = dst_clone(dst); - skb->csum = 0; dccp_inc_seqno(&dp->dccps_gss); @@ -401,7 +402,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr); dccp_hdr_reset(skb)->dccph_reset_code = code; - inet_csk(sk)->icsk_af_ops->send_check(sk, skb->len, skb); + inet_csk(sk)->icsk_af_ops->send_check(sk, 0, skb); DCCP_INC_STATS(DCCP_MIB_OUTSEGS); return skb; @@ -475,7 +476,6 @@ int dccp_connect(struct sock *sk) skb_reserve(skb, sk->sk_prot->max_header); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; - skb->csum = 0; dccp_skb_entail(sk, skb); dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); @@ -507,7 +507,6 @@ void dccp_send_ack(struct sock *sk) /* Reserve space for headers */ skb_reserve(skb, sk->sk_prot->max_header); - skb->csum = 0; DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; dccp_transmit_skb(sk, skb); } @@ -561,7 +560,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq, /* Reserve space for headers and prepare control bits. */ skb_reserve(skb, sk->sk_prot->max_header); - skb->csum = 0; DCCP_SKB_CB(skb)->dccpd_type = pkt_type; DCCP_SKB_CB(skb)->dccpd_seq = seq; @@ -587,7 +585,6 @@ void dccp_send_close(struct sock *sk, const int active) /* Reserve space for headers and prepare control bits. */ skb_reserve(skb, sk->sk_prot->max_header); - skb->csum = 0; DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 047d170a363a..db54e557eff1 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -472,7 +472,6 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, case DCCP_SOCKOPT_PACKET_SIZE: dp->dccps_packet_size = val; break; - case DCCP_SOCKOPT_CHANGE_L: if (optlen != sizeof(struct dccp_so_feat)) err = -EINVAL; @@ -481,7 +480,6 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, (struct dccp_so_feat __user *) optval); break; - case DCCP_SOCKOPT_CHANGE_R: if (optlen != sizeof(struct dccp_so_feat)) err = -EINVAL; @@ -490,12 +488,26 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, (struct dccp_so_feat __user *) optval); break; - + case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */ + if (val < 0 || val > 15) + err = -EINVAL; + else + dp->dccps_pcslen = val; + break; + case DCCP_SOCKOPT_RECV_CSCOV: /* receiver side, RFC 4340 sec. 9.2.1 */ + if (val < 0 || val > 15) + err = -EINVAL; + else { + dp->dccps_pcrlen = val; + /* FIXME: add feature negotiation, + * ChangeL(MinimumChecksumCoverage, val) */ + } + break; default: err = -ENOPROTOOPT; break; } - + release_sock(sk); return err; } @@ -575,6 +587,12 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, case DCCP_SOCKOPT_SERVICE: return dccp_getsockopt_service(sk, len, (__be32 __user *)optval, optlen); + case DCCP_SOCKOPT_SEND_CSCOV: + val = dp->dccps_pcslen; + break; + case DCCP_SOCKOPT_RECV_CSCOV: + val = dp->dccps_pcrlen; + break; case 128 ... 191: return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, len, (u32 __user *)optval, optlen); -- cgit v1.2.3-70-g09d2 From a94f723d595ee085f81b1788d18e031af7eeba91 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 14:06:49 -0800 Subject: [TCP]: Remove dead code in init_sequence This removes two redundancies: 1) The test (skb->protocol == htons(ETH_P_IPV6) in tcp_v6_init_sequence() is always true, due to * tcp_v6_conn_request() is the only function calling this one * tcp_v6_conn_request() redirects all skb's with ETH_P_IP protocol to tcp_v4_conn_request() [ cf. top of tcp_v6_conn_request()] 2) The first argument, `struct sock *sk' of tcp_v{4,6}_init_sequence() is never used. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv6/tcp_ipv6.c | 19 ++++++------------- 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5fbf96552cac..2eb58844403c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -111,7 +111,7 @@ void tcp_unhash(struct sock *sk) inet_unhash(&tcp_hashinfo, sk); } -static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) +static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb) { return secure_tcp_sequence_number(skb->nh.iph->daddr, skb->nh.iph->saddr, @@ -859,7 +859,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; } - isn = tcp_v4_init_sequence(sk, skb); + isn = tcp_v4_init_sequence(skb); } tcp_rsk(req)->snt_isn = isn; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 06b536b47f97..9a8e690fdf7c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -106,19 +106,12 @@ static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); } -static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) +static __u32 tcp_v6_init_sequence(struct sk_buff *skb) { - if (skb->protocol == htons(ETH_P_IPV6)) { - return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, - skb->nh.ipv6h->saddr.s6_addr32, - skb->h.th->dest, - skb->h.th->source); - } else { - return secure_tcp_sequence_number(skb->nh.iph->daddr, - skb->nh.iph->saddr, - skb->h.th->dest, - skb->h.th->source); - } + return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, + skb->nh.ipv6h->saddr.s6_addr32, + skb->h.th->dest, + skb->h.th->source); } static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, @@ -822,7 +815,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) treq->iif = inet6_iif(skb); if (isn == 0) - isn = tcp_v6_init_sequence(sk,skb); + isn = tcp_v6_init_sequence(skb); tcp_rsk(req)->snt_isn = isn; -- cgit v1.2.3-70-g09d2 From 339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 10 Nov 2006 14:10:15 -0800 Subject: [NETLINK]: Do precise netlink message allocations where possible Account for the netlink message header size directly in nlmsg_new() instead of relying on the caller calculate it correctly. Replaces error handling of message construction functions when constructing notifications with bug traps since a failure implies a bug in calculating the size of the skb. Signed-off-by: Thomas Graf Acked-by: Paul Moore Signed-off-by: David S. Miller --- include/linux/netlink.h | 1 + include/net/fib_rules.h | 1 + include/net/netlink.h | 9 ++--- kernel/taskstats.c | 3 +- net/bridge/br_netlink.c | 21 ++++++++---- net/core/fib_rules.c | 24 +++++++++++--- net/core/neighbour.c | 17 +++++++--- net/core/rtnetlink.c | 39 ++++++++++++++-------- net/decnet/dn_rules.c | 6 ++++ net/decnet/dn_table.c | 34 ++++++++++++++++--- net/ipv4/devinet.c | 18 +++++++--- net/ipv4/fib_rules.c | 8 +++++ net/ipv4/fib_semantics.c | 36 ++++++++++++++++---- net/ipv6/addrconf.c | 70 ++++++++++++++++++--------------------- net/ipv6/fib6_rules.c | 7 ++++ net/ipv6/route.c | 23 +++++++++---- net/netlabel/netlabel_cipso_v4.c | 2 +- net/netlabel/netlabel_mgmt.c | 4 +-- net/netlabel/netlabel_unlabeled.c | 2 +- net/netlink/af_netlink.c | 13 ++++---- net/netlink/genetlink.c | 2 +- 21 files changed, 233 insertions(+), 107 deletions(-) (limited to 'net') diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 66411622e06e..e61e1e138421 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -174,6 +174,7 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol); */ #define NLMSG_GOODORDER 0 #define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER)) +#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN) struct netlink_callback diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index e4ba781d289f..bc3c26494c3d 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -52,6 +52,7 @@ struct fib_rules_ops struct nlmsghdr *, struct fib_rule_hdr *); u32 (*default_pref)(void); + size_t (*nlmsg_payload)(struct fib_rule *); int nlgroup; struct nla_policy *policy; diff --git a/include/net/netlink.h b/include/net/netlink.h index ce5cba19c393..30021339157c 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -500,14 +500,15 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb, /** * nlmsg_new - Allocate a new netlink message - * @size: maximum size of message + * @payload: size of the message payload * @flags: the type of memory to allocate. * - * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. + * Use NLMSG_DEFAULT_SIZE if the size of the payload isn't known + * and a good default is needed. */ -static inline struct sk_buff *nlmsg_new(int size, gfp_t flags) +static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags) { - return alloc_skb(size, flags); + return alloc_skb(nlmsg_total_size(payload), flags); } /** diff --git a/kernel/taskstats.c b/kernel/taskstats.c index f45c5e70773c..4f3f0e48c845 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -77,8 +77,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, /* * If new attributes are added, please revisit this allocation */ - size = nlmsg_total_size(genlmsg_total_size(size)); - skb = nlmsg_new(size, GFP_KERNEL); + skb = nlmsg_new(genlmsg_total_size(size), GFP_KERNEL); if (!skb) return -ENOMEM; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 8f661195d09d..15d6efbe7519 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -15,6 +15,18 @@ #include #include "br_private.h" +static inline size_t br_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + + nla_total_size(4) /* IFLA_MASTER */ + + nla_total_size(4) /* IFLA_MTU */ + + nla_total_size(4) /* IFLA_LINK */ + + nla_total_size(1) /* IFLA_OPERSTATE */ + + nla_total_size(1); /* IFLA_PROTINFO */ +} + /* * Create one netlink message for one interface * Contains port and master info as well as carrier and bridge state. @@ -77,19 +89,16 @@ rtattr_failure: void br_ifinfo_notify(int event, struct net_bridge_port *port) { struct sk_buff *skb; - int payload = sizeof(struct ifinfomsg) + 128; int err = -ENOBUFS; pr_debug("bridge notify event=%d\n", event); - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); + skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; err = br_fill_ifinfo(skb, port, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in br_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); errout: diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 4148e274a204..1df6cd4568d3 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -306,6 +306,22 @@ errout: return err; } +static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops, + struct fib_rule *rule) +{ + size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr)) + + nla_total_size(IFNAMSIZ) /* FRA_IFNAME */ + + nla_total_size(4) /* FRA_PRIORITY */ + + nla_total_size(4) /* FRA_TABLE */ + + nla_total_size(4) /* FRA_FWMARK */ + + nla_total_size(4); /* FRA_FWMASK */ + + if (ops->nlmsg_payload) + payload += ops->nlmsg_payload(rule); + + return payload; +} + static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, u32 pid, u32 seq, int type, int flags, struct fib_rules_ops *ops) @@ -384,15 +400,13 @@ static void notify_rule_change(int event, struct fib_rule *rule, struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL); if (skb == NULL) goto errout; err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in fib_rule_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); errout: diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b4b478353b27..0e097ba14d73 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2410,20 +2410,27 @@ static struct file_operations neigh_stat_seq_fops = { #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_ARPD +static inline size_t neigh_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ndmsg)) + + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */ + + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */ + + nla_total_size(sizeof(struct nda_cacheinfo)) + + nla_total_size(4); /* NDA_PROBES */ +} + static void __neigh_notify(struct neighbour *n, int type, int flags) { struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; err = neigh_fill_info(skb, n, 0, 0, type, flags); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in neigh_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); errout: diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 02f3c7947898..50d6cb40c6e3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -273,6 +273,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->tx_compressed = b->tx_compressed; }; +static inline size_t if_nlmsg_size(int iwbuflen) +{ + return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ + + nla_total_size(sizeof(struct rtnl_link_ifmap)) + + nla_total_size(sizeof(struct rtnl_link_stats)) + + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ + + nla_total_size(4) /* IFLA_TXQLEN */ + + nla_total_size(4) /* IFLA_WEIGHT */ + + nla_total_size(4) /* IFLA_MTU */ + + 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(iwbuflen); +} + static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, void *iwbuf, int iwbuflen, int type, u32 pid, u32 seq, u32 change, unsigned int flags) @@ -558,7 +577,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) struct sk_buff *nskb; char *iw_buf = NULL, *iw = NULL; int iw_buf_len = 0; - int err, payload; + int err; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); if (err < 0) @@ -587,9 +606,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) } #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ - payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + - nla_total_size(iw_buf_len)); - nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); + nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL); if (nskb == NULL) { err = -ENOBUFS; goto errout; @@ -597,10 +614,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); - if (err <= 0) { - kfree_skb(nskb); - goto errout; - } + /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */ + BUG_ON(err < 0); err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); errout: @@ -639,15 +654,13 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(if_nlmsg_size(0), GFP_KERNEL); if (skb == NULL) goto errout; err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in if_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); errout: diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index e32d0c3d5a96..b7dfd04a9638 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -241,6 +241,12 @@ static u32 dn_fib_rule_default_pref(void) return 0; } +static size_t dn_fib_rule_nlmsg_payload(struct fib_rule *rule) +{ + return nla_total_size(2) /* dst */ + + nla_total_size(2); /* src */ +} + int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) { return fib_rules_dump(skb, cb, AF_DECnet); diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 317904bb5896..e74b744254ab 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern return 0; } +static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi) +{ + size_t payload = NLMSG_ALIGN(struct rtmsg) + + nla_total_size(4) /* RTA_TABLE */ + + nla_total_size(2) /* RTA_DST */ + + nla_total_size(4); /* RTA_PRIORITY */ + + /* space for nested metrics */ + payload += nla_total_size((RTAX_MAX * nla_total_size(4))); + + if (fi->fib_nhs) { + /* Also handles the special case fib_nhs == 1 */ + + /* each nexthop is packed in an attribute */ + size_t nhsize = nla_total_size(sizeof(struct rtnexthop)); + + /* may contain a gateway attribute */ + nhsize += nla_total_size(4); + + /* all nexthops are packed in a nested attribute */ + payload += nla_total_size(fi->fib_nhs * nhsize); + } + + return payload; +} + static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, struct dn_fib_info *fi, unsigned int flags) @@ -335,17 +361,15 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id, u32 pid = req ? req->pid : 0; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f), GFP_KERNEL)); if (skb == NULL) goto errout; err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, f->fn_type, f->fn_scope, &f->fn_key, z, DN_FIB_INFO(f), 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in dn_fib_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); errout: diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 7602c79a389b..f38cbbae0ae3 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = { .notifier_call =inetdev_event, }; +static inline size_t inet_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + + nla_total_size(4) /* IFA_ADDRESS */ + + nla_total_size(4) /* IFA_LOCAL */ + + nla_total_size(4) /* IFA_BROADCAST */ + + nla_total_size(4) /* IFA_ANYCAST */ + + nla_total_size(IFNAMSIZ); /* IFA_LABEL */ +} + static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, u32 pid, u32 seq, int event, unsigned int flags) { @@ -1208,15 +1218,13 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh, u32 seq = nlh ? nlh->nlmsg_seq : 0; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); if (skb == NULL) goto errout; err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in inet_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); errout: diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index fd4a8cd4c06e..b837c33e0404 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -299,6 +299,13 @@ static u32 fib4_rule_default_pref(void) return 0; } +static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) +{ + return nla_total_size(4) /* dst */ + + nla_total_size(4) /* src */ + + nla_total_size(4); /* flow */ +} + static struct fib_rules_ops fib4_rules_ops = { .family = AF_INET, .rule_size = sizeof(struct fib4_rule), @@ -308,6 +315,7 @@ static struct fib_rules_ops fib4_rules_ops = { .compare = fib4_rule_compare, .fill = fib4_rule_fill, .default_pref = fib4_rule_default_pref, + .nlmsg_payload = fib4_rule_nlmsg_payload, .nlgroup = RTNLGRP_IPV4_RULE, .policy = fib4_rule_policy, .rules_list = &fib4_rules, diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 884d176e0082..e63b8a98fb4d 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev) return -1; } +static inline size_t fib_nlmsg_size(struct fib_info *fi) +{ + size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg)) + + nla_total_size(4) /* RTA_TABLE */ + + nla_total_size(4) /* RTA_DST */ + + nla_total_size(4) /* RTA_PRIORITY */ + + nla_total_size(4); /* RTA_PREFSRC */ + + /* space for nested metrics */ + payload += nla_total_size((RTAX_MAX * nla_total_size(4))); + + if (fi->fib_nhs) { + /* Also handles the special case fib_nhs == 1 */ + + /* each nexthop is packed in an attribute */ + size_t nhsize = nla_total_size(sizeof(struct rtnexthop)); + + /* may contain flow and gateway attribute */ + nhsize += 2 * nla_total_size(4); + + /* all nexthops are packed in a nested attribute */ + payload += nla_total_size(fi->fib_nhs * nhsize); + } + + return payload; +} + void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, int dst_len, u32 tb_id, struct nl_info *info) { struct sk_buff *skb; - int payload = sizeof(struct rtmsg) + 256; u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; int err = -ENOBUFS; - skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); + skb = nlmsg_new(fib_nlmsg_size(fa->fa_info), GFP_KERNEL); if (skb == NULL) goto errout; err = fib_dump_info(skb, info->pid, seq, event, tb_id, fa->fa_type, fa->fa_scope, key, dst_len, fa->fa_tos, fa->fa_info, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in fib_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, info->nlh, GFP_KERNEL); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6a98f68348cb..967ea320a9ca 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope) static inline int inet6_ifaddr_msgsize(void) { - return nlmsg_total_size(sizeof(struct ifaddrmsg) + - nla_total_size(16) + - nla_total_size(sizeof(struct ifa_cacheinfo)) + - 128); + return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + + nla_total_size(16) /* IFA_ADDRESS */ + + nla_total_size(sizeof(struct ifa_cacheinfo)); } static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, @@ -3329,10 +3328,8 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWADDR, 0); - if (err < 0) { - kfree_skb(skb); - goto errout_ifa; - } + /* failure implies BUG in inet6_ifaddr_msgsize() */ + BUG_ON(err < 0); err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); errout_ifa: @@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) goto errout; err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in inet6_ifaddr_msgsize() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); errout: @@ -3397,16 +3392,19 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; } -/* Maximum length of ifinfomsg attributes */ -#define INET6_IFINFO_RTA_SPACE \ - RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ - RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ - RTA_SPACE(sizeof(u32)) /* MTU */ + \ - RTA_SPACE(sizeof(int)) /* LINK */ + \ - RTA_SPACE(0) /* PROTINFO */ + \ - RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ - RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ - RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ +static inline size_t inet6_if_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + + nla_total_size(4) /* IFLA_MTU */ + + nla_total_size(4) /* IFLA_LINK */ + + nla_total_size( /* IFLA_PROTINFO */ + nla_total_size(4) /* IFLA_INET6_FLAGS */ + + nla_total_size(sizeof(struct ifla_cacheinfo)) + + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ + ); +} static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, u32 pid, u32 seq, int event, unsigned int flags) @@ -3501,18 +3499,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) void inet6_ifinfo_notify(int event, struct inet6_dev *idev) { struct sk_buff *skb; - int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE; int err = -ENOBUFS; - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); + skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in inet6_if_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); errout: @@ -3520,10 +3515,12 @@ errout: rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); } -/* Maximum length of prefix_cacheinfo attributes */ -#define INET6_PREFIX_RTA_SPACE \ - RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ - RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ +static inline size_t inet6_prefix_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct prefixmsg)) + + nla_total_size(sizeof(struct in6_addr)) + + nla_total_size(sizeof(struct prefix_cacheinfo)); +} static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, struct prefix_info *pinfo, u32 pid, u32 seq, @@ -3569,18 +3566,15 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, struct prefix_info *pinfo) { struct sk_buff *skb; - int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE; int err = -ENOBUFS; - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); + skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in inet6_prefix_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); errout: diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 25804cb69cf0..d587dde5897e 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -232,6 +232,12 @@ static u32 fib6_rule_default_pref(void) return 0x3FFF; } +static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) +{ + return nla_total_size(16) /* dst */ + + nla_total_size(16); /* src */ +} + static struct fib_rules_ops fib6_rules_ops = { .family = AF_INET6, .rule_size = sizeof(struct fib6_rule), @@ -241,6 +247,7 @@ static struct fib_rules_ops fib6_rules_ops = { .compare = fib6_rule_compare, .fill = fib6_rule_fill, .default_pref = fib6_rule_default_pref, + .nlmsg_payload = fib6_rule_nlmsg_payload, .nlgroup = RTNLGRP_IPV6_RULE, .policy = fib6_rule_policy, .rules_list = &fib6_rules, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0ad07c9087a7..a6472cb9054c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2006,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) return ip6_route_add(&cfg); } +static inline size_t rt6_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct rtmsg)) + + nla_total_size(16) /* RTA_SRC */ + + nla_total_size(16) /* RTA_DST */ + + nla_total_size(16) /* RTA_GATEWAY */ + + nla_total_size(16) /* RTA_PREFSRC */ + + nla_total_size(4) /* RTA_TABLE */ + + nla_total_size(4) /* RTA_IIF */ + + nla_total_size(4) /* RTA_OIF */ + + nla_total_size(4) /* RTA_PRIORITY */ + + nla_total_size(sizeof(struct rta_cacheinfo)); +} + static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, struct in6_addr *dst, struct in6_addr *src, int iif, int type, u32 pid, u32 seq, @@ -2200,7 +2214,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) struct sk_buff *skb; u32 pid = 0, seq = 0; struct nlmsghdr *nlh = NULL; - int payload = sizeof(struct rtmsg) + 256; int err = -ENOBUFS; if (info) { @@ -2210,15 +2223,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) seq = nlh->nlmsg_seq; } - skb = nlmsg_new(nlmsg_total_size(payload), gfp_any()); + skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); if (skb == NULL) goto errout; err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in rt6_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); errout: diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index a6ce1d6d5c59..f1788bd290f8 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -452,7 +452,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) } list_start: - ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL); if (ans_skb == NULL) { ret_val = -ENOMEM; goto list_failure; diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 53c9079ad2c3..c529622ff0b7 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -356,7 +356,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) void *data; struct netlbl_dom_map *entry; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; data = netlbl_netlink_hdr_put(ans_skb, @@ -492,7 +492,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) struct sk_buff *ans_skb = NULL; void *data; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; data = netlbl_netlink_hdr_put(ans_skb, diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 1833ad233b39..219dccade4e1 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -138,7 +138,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) struct sk_buff *ans_skb; void *data; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) goto list_failure; data = netlbl_netlink_hdr_put(ans_skb, diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d527c8977b1f..f61d81b3c61c 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1148,7 +1148,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; - skb = nlmsg_new(len, GFP_KERNEL); + skb = alloc_skb(len, GFP_KERNEL); if (skb==NULL) goto out; @@ -1435,14 +1435,13 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) struct sk_buff *skb; struct nlmsghdr *rep; struct nlmsgerr *errmsg; - int size; + size_t payload = sizeof(*errmsg); - if (err == 0) - size = nlmsg_total_size(sizeof(*errmsg)); - else - size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh)); + /* error messages get the original request appened */ + if (err) + payload += nlmsg_len(nlh); - skb = nlmsg_new(size, GFP_KERNEL); + skb = nlmsg_new(payload, GFP_KERNEL); if (!skb) { struct sock *sk; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 49bc2db7982b..70d60c818897 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -480,7 +480,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid, struct sk_buff *skb; int err; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (skb == NULL) return ERR_PTR(-ENOBUFS); -- cgit v1.2.3-70-g09d2 From f465e489c457821751f6253abaaf28c10f9d8895 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 10 Nov 2006 14:11:04 -0800 Subject: [IPv6] rules: Remove bogus tos validation check Noticed by Al Viro: (frh->tos & ~IPV6_FLOWINFO_MASK)) where IPV6_FLOWINFO_MASK is htonl(0xfffffff) and frh->tos is u8, which makes no sense here... Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/ipv6/fib6_rules.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index d587dde5897e..0862809ffcf7 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -142,8 +142,7 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, int err = -EINVAL; struct fib6_rule *rule6 = (struct fib6_rule *) rule; - if (frh->src_len > 128 || frh->dst_len > 128 || - (frh->tos & ~IPV6_FLOWINFO_MASK)) + if (frh->src_len > 128 || frh->dst_len > 128) goto errout; if (rule->action == FR_ACT_TO_TBL) { -- cgit v1.2.3-70-g09d2 From d3a1be9cba86c4385a5fe46673bbb4730551f454 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Fri, 10 Nov 2006 14:54:51 -0800 Subject: [IPv6]: Only modify checksum for UDP Only change upper-layer checksum from 0 to 0xFFFF for UDP (as RFC 768 states), not for others as RFC 4443 doesn't require it. Signed-off-by: Brian Haley Signed-off-by: David S. Miller --- net/ipv6/icmp.c | 2 -- net/ipv6/raw.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 52cca93ff2f8..bd51847acd57 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -247,8 +247,6 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct len, fl->proto, tmp_csum); icmp6h->icmp6_cksum = tmp_csum; } - if (icmp6h->icmp6_cksum == 0) - icmp6h->icmp6_cksum = -1; ip6_push_pending_frames(sk); out: return err; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 18a90075f942..813fa1d96862 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -536,7 +536,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, &fl->fl6_dst, total_len, fl->proto, tmp_csum); - if (tmp_csum == 0) + if (tmp_csum == 0 && fl->proto == IPPROTO_UDP) tmp_csum = -1; csum = tmp_csum; -- cgit v1.2.3-70-g09d2 From 2404043a665a9f4c748ab81eef29c76b3e443801 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 10 Nov 2006 15:01:14 -0800 Subject: [TCP] htcp: Better packing of struct htcp. Based upon a patch by Joe Perches. Signed-off-by: David S. Miller --- net/ipv4/tcp_htcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 283be3cb4667..753987a1048f 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -26,12 +26,12 @@ struct htcp { u32 alpha; /* Fixed point arith, << 7 */ u8 beta; /* Fixed point arith, << 7 */ u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */ - u32 last_cong; /* Time since last congestion event end */ - u32 undo_last_cong; u16 pkts_acked; u32 packetcount; u32 minRTT; u32 maxRTT; + u32 last_cong; /* Time since last congestion event end */ + u32 undo_last_cong; u32 undo_maxRTT; u32 undo_old_maxB; -- cgit v1.2.3-70-g09d2 From 75356f27ed4f85bd789a822bca3fc5e92e334140 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 12 Nov 2006 23:02:01 -0800 Subject: [DECNET]: Fix build regressions. Spotted by Arnaldo. Signed-off-by: David S. Miller --- net/decnet/dn_rules.c | 6 ------ net/decnet/dn_table.c | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index b7dfd04a9638..e32d0c3d5a96 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -241,12 +241,6 @@ static u32 dn_fib_rule_default_pref(void) return 0; } -static size_t dn_fib_rule_nlmsg_payload(struct fib_rule *rule) -{ - return nla_total_size(2) /* dst */ - + nla_total_size(2); /* src */ -} - int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) { return fib_rules_dump(skb, cb, AF_DECnet); diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index e74b744254ab..9ce58c24a8d3 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -265,7 +265,7 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi) { - size_t payload = NLMSG_ALIGN(struct rtmsg) + size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg)) + nla_total_size(4) /* RTA_TABLE */ + nla_total_size(2) /* RTA_DST */ + nla_total_size(4); /* RTA_PRIORITY */ @@ -361,7 +361,7 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id, u32 pid = req ? req->pid : 0; int err = -ENOBUFS; - skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f), GFP_KERNEL)); + skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL); if (skb == NULL) goto errout; -- cgit v1.2.3-70-g09d2 From 08a29e41bb6d6516b0f65e19381f537168d1768e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:07:51 -0200 Subject: [DCCP]: Update comments on precisely which packets can be retransmitted This updates program documentation: spell out precise conditions about which packets are eligible for retransmission (which is actually quite hard to extract from RFC 4340). It is based on the following table derived from RFC 4340: +-----------+---------------------------------+---------------------+ | Type | Retransmit? | Remark | +-----------+---------------------------------+---------------------+ | Request | in client-REQUEST state | sec. 8.1.1 | | Response | NEVER | SHOULD NOT, 8.1.3 | | Data | NEVER | unreliable protocol | | Ack | possible in client-PARTOPEN | sec. 8.1.5 | | DataAck | NEVER | unreliable protocol | | CloseReq | only in server-CLOSEREQ state | MUST, sec. 8.3 | | Close | in node-CLOSING state | MUST, sec. 8.3 | +-----------+-------------------------------------------------------+ | Reset | only in response to other packets | | Sync | only in response to sequence-invalid packets (7.5.4) | | SyncAck | only in response to Sync packets | +-----------+-------------------------------------------------------+ Hence the only packets eligible for retransmission are: * Requests in client-REQUEST state (sec. 8.1.1) * Acks in client-PARTOPEN state (sec. 8.1.5) * CloseReq in server-CLOSEREQ state (sec. 8.3) * Close in node-CLOSING state (sec. 8.3) I had meant to put in a check for these types too, but have left that for later. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/timer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/dccp/timer.c b/net/dccp/timer.c index 8447742f5615..bda0af639ae4 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -142,7 +142,7 @@ static void dccp_retransmit_timer(struct sock *sk) /* retransmit timer is used for feature negotiation throughout * connection. In this case, no packet is re-transmitted, but rather an - * ack is generated and pending changes are splaced into its options. + * ack is generated and pending changes are placed into its options. */ if (sk->sk_send_head == NULL) { dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk); @@ -154,9 +154,11 @@ static void dccp_retransmit_timer(struct sock *sk) /* * sk->sk_send_head has to have one skb with * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP - * packet types (REQUEST, RESPONSE, the ACK in the 3way handshake - * (PARTOPEN timer), etc). - */ + * packet types. The only packets eligible for retransmission are: + * -- Requests in client-REQUEST state (sec. 8.1.1) + * -- Acks in client-PARTOPEN state (sec. 8.1.5) + * -- CloseReq in server-CLOSEREQ state (sec. 8.3) + * -- Close in node-CLOSING state (sec. 8.3) */ BUG_TRAP(sk->sk_send_head != NULL); /* -- cgit v1.2.3-70-g09d2 From e11d9d30802278af22e78d8c10f348b683670cd9 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:12:07 -0200 Subject: [DCCP]: Increment sequence numbers on retransmitted Response packets Problem: --- net/dccp/minisocks.c | 16 +++++++++------- net/dccp/output.c | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index d3de696fe4bf..5b2773efd7c7 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -196,15 +196,17 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, /* Check for retransmitted REQUEST */ if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) { - if (after48(DCCP_SKB_CB(skb)->dccpd_seq, - dccp_rsk(req)->dreq_isr)) { - struct dccp_request_sock *dreq = dccp_rsk(req); + struct dccp_request_sock *dreq = dccp_rsk(req); + if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_isr)) { dccp_pr_debug("Retransmitted REQUEST\n"); - /* Send another RESPONSE packet */ - dccp_set_seqno(&dreq->dreq_iss, dreq->dreq_iss + 1); - dccp_set_seqno(&dreq->dreq_isr, - DCCP_SKB_CB(skb)->dccpd_seq); + dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; + /* + * Send another RESPONSE packet + * To protect against Request floods, increment retrans + * counter (backoff, monitored by dccp_response_timer). + */ + req->retrans++; req->rsk_ops->rtx_syn_ack(sk, req, NULL); } /* Network Duplicate, discard packet */ diff --git a/net/dccp/output.c b/net/dccp/output.c index 992caedd7725..08ee5547a2f2 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -332,6 +332,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, skb->dst = dst_clone(dst); dreq = dccp_rsk(req); + if (inet_rsk(req)->acked) /* increase ISS upon retransmission */ + dccp_inc_seqno(&dreq->dreq_iss); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; @@ -354,6 +356,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, dccp_csum_outgoing(skb); + /* We use `acked' to remember that a Response was already sent. */ + inet_rsk(req)->acked = 1; DCCP_INC_STATS(DCCP_MIB_OUTSEGS); return skb; } -- cgit v1.2.3-70-g09d2 From 2e2e9e92bd723244ea20fa488b1780111f2b05e1 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:23:52 -0200 Subject: [DCCP]: Add sysctls to control retransmission behaviour This adds 3 sysctls which govern the retransmission behaviour of DCCP control packets (3way handshake, feature negotiation). It removes 4 FIXMEs from the code. The close resemblance of sysctl variables to their TCP analogues is emphasised not only by their name, but also by giving them the same initial values. This is useful since there is not much practical experience with DCCP yet. Furthermore, with regard to the previous patch, it is now possible to limit the number of keepalive-Responses by setting net.dccp.default.request_retries (also a bit like in TCP). Lastly, added documentation of all existing DCCP sysctls. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/networking/dccp.txt | 41 +++++++++++++++++++++++++++++++++++++++ include/linux/sysctl.h | 3 +++ net/dccp/dccp.h | 11 +++++++++++ net/dccp/feat.h | 7 ------- net/dccp/proto.c | 1 + net/dccp/sysctl.c | 25 ++++++++++++++++++++++++ net/dccp/timer.c | 16 +++++++++------ 7 files changed, 91 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index a8142a81038a..c2328c862e98 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -63,6 +63,47 @@ DCCP_SOCKOPT_SEND_CSCOV is for the receiver and has a different meaning: it coverage value are also acceptable. The higher the number, the more restrictive this setting (see [RFC 4340, sec. 9.2.1]). +Sysctl variables +================ +Several DCCP default parameters can be managed by the following sysctls +(sysctl net.dccp.default or /proc/sys/net/dccp/default): + +request_retries + The number of active connection initiation retries (the number of + Requests minus one) before timing out. In addition, it also governs + the behaviour of the other, passive side: this variable also sets + the number of times DCCP repeats sending a Response when the initial + handshake does not progress from RESPOND to OPEN (i.e. when no Ack + is received after the initial Request). This value should be greater + than 0, suggested is less than 10. Analogue of tcp_syn_retries. + +retries1 + How often a DCCP Response is retransmitted until the listening DCCP + side considers its connecting peer dead. Analogue of tcp_retries1. + +retries2 + The number of times a general DCCP packet is retransmitted. This has + importance for retransmitted acknowledgments and feature negotiation, + data packets are never retransmitted. Analogue of tcp_retries2. + +send_ndp = 1 + Whether or not to send NDP count options (sec. 7.7.2). + +send_ackvec = 1 + Whether or not to send Ack Vector options (sec. 11.5). + +ack_ratio = 2 + The default Ack Ratio (sec. 11.3) to use. + +tx_ccid = 2 + Default CCID for the sender-receiver half-connection. + +rx_ccid = 2 + Default CCID for the receiver-sender half-connection. + +seq_window = 100 + The initial sequence window (sec. 7.5.2). + Notes ===== diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 0725441621d0..2e8c5ad82793 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -614,6 +614,9 @@ enum { NET_DCCP_DEFAULT_ACK_RATIO = 4, NET_DCCP_DEFAULT_SEND_ACKVEC = 5, NET_DCCP_DEFAULT_SEND_NDP = 6, + NET_DCCP_DEFAULT_REQ_RETRIES = 7, + NET_DCCP_DEFAULT_RETRIES1 = 8, + NET_DCCP_DEFAULT_RETRIES2 = 9, }; /* /proc/sys/net/ipx */ diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index d5c414bf7819..e7b96074a1b1 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -64,6 +64,17 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); #define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */ +/* sysctl variables for DCCP */ +extern int sysctl_dccp_request_retries; +extern int sysctl_dccp_retries1; +extern int sysctl_dccp_retries2; +extern int dccp_feat_default_sequence_window; +extern int dccp_feat_default_rx_ccid; +extern int dccp_feat_default_tx_ccid; +extern int dccp_feat_default_ack_ratio; +extern int dccp_feat_default_send_ack_vector; +extern int dccp_feat_default_send_ndp_count; + /* is seq1 < seq2 ? */ static inline int before48(const u64 seq1, const u64 seq2) { diff --git a/net/dccp/feat.h b/net/dccp/feat.h index cee553d416ca..6048373c7186 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h @@ -26,11 +26,4 @@ extern void dccp_feat_clean(struct dccp_minisock *dmsk); extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); extern int dccp_feat_init(struct dccp_minisock *dmsk); -extern int dccp_feat_default_sequence_window; -extern int dccp_feat_default_rx_ccid; -extern int dccp_feat_default_tx_ccid; -extern int dccp_feat_default_ack_ratio; -extern int dccp_feat_default_send_ack_vector; -extern int dccp_feat_default_send_ndp_count; - #endif /* _DCCP_FEAT_H */ diff --git a/net/dccp/proto.c b/net/dccp/proto.c index db54e557eff1..9c9c08cffdaf 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -212,6 +212,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) dccp_init_xmit_timers(sk); icsk->icsk_rto = DCCP_TIMEOUT_INIT; + icsk->icsk_syn_retries = sysctl_dccp_request_retries; sk->sk_state = DCCP_CLOSED; sk->sk_write_space = dccp_write_space; icsk->icsk_sync_mss = dccp_sync_mss; diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 38bc157876f3..7b09f2179985 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -11,6 +11,7 @@ #include #include +#include "dccp.h" #include "feat.h" #ifndef CONFIG_SYSCTL @@ -66,6 +67,30 @@ static struct ctl_table dccp_default_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .ctl_name = NET_DCCP_DEFAULT_REQ_RETRIES, + .procname = "request_retries", + .data = &sysctl_dccp_request_retries, + .maxlen = sizeof(sysctl_dccp_request_retries), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_RETRIES1, + .procname = "retries1", + .data = &sysctl_dccp_retries1, + .maxlen = sizeof(sysctl_dccp_retries1), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_RETRIES2, + .procname = "retries2", + .data = &sysctl_dccp_retries2, + .maxlen = sizeof(sysctl_dccp_retries2), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { .ctl_name = 0, } }; diff --git a/net/dccp/timer.c b/net/dccp/timer.c index bda0af639ae4..7b3f16e29a97 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -15,6 +15,11 @@ #include "dccp.h" +/* sysctl variables governing numbers of retransmission attempts */ +int sysctl_dccp_request_retries __read_mostly = TCP_SYN_RETRIES; +int sysctl_dccp_retries1 __read_mostly = TCP_RETR1; +int sysctl_dccp_retries2 __read_mostly = TCP_RETR2; + static void dccp_write_timer(unsigned long data); static void dccp_keepalive_timer(unsigned long data); static void dccp_delack_timer(unsigned long data); @@ -44,11 +49,10 @@ static int dccp_write_timeout(struct sock *sk) if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) { if (icsk->icsk_retransmits != 0) dst_negative_advice(&sk->sk_dst_cache); - retry_until = icsk->icsk_syn_retries ? : - /* FIXME! */ 3 /* FIXME! sysctl_tcp_syn_retries */; + retry_until = icsk->icsk_syn_retries ? + : sysctl_dccp_request_retries; } else { - if (icsk->icsk_retransmits >= - /* FIXME! sysctl_tcp_retries1 */ 5 /* FIXME! */) { + if (icsk->icsk_retransmits >= sysctl_dccp_retries1) { /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black hole detection. :-( @@ -72,7 +76,7 @@ static int dccp_write_timeout(struct sock *sk) dst_negative_advice(&sk->sk_dst_cache); } - retry_until = /* FIXME! */ 15 /* FIXME! sysctl_tcp_retries2 */; + retry_until = sysctl_dccp_retries2; /* * FIXME: see tcp_write_timout and tcp_out_of_resources */ @@ -196,7 +200,7 @@ backoff: icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, DCCP_RTO_MAX); - if (icsk->icsk_retransmits > 3 /* FIXME: sysctl_dccp_retries1 */) + if (icsk->icsk_retransmits > sysctl_dccp_retries1) __sk_dst_reset(sk); out:; } -- cgit v1.2.3-70-g09d2 From afb0a34dd3e20b3f534de19993271b8664cf10bb Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:25:41 -0200 Subject: [DCCP]: Introduce a consistent naming scheme for sysctls In order to make their function clearer and obtain a consistent naming scheme to identify sysctls, all existing DCCP sysctls have been prefixed with `sysctl_dccp', following the same convention as used by TCP. Feature-specific sysctls retain the `feat' in the middle, although the `default' has been dropped, since it is obvious from use. Also removed a duplicate `dccp_feat_default_sequence_window' in ipv4.c. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/dccp.h | 12 ++++++------ net/dccp/ipv4.c | 1 - net/dccp/minisocks.c | 2 +- net/dccp/options.c | 26 +++++++++++++------------- net/dccp/sysctl.c | 24 ++++++++++++------------ 5 files changed, 32 insertions(+), 33 deletions(-) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index e7b96074a1b1..363fa520056e 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -68,12 +68,12 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); extern int sysctl_dccp_request_retries; extern int sysctl_dccp_retries1; extern int sysctl_dccp_retries2; -extern int dccp_feat_default_sequence_window; -extern int dccp_feat_default_rx_ccid; -extern int dccp_feat_default_tx_ccid; -extern int dccp_feat_default_ack_ratio; -extern int dccp_feat_default_send_ack_vector; -extern int dccp_feat_default_send_ndp_count; +extern int sysctl_dccp_feat_sequence_window; +extern int sysctl_dccp_feat_rx_ccid; +extern int sysctl_dccp_feat_tx_ccid; +extern int sysctl_dccp_feat_ack_ratio; +extern int sysctl_dccp_feat_send_ack_vector; +extern int sysctl_dccp_feat_send_ndp_count; /* is seq1 < seq2 ? */ static inline int before48(const u64 seq1, const u64 seq2) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 496112080f3d..84c05405984e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -651,7 +651,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq->loc_addr = skb->nh.iph->daddr; ireq->rmt_addr = skb->nh.iph->saddr; - req->rcv_wnd = dccp_feat_default_sequence_window; ireq->opt = NULL; /* diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 5b2773efd7c7..0c49733f5be1 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -300,7 +300,7 @@ void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb) { inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; inet_rsk(req)->acked = 0; - req->rcv_wnd = dccp_feat_default_sequence_window; + req->rcv_wnd = sysctl_dccp_feat_sequence_window; } EXPORT_SYMBOL_GPL(dccp_reqsk_init); diff --git a/net/dccp/options.c b/net/dccp/options.c index fb0db1f7cd7b..121e794fe454 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -22,23 +22,23 @@ #include "dccp.h" #include "feat.h" -int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; -int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID; -int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID; -int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO; -int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; -int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; +int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; +int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID; +int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID; +int sysctl_dccp_feat_ack_ratio = DCCPF_INITIAL_ACK_RATIO; +int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; +int sysctl_dccp_feat_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; -EXPORT_SYMBOL_GPL(dccp_feat_default_sequence_window); +EXPORT_SYMBOL_GPL(sysctl_dccp_feat_sequence_window); void dccp_minisock_init(struct dccp_minisock *dmsk) { - dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window; - dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid; - dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid; - dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio; - dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector; - dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count; + dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window; + dmsk->dccpms_rx_ccid = sysctl_dccp_feat_rx_ccid; + dmsk->dccpms_tx_ccid = sysctl_dccp_feat_tx_ccid; + dmsk->dccpms_ack_ratio = sysctl_dccp_feat_ack_ratio; + dmsk->dccpms_send_ack_vector = sysctl_dccp_feat_send_ack_vector; + dmsk->dccpms_send_ndp_count = sysctl_dccp_feat_send_ndp_count; } static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 7b09f2179985..8b62061e5701 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -22,48 +22,48 @@ static struct ctl_table dccp_default_table[] = { { .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW, .procname = "seq_window", - .data = &dccp_feat_default_sequence_window, - .maxlen = sizeof(dccp_feat_default_sequence_window), + .data = &sysctl_dccp_feat_sequence_window, + .maxlen = sizeof(sysctl_dccp_feat_sequence_window), .mode = 0644, .proc_handler = proc_dointvec, }, { .ctl_name = NET_DCCP_DEFAULT_RX_CCID, .procname = "rx_ccid", - .data = &dccp_feat_default_rx_ccid, - .maxlen = sizeof(dccp_feat_default_rx_ccid), + .data = &sysctl_dccp_feat_rx_ccid, + .maxlen = sizeof(sysctl_dccp_feat_rx_ccid), .mode = 0644, .proc_handler = proc_dointvec, }, { .ctl_name = NET_DCCP_DEFAULT_TX_CCID, .procname = "tx_ccid", - .data = &dccp_feat_default_tx_ccid, - .maxlen = sizeof(dccp_feat_default_tx_ccid), + .data = &sysctl_dccp_feat_tx_ccid, + .maxlen = sizeof(sysctl_dccp_feat_tx_ccid), .mode = 0644, .proc_handler = proc_dointvec, }, { .ctl_name = NET_DCCP_DEFAULT_ACK_RATIO, .procname = "ack_ratio", - .data = &dccp_feat_default_ack_ratio, - .maxlen = sizeof(dccp_feat_default_ack_ratio), + .data = &sysctl_dccp_feat_ack_ratio, + .maxlen = sizeof(sysctl_dccp_feat_ack_ratio), .mode = 0644, .proc_handler = proc_dointvec, }, { .ctl_name = NET_DCCP_DEFAULT_SEND_ACKVEC, .procname = "send_ackvec", - .data = &dccp_feat_default_send_ack_vector, - .maxlen = sizeof(dccp_feat_default_send_ack_vector), + .data = &sysctl_dccp_feat_send_ack_vector, + .maxlen = sizeof(sysctl_dccp_feat_send_ack_vector), .mode = 0644, .proc_handler = proc_dointvec, }, { .ctl_name = NET_DCCP_DEFAULT_SEND_NDP, .procname = "send_ndp", - .data = &dccp_feat_default_send_ndp_count, - .maxlen = sizeof(dccp_feat_default_send_ndp_count), + .data = &sysctl_dccp_feat_send_ndp_count, + .maxlen = sizeof(sysctl_dccp_feat_send_ndp_count), .mode = 0644, .proc_handler = proc_dointvec, }, -- cgit v1.2.3-70-g09d2 From 4ed800d02cfb639b4f8375a0f0f04f0efea64e7f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:26:51 -0200 Subject: [DCCP]: Remove forward declarations in timer.c This removes 3 forward declarations by reordering 2 functions. No code change at all. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/timer.c | 110 +++++++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 57 deletions(-) (limited to 'net') diff --git a/net/dccp/timer.c b/net/dccp/timer.c index 7b3f16e29a97..e8f519e7f481 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -20,16 +20,6 @@ int sysctl_dccp_request_retries __read_mostly = TCP_SYN_RETRIES; int sysctl_dccp_retries1 __read_mostly = TCP_RETR1; int sysctl_dccp_retries2 __read_mostly = TCP_RETR2; -static void dccp_write_timer(unsigned long data); -static void dccp_keepalive_timer(unsigned long data); -static void dccp_delack_timer(unsigned long data); - -void dccp_init_xmit_timers(struct sock *sk) -{ - inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer, - &dccp_keepalive_timer); -} - static void dccp_write_err(struct sock *sk) { sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT; @@ -90,53 +80,6 @@ static int dccp_write_timeout(struct sock *sk) return 0; } -/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */ -static void dccp_delack_timer(unsigned long data) -{ - struct sock *sk = (struct sock *)data; - struct inet_connection_sock *icsk = inet_csk(sk); - - bh_lock_sock(sk); - if (sock_owned_by_user(sk)) { - /* Try again later. */ - icsk->icsk_ack.blocked = 1; - NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED); - sk_reset_timer(sk, &icsk->icsk_delack_timer, - jiffies + TCP_DELACK_MIN); - goto out; - } - - if (sk->sk_state == DCCP_CLOSED || - !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) - goto out; - if (time_after(icsk->icsk_ack.timeout, jiffies)) { - sk_reset_timer(sk, &icsk->icsk_delack_timer, - icsk->icsk_ack.timeout); - goto out; - } - - icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER; - - if (inet_csk_ack_scheduled(sk)) { - if (!icsk->icsk_ack.pingpong) { - /* Delayed ACK missed: inflate ATO. */ - icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, - icsk->icsk_rto); - } else { - /* Delayed ACK missed: leave pingpong mode and - * deflate ATO. - */ - icsk->icsk_ack.pingpong = 0; - icsk->icsk_ack.ato = TCP_ATO_MIN; - } - dccp_send_ack(sk); - NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS); - } -out: - bh_unlock_sock(sk); - sock_put(sk); -} - /* * The DCCP retransmit timer. */ @@ -270,3 +213,56 @@ out: bh_unlock_sock(sk); sock_put(sk); } + +/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */ +static void dccp_delack_timer(unsigned long data) +{ + struct sock *sk = (struct sock *)data; + struct inet_connection_sock *icsk = inet_csk(sk); + + bh_lock_sock(sk); + if (sock_owned_by_user(sk)) { + /* Try again later. */ + icsk->icsk_ack.blocked = 1; + NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED); + sk_reset_timer(sk, &icsk->icsk_delack_timer, + jiffies + TCP_DELACK_MIN); + goto out; + } + + if (sk->sk_state == DCCP_CLOSED || + !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) + goto out; + if (time_after(icsk->icsk_ack.timeout, jiffies)) { + sk_reset_timer(sk, &icsk->icsk_delack_timer, + icsk->icsk_ack.timeout); + goto out; + } + + icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER; + + if (inet_csk_ack_scheduled(sk)) { + if (!icsk->icsk_ack.pingpong) { + /* Delayed ACK missed: inflate ATO. */ + icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, + icsk->icsk_rto); + } else { + /* Delayed ACK missed: leave pingpong mode and + * deflate ATO. + */ + icsk->icsk_ack.pingpong = 0; + icsk->icsk_ack.ato = TCP_ATO_MIN; + } + dccp_send_ack(sk); + NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS); + } +out: + bh_unlock_sock(sk); + sock_put(sk); +} + +void dccp_init_xmit_timers(struct sock *sk) +{ + inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer, + &dccp_keepalive_timer); +} -- cgit v1.2.3-70-g09d2 From 865e9022d88ceedd89fa1079a6e1f9266ccd3711 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:31:50 -0200 Subject: [DCCP]: Remove redundant statements in init_sequence (ISS) This patch removes the following redundancies: 1) The test skb->protocol == htons(ETH_P_IPV6) in dccp_v6_init_sequence is always true since * dccp_v6_conn_request() is the only calling function * dccp_v6_conn_request() redirects all skb's with ETH_P_IP to dccp_v4_conn_request() 2) The first argument, `struct sock *sk', of dccp_v{4,6}_init_sequence() is never used. (This is similar for tcp_v{4,6}_init_sequence, an analogous patch has been submitted to netdev and merged.) By the way - are the `sport' / `dport' arguments in the right order? I have made them consistent among calls but they seem to be in the reverse order. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv4.c | 5 ++--- net/dccp/ipv6.c | 20 ++++++-------------- 2 files changed, 8 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 84c05405984e..b56a2fa2694a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -366,8 +366,7 @@ void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb) EXPORT_SYMBOL_GPL(dccp_v4_send_check); -static inline u64 dccp_v4_init_sequence(const struct sock *sk, - const struct sk_buff *skb) +static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb) { return secure_dccp_sequence_number(skb->nh.iph->daddr, skb->nh.iph->saddr, @@ -663,7 +662,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) */ dreq = dccp_rsk(req); dreq->dreq_isr = dcb->dccpd_seq; - dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); + dreq->dreq_iss = dccp_v4_init_sequence(skb); dreq->dreq_service = service; if (dccp_v4_send_response(sk, req, NULL)) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 193b946fd039..a08af75ddc9e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -76,20 +76,12 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value, dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); } -static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) +static inline __u32 dccp_v6_init_sequence(const struct sk_buff *skb) { - const struct dccp_hdr *dh = dccp_hdr(skb); - - if (skb->protocol == htons(ETH_P_IPV6)) - return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, - skb->nh.ipv6h->saddr.s6_addr32, - dh->dccph_dport, - dh->dccph_sport); - - return secure_dccp_sequence_number(skb->nh.iph->daddr, - skb->nh.iph->saddr, - dh->dccph_dport, - dh->dccph_sport); + return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, + skb->nh.ipv6h->saddr.s6_addr32, + dccp_hdr(skb)->dccph_dport, + dccp_hdr(skb)->dccph_sport ); } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -491,7 +483,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) */ dreq = dccp_rsk(req); dreq->dreq_isr = dcb->dccpd_seq; - dreq->dreq_iss = dccp_v6_init_sequence(sk, skb); + dreq->dreq_iss = dccp_v6_init_sequence(skb); dreq->dreq_service = service; if (dccp_v6_send_response(sk, req, NULL)) -- cgit v1.2.3-70-g09d2 From d7f7365f5776723da6df73540d855069c2daaa5c Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 13 Nov 2006 13:34:38 -0200 Subject: [DCCPv6]: Choose a genuine initial sequence number This * resolves a FIXME - DCCPv6 connections started all with an initial sequence number of 1; * provides a redirection `secure_dccpv6_sequence_number' in case the init_sequence_v6 code should be updated later; * concentrates the update of S.GAR into dccp_connect_init(); * removes a duplicate dccp_update_gss() in ipv4.c; * uses inet->dport instead of usin->sin_port, due to the following assignment in dccp_v4_connect(): inet->dport = usin->sin_port; Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv4.c | 9 ++------- net/dccp/ipv6.c | 28 ++++++++++++++++------------ net/dccp/output.c | 6 +++++- 3 files changed, 23 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b56a2fa2694a..bc400b2ba25e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -113,13 +113,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) /* OK, now commit destination to socket. */ sk_setup_caps(sk, &rt->u.dst); - dp->dccps_gar = - dp->dccps_iss = secure_dccp_sequence_number(inet->saddr, - inet->daddr, - inet->sport, - usin->sin_port); - dccp_update_gss(sk, dp->dccps_iss); - + dp->dccps_iss = secure_dccp_sequence_number(inet->saddr, inet->daddr, + inet->sport, inet->dport); inet->id = dp->dccps_iss ^ jiffies; err = dccp_connect(sk); diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index a08af75ddc9e..8d6ddb6389a7 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -76,12 +76,19 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value, dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); } -static inline __u32 dccp_v6_init_sequence(const struct sk_buff *skb) +static inline __u32 secure_dccpv6_sequence_number(__u32 *saddr, __u32 *daddr, + __u16 sport, __u16 dport ) { - return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, - skb->nh.ipv6h->saddr.s6_addr32, - dccp_hdr(skb)->dccph_dport, - dccp_hdr(skb)->dccph_sport ); + return secure_tcpv6_sequence_number(saddr, daddr, sport, dport); +} + +static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) +{ + return secure_dccpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, + skb->nh.ipv6h->saddr.s6_addr32, + dccp_hdr(skb)->dccph_dport, + dccp_hdr(skb)->dccph_sport ); + } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -1065,13 +1072,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, err = inet6_hash_connect(&dccp_death_row, sk); if (err) goto late_failure; - /* FIXME */ -#if 0 - dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32, - np->daddr.s6_addr32, - inet->sport, - inet->dport); -#endif + + dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32, + np->daddr.s6_addr32, + inet->sport, inet->dport); err = dccp_connect(sk); if (err) goto late_failure; diff --git a/net/dccp/output.c b/net/dccp/output.c index 08ee5547a2f2..0994b13f0f15 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -448,7 +448,6 @@ static inline void dccp_connect_init(struct sock *sk) dccp_sync_mss(sk, dst_mtu(dst)); - dccp_update_gss(sk, dp->dccps_iss); /* * SWL and AWL are initially adjusted so that they are not less than * the initial Sequence Numbers received and sent, respectively: @@ -457,8 +456,13 @@ static inline void dccp_connect_init(struct sock *sk) * These adjustments MUST be applied only at the beginning of the * connection. */ + dccp_update_gss(sk, dp->dccps_iss); dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss)); + /* S.GAR - greatest valid acknowledgement number received on a non-Sync; + * initialized to S.ISS (sec. 8.5) */ + dp->dccps_gar = dp->dccps_iss; + icsk->icsk_retransmits = 0; init_timer(&dp->dccps_xmit_timer); dp->dccps_xmit_timer.data = (unsigned long)sk; -- cgit v1.2.3-70-g09d2 From 90833aa4f496d69ca374af6acef7d1614c8693ff Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 13 Nov 2006 16:02:22 -0800 Subject: [NET]: The scheduled removal of the frame diverter. This patch contains the scheduled removal of the frame diverter. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 15 - drivers/net/Space.c | 1 - include/linux/Kbuild | 1 - include/linux/divert.h | 132 ------- include/linux/netdevice.h | 6 - include/linux/sockios.h | 4 +- net/Kconfig | 27 -- net/core/Makefile | 1 - net/core/dev.c | 20 +- net/core/dv.c | 546 ----------------------------- net/core/sysctl_net_core.c | 14 - net/socket.c | 6 - 12 files changed, 6 insertions(+), 767 deletions(-) delete mode 100644 include/linux/divert.h delete mode 100644 net/core/dv.c (limited to 'net') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d52c4aaaf17f..b3949cd3d013 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -227,21 +227,6 @@ Who: Patrick McHardy --------------------------- -What: frame diverter -When: November 2006 -Why: The frame diverter is included in most distribution kernels, but is - broken. It does not correctly handle many things: - - IPV6 - - non-linear skb's - - network device RCU on removal - - input frames not correctly checked for protocol errors - It also adds allocation overhead even if not enabled. - It is not clear if anyone is still using it. -Who: Stephen Hemminger - ---------------------------- - - What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment When: October 2008 Why: The stacking of class devices makes these values misleading and diff --git a/drivers/net/Space.c b/drivers/net/Space.c index a67f5efc983f..602ed31a5dd9 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -33,7 +33,6 @@ #include #include #include -#include /* A unified ethernet device probe. This is the easiest way to have every ethernet adaptor have the name "eth[0123...]". diff --git a/include/linux/Kbuild b/include/linux/Kbuild index a1155a2beb32..d7e04689304c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -193,7 +193,6 @@ unifdef-y += cuda.h unifdef-y += cyclades.h unifdef-y += dccp.h unifdef-y += dirent.h -unifdef-y += divert.h unifdef-y += dlm.h unifdef-y += elfcore.h unifdef-y += errno.h diff --git a/include/linux/divert.h b/include/linux/divert.h deleted file mode 100644 index 8fb4e9de6843..000000000000 --- a/include/linux/divert.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Frame Diversion, Benoit Locher - * - * Changes: - * 06/09/2000 BL: initial version - * - */ - -#ifndef _LINUX_DIVERT_H -#define _LINUX_DIVERT_H - -#include - -#define MAX_DIVERT_PORTS 8 /* Max number of ports to divert (tcp, udp) */ - -/* Divertable protocols */ -#define DIVERT_PROTO_NONE 0x0000 -#define DIVERT_PROTO_IP 0x0001 -#define DIVERT_PROTO_ICMP 0x0002 -#define DIVERT_PROTO_TCP 0x0004 -#define DIVERT_PROTO_UDP 0x0008 - -/* - * This is an Ethernet Frame Diverter option block - */ -struct divert_blk -{ - int divert; /* are we active */ - unsigned int protos; /* protocols */ - __u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */ - __u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */ - __u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */ - __u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */ -}; - -/* - * Diversion control block, for configuration with the userspace tool - * divert - */ - -typedef union _divert_cf_arg -{ - __s16 int16; - __u16 uint16; - __s32 int32; - __u32 uint32; - __s64 int64; - __u64 uint64; - void __user *ptr; -} divert_cf_arg; - - -struct divert_cf -{ - int cmd; /* Command */ - divert_cf_arg arg1, - arg2, - arg3; - int dev_index; /* device index (eth0=0, etc...) */ -}; - - -/* Diversion commands */ -#define DIVCMD_DIVERT 1 /* ENABLE/DISABLE diversion */ -#define DIVCMD_IP 2 /* ENABLE/DISABLE whold IP diversion */ -#define DIVCMD_TCP 3 /* ENABLE/DISABLE whold TCP diversion */ -#define DIVCMD_TCPDST 4 /* ADD/REMOVE TCP DST port for diversion */ -#define DIVCMD_TCPSRC 5 /* ADD/REMOVE TCP SRC port for diversion */ -#define DIVCMD_UDP 6 /* ENABLE/DISABLE whole UDP diversion */ -#define DIVCMD_UDPDST 7 /* ADD/REMOVE UDP DST port for diversion */ -#define DIVCMD_UDPSRC 8 /* ADD/REMOVE UDP SRC port for diversion */ -#define DIVCMD_ICMP 9 /* ENABLE/DISABLE whole ICMP diversion */ -#define DIVCMD_GETSTATUS 10 /* GET the status of the diverter */ -#define DIVCMD_RESET 11 /* Reset the diverter on the specified dev */ -#define DIVCMD_GETVERSION 12 /* Retrieve the diverter code version (char[32]) */ - -/* General syntax of the commands: - * - * DIVCMD_xxxxxx(arg1, arg2, arg3, dev_index) - * - * SIOCSIFDIVERT: - * DIVCMD_DIVERT(DIVARG1_ENABLE|DIVARG1_DISABLE, , ,ifindex) - * DIVCMD_IP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_TCP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_TCPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_TCPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_UDP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_UDPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_UDPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_ICMP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_RESET(, , , ifindex) - * - * SIOGIFDIVERT: - * DIVCMD_GETSTATUS(divert_blk, , , ifindex) - * DIVCMD_GETVERSION(string[3]) - */ - - -/* Possible values for arg1 */ -#define DIVARG1_ENABLE 0 /* ENABLE something */ -#define DIVARG1_DISABLE 1 /* DISABLE something */ -#define DIVARG1_ADD 2 /* ADD something */ -#define DIVARG1_REMOVE 3 /* REMOVE something */ - - -#ifdef __KERNEL__ - -/* diverter functions */ -#include - -#ifdef CONFIG_NET_DIVERT -#include - -int alloc_divert_blk(struct net_device *); -void free_divert_blk(struct net_device *); -int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg); -void divert_frame(struct sk_buff *skb); -static inline void handle_diverter(struct sk_buff *skb) -{ - /* if diversion is supported on device, then divert */ - if (skb->dev->divert && skb->dev->divert->divert) - divert_frame(skb); -} - -#else -# define alloc_divert_blk(dev) (0) -# define free_divert_blk(dev) do {} while (0) -# define divert_ioctl(cmd, arg) (-ENOPKG) -# define handle_diverter(skb) do {} while (0) -#endif -#endif -#endif /* _LINUX_DIVERT_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 83b8c4f1d69d..4e967b2e22cc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -38,7 +38,6 @@ #include #include -struct divert_blk; struct vlan_group; struct ethtool_ops; struct netpoll_info; @@ -517,11 +516,6 @@ struct net_device /* bridge stuff */ struct net_bridge_port *br_port; -#ifdef CONFIG_NET_DIVERT - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; -#endif /* CONFIG_NET_DIVERT */ - /* class/net/name entry */ struct class_device class_dev; /* space for optional statistics and wireless sysfs groups */ diff --git a/include/linux/sockios.h b/include/linux/sockios.h index e6b9d1d36ea2..abef7596655a 100644 --- a/include/linux/sockios.h +++ b/include/linux/sockios.h @@ -72,8 +72,8 @@ #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ -#define SIOCGIFDIVERT 0x8944 /* Frame diversion support */ -#define SIOCSIFDIVERT 0x8945 /* Set frame diversion options */ +/* SIOCGIFDIVERT was: 0x8944 Frame diversion support */ +/* SIOCSIFDIVERT was: 0x8945 Set frame diversion options */ #define SIOCETHTOOL 0x8946 /* Ethtool interface */ diff --git a/net/Kconfig b/net/Kconfig index 67e39ad8b8b6..867f95032513 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -175,33 +175,6 @@ source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" - -config NET_DIVERT - bool "Frame Diverter (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN - ---help--- - The Frame Diverter allows you to divert packets from the - network, that are not aimed at the interface receiving it (in - promisc. mode). Typically, a Linux box setup as an Ethernet bridge - with the Frames Diverter on, can do some *really* transparent www - caching using a Squid proxy for example. - - This is very useful when you don't want to change your router's - config (or if you simply don't have access to it). - - The other possible usages of diverting Ethernet Frames are - numberous: - - reroute smtp traffic to another interface - - traffic-shape certain network streams - - transparently proxy smtp connections - - etc... - - For more informations, please refer to: - - - - If unsure, say N. - source "net/econet/Kconfig" source "net/wanrouter/Kconfig" source "net/sched/Kconfig" diff --git a/net/core/Makefile b/net/core/Makefile index 119568077dab..73272d506e93 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -12,7 +12,6 @@ obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ obj-$(CONFIG_XFRM) += flow.o obj-$(CONFIG_SYSFS) += net-sysfs.o -obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_WIRELESS_EXT) += wireless.o obj-$(CONFIG_NETPOLL) += netpoll.o diff --git a/net/core/dev.c b/net/core/dev.c index 411c2428d268..5bf13b132dd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -98,7 +98,6 @@ #include #include #include -#include #include #include #include @@ -1827,8 +1826,6 @@ int netif_receive_skb(struct sk_buff *skb) ncls: #endif - handle_diverter(skb); - if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) goto out; @@ -2898,10 +2895,6 @@ int register_netdevice(struct net_device *dev) spin_lock_init(&dev->ingress_lock); #endif - ret = alloc_divert_blk(dev); - if (ret) - goto out; - dev->iflink = -1; /* Init, if this function is available */ @@ -2910,13 +2903,13 @@ int register_netdevice(struct net_device *dev) if (ret) { if (ret > 0) ret = -EIO; - goto out_err; + goto out; } } if (!dev_valid_name(dev->name)) { ret = -EINVAL; - goto out_err; + goto out; } dev->ifindex = dev_new_index(); @@ -2930,7 +2923,7 @@ int register_netdevice(struct net_device *dev) = hlist_entry(p, struct net_device, name_hlist); if (!strncmp(d->name, dev->name, IFNAMSIZ)) { ret = -EEXIST; - goto out_err; + goto out; } } @@ -2974,7 +2967,7 @@ int register_netdevice(struct net_device *dev) ret = netdev_register_sysfs(dev); if (ret) - goto out_err; + goto out; dev->reg_state = NETREG_REGISTERED; /* @@ -3001,9 +2994,6 @@ int register_netdevice(struct net_device *dev) out: return ret; -out_err: - free_divert_blk(dev); - goto out; } /** @@ -3320,8 +3310,6 @@ int unregister_netdevice(struct net_device *dev) /* Notifier chain MUST detach us from master device. */ BUG_TRAP(!dev->master); - free_divert_blk(dev); - /* Finish processing unregister after unlock */ net_set_todo(dev); diff --git a/net/core/dv.c b/net/core/dv.c deleted file mode 100644 index 29ee77f15932..000000000000 --- a/net/core/dv.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Generic frame diversion - * - * Authors: - * Benoit LOCHER: initial integration within the kernel with support for ethernet - * Dave Miller: improvement on the code (correctness, performance and source files) - * - */ -#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 - -const char sysctl_divert_version[32]="0.46"; /* Current version */ - -static int __init dv_init(void) -{ - return 0; -} -module_init(dv_init); - -/* - * Allocate a divert_blk for a device. This must be an ethernet nic. - */ -int alloc_divert_blk(struct net_device *dev) -{ - int alloc_size = (sizeof(struct divert_blk) + 3) & ~3; - - dev->divert = NULL; - if (dev->type == ARPHRD_ETHER) { - dev->divert = kzalloc(alloc_size, GFP_KERNEL); - if (dev->divert == NULL) { - printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", - dev->name); - return -ENOMEM; - } - dev_hold(dev); - } - - return 0; -} - -/* - * Free a divert_blk allocated by the above function, if it was - * allocated on that device. - */ -void free_divert_blk(struct net_device *dev) -{ - if (dev->divert) { - kfree(dev->divert); - dev->divert=NULL; - dev_put(dev); - } -} - -/* - * Adds a tcp/udp (source or dest) port to an array - */ -static int add_port(u16 ports[], u16 port) -{ - int i; - - if (port == 0) - return -EINVAL; - - /* Storing directly in network format for performance, - * thanks Dave :) - */ - port = htons(port); - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == port) - return -EALREADY; - } - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == 0) { - ports[i] = port; - return 0; - } - } - - return -ENOBUFS; -} - -/* - * Removes a port from an array tcp/udp (source or dest) - */ -static int remove_port(u16 ports[], u16 port) -{ - int i; - - if (port == 0) - return -EINVAL; - - /* Storing directly in network format for performance, - * thanks Dave ! - */ - port = htons(port); - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == port) { - ports[i] = 0; - return 0; - } - } - - return -EINVAL; -} - -/* Some basic sanity checks on the arguments passed to divert_ioctl() */ -static int check_args(struct divert_cf *div_cf, struct net_device **dev) -{ - char devname[32]; - int ret; - - if (dev == NULL) - return -EFAULT; - - /* GETVERSION: all other args are unused */ - if (div_cf->cmd == DIVCMD_GETVERSION) - return 0; - - /* Network device index should reasonably be between 0 and 1000 :) */ - if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) - return -EINVAL; - - /* Let's try to find the ifname */ - sprintf(devname, "eth%d", div_cf->dev_index); - *dev = dev_get_by_name(devname); - - /* dev should NOT be null */ - if (*dev == NULL) - return -EINVAL; - - ret = 0; - - /* user issuing the ioctl must be a super one :) */ - if (!capable(CAP_SYS_ADMIN)) { - ret = -EPERM; - goto out; - } - - /* Device must have a divert_blk member NOT null */ - if ((*dev)->divert == NULL) - ret = -EINVAL; -out: - dev_put(*dev); - return ret; -} - -/* - * control function of the diverter - */ -#if 0 -#define DVDBG(a) \ - printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a)) -#else -#define DVDBG(a) -#endif - -int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg) -{ - struct divert_cf div_cf; - struct divert_blk *div_blk; - struct net_device *dev; - int ret; - - switch (cmd) { - case SIOCGIFDIVERT: - DVDBG("SIOCGIFDIVERT, copy_from_user"); - if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) - return -EFAULT; - DVDBG("before check_args"); - ret = check_args(&div_cf, &dev); - if (ret) - return ret; - DVDBG("after checkargs"); - div_blk = dev->divert; - - DVDBG("befre switch()"); - switch (div_cf.cmd) { - case DIVCMD_GETSTATUS: - /* Now, just give the user the raw divert block - * for him to play with :) - */ - if (copy_to_user(div_cf.arg1.ptr, dev->divert, - sizeof(struct divert_blk))) - return -EFAULT; - break; - - case DIVCMD_GETVERSION: - DVDBG("GETVERSION: checking ptr"); - if (div_cf.arg1.ptr == NULL) - return -EINVAL; - DVDBG("GETVERSION: copying data to userland"); - if (copy_to_user(div_cf.arg1.ptr, - sysctl_divert_version, 32)) - return -EFAULT; - DVDBG("GETVERSION: data copied"); - break; - - default: - return -EINVAL; - } - - break; - - case SIOCSIFDIVERT: - if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) - return -EFAULT; - - ret = check_args(&div_cf, &dev); - if (ret) - return ret; - - div_blk = dev->divert; - - switch(div_cf.cmd) { - case DIVCMD_RESET: - div_blk->divert = 0; - div_blk->protos = DIVERT_PROTO_NONE; - memset(div_blk->tcp_dst, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->tcp_src, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->udp_dst, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->udp_src, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - return 0; - - case DIVCMD_DIVERT: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->divert) - return -EALREADY; - div_blk->divert = 1; - break; - - case DIVARG1_DISABLE: - if (!div_blk->divert) - return -EALREADY; - div_blk->divert = 0; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_IP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_IP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_IP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_IP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_IP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_TCP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_TCP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_TCP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_TCP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCPDST: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->tcp_dst, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->tcp_dst, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCPSRC: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->tcp_src, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->tcp_src, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_UDP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_UDP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_UDP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_UDP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDPDST: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->udp_dst, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->udp_dst, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDPSRC: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->udp_src, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->udp_src, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_ICMP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_ICMP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_ICMP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_ICMP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_ICMP; - break; - - default: - return -EINVAL; - } - - break; - - default: - return -EINVAL; - } - - break; - - default: - return -EINVAL; - } - - return 0; -} - - -/* - * Check if packet should have its dest mac address set to the box itself - * for diversion - */ - -#define ETH_DIVERT_FRAME(skb) \ - memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \ - skb->pkt_type=PACKET_HOST - -void divert_frame(struct sk_buff *skb) -{ - struct ethhdr *eth = eth_hdr(skb); - struct iphdr *iph; - struct tcphdr *tcph; - struct udphdr *udph; - struct divert_blk *divert = skb->dev->divert; - int i, src, dst; - unsigned char *skb_data_end = skb->data + skb->len; - - /* Packet is already aimed at us, return */ - if (!compare_ether_addr(eth->h_dest, skb->dev->dev_addr)) - return; - - /* proto is not IP, do nothing */ - if (eth->h_proto != htons(ETH_P_IP)) - return; - - /* Divert all IP frames ? */ - if (divert->protos & DIVERT_PROTO_IP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP frame (thanks Dave) */ - iph = (struct iphdr *) skb->data; - if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) { - printk(KERN_INFO "divert: malformed IP packet !\n"); - return; - } - - switch (iph->protocol) { - /* Divert all ICMP frames ? */ - case IPPROTO_ICMP: - if (divert->protos & DIVERT_PROTO_ICMP) { - ETH_DIVERT_FRAME(skb); - return; - } - break; - - /* Divert all TCP frames ? */ - case IPPROTO_TCP: - if (divert->protos & DIVERT_PROTO_TCP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP - * frame (thanx Dave) - */ - tcph = (struct tcphdr *) - (((unsigned char *)iph) + (iph->ihl<<2)); - if (((unsigned char *)(tcph+1)) >= skb_data_end) { - printk(KERN_INFO "divert: malformed TCP packet !\n"); - return; - } - - /* Divert some tcp dst/src ports only ?*/ - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - dst = divert->tcp_dst[i]; - src = divert->tcp_src[i]; - if ((dst && dst == tcph->dest) || - (src && src == tcph->source)) { - ETH_DIVERT_FRAME(skb); - return; - } - } - break; - - /* Divert all UDP frames ? */ - case IPPROTO_UDP: - if (divert->protos & DIVERT_PROTO_UDP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP - * packet (thanks Dave) - */ - udph = (struct udphdr *) - (((unsigned char *)iph) + (iph->ihl<<2)); - if (((unsigned char *)(udph+1)) >= skb_data_end) { - printk(KERN_INFO - "divert: malformed UDP packet !\n"); - return; - } - - /* Divert some udp dst/src ports only ? */ - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - dst = divert->udp_dst[i]; - src = divert->udp_src[i]; - if ((dst && dst == udph->dest) || - (src && src == udph->source)) { - ETH_DIVERT_FRAME(skb); - return; - } - } - break; - } -} diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 02534131d88e..1e75b1585460 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -21,10 +21,6 @@ extern __u32 sysctl_rmem_max; extern int sysctl_core_destroy_delay; -#ifdef CONFIG_NET_DIVERT -extern char sysctl_divert_version[]; -#endif /* CONFIG_NET_DIVERT */ - #ifdef CONFIG_XFRM extern u32 sysctl_xfrm_aevent_etime; extern u32 sysctl_xfrm_aevent_rseqth; @@ -105,16 +101,6 @@ ctl_table core_table[] = { .mode = 0644, .proc_handler = &proc_dointvec }, -#ifdef CONFIG_NET_DIVERT - { - .ctl_name = NET_CORE_DIVERT_VERSION, - .procname = "divert_version", - .data = (void *)sysctl_divert_version, - .maxlen = 32, - .mode = 0444, - .proc_handler = &proc_dostring - }, -#endif /* CONFIG_NET_DIVERT */ #ifdef CONFIG_XFRM { .ctl_name = NET_CORE_AEVENT_ETIME, diff --git a/net/socket.c b/net/socket.c index 6c9b9b326d76..e8db54702a69 100644 --- a/net/socket.c +++ b/net/socket.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include @@ -852,11 +851,6 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) err = vlan_ioctl_hook(argp); mutex_unlock(&vlan_ioctl_mutex); break; - case SIOCGIFDIVERT: - case SIOCSIFDIVERT: - /* Convert this to call through a hook */ - err = divert_ioctl(cmd, argp); - break; case SIOCADDDLCI: case SIOCDELDLCI: err = -ENOPKG; -- cgit v1.2.3-70-g09d2 From 1ed176a801b83915b7c8ab80e0a2a6376a2d6051 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 13 Nov 2006 16:19:07 -0800 Subject: [SCTP]: Cleanup of the sctp state table code. I noticed an insane high density of repeated characters fixable by a simple regular expression: % s/{.fn = \([^,]*\),[[:space:]]\+\(\\\n[[:space:]]\+\)\?.name = "\1"}/TYPE_SCTP_FUNC(\1)/g (NOTE: the .name for .fn = sctp_sf_do_9_2_start_shutdown didn't match) Signed-off-by: Peter Zijlstra Signed-off-by: David S. Miller --- net/sctp/sm_statetable.c | 696 +++++++++++++++++++++++------------------------ 1 file changed, 335 insertions(+), 361 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 8bcca5676151..733dd87b3a7d 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -104,325 +104,322 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, }; } +#define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} + #define TYPE_SCTP_DATA { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_data_6_2), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_data_6_2), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_eat_data_fast_4_4, .name = "sctp_sf_eat_data_fast_4_4"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_data_fast_4_4), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_DATA */ #define TYPE_SCTP_INIT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_do_5_1B_init, .name = "sctp_sf_do_5_1B_init"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_1B_init), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_1_siminit), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_1_siminit), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_2_dupinit), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_do_9_2_reshutack, .name = "sctp_sf_do_9_2_reshutack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_reshutack), \ } /* TYPE_SCTP_INIT */ #define TYPE_SCTP_INIT_ACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_5_1C_ack, .name = "sctp_sf_do_5_1C_ack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_1C_ack), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_INIT_ACK */ #define TYPE_SCTP_SACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_sack_6_2), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_SACK */ #define TYPE_SCTP_HEARTBEAT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ /* This should not happen, but we are nice. */ \ - {.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_beat_8_3), \ } /* TYPE_SCTP_HEARTBEAT */ #define TYPE_SCTP_HEARTBEAT_ACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \ + TYPE_SCTP_FUNC(sctp_sf_violation), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_backbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_HEARTBEAT_ACK */ #define TYPE_SCTP_ABORT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_pdiscard, .name = "sctp_sf_pdiscard"}, \ + TYPE_SCTP_FUNC(sctp_sf_pdiscard), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_cookie_wait_abort, .name = "sctp_sf_cookie_wait_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_wait_abort), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_cookie_echoed_abort, \ - .name = "sctp_sf_cookie_echoed_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_abort), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_1_abort), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_shutdown_pending_abort, \ - .name = "sctp_sf_shutdown_pending_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_pending_abort), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_shutdown_sent_abort, \ - .name = "sctp_sf_shutdown_sent_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_sent_abort), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_1_abort), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_shutdown_ack_sent_abort, \ - .name = "sctp_sf_shutdown_ack_sent_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_ack_sent_abort), \ } /* TYPE_SCTP_ABORT */ #define TYPE_SCTP_SHUTDOWN { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_9_2_shutdown, .name = "sctp_sf_do_9_2_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_9_2_shutdown_ack, \ - .name = "sctp_sf_do_9_2_shutdown_ack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_SHUTDOWN */ #define TYPE_SCTP_SHUTDOWN_ACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_8_5_1_E_sa), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_8_5_1_E_sa, .name = "sctp_sf_do_8_5_1_E_sa"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_8_5_1_E_sa), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \ + TYPE_SCTP_FUNC(sctp_sf_violation), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \ + TYPE_SCTP_FUNC(sctp_sf_violation), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_final), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \ + TYPE_SCTP_FUNC(sctp_sf_violation), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_final), \ } /* TYPE_SCTP_SHUTDOWN_ACK */ #define TYPE_SCTP_ERROR { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_cookie_echoed_err, .name = "sctp_sf_cookie_echoed_err"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_err), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \ + TYPE_SCTP_FUNC(sctp_sf_operr_notify), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \ + TYPE_SCTP_FUNC(sctp_sf_operr_notify), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \ + TYPE_SCTP_FUNC(sctp_sf_operr_notify), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_ERROR */ #define TYPE_SCTP_COOKIE_ECHO { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_do_5_1D_ce, .name = "sctp_sf_do_5_1D_ce"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_1D_ce), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_2_4_dupcook), \ } /* TYPE_SCTP_COOKIE_ECHO */ #define TYPE_SCTP_COOKIE_ACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_5_1E_ca, .name = "sctp_sf_do_5_1E_ca"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_5_1E_ca), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_COOKIE_ACK */ #define TYPE_SCTP_ECN_ECNE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecne), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecne), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecne), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecne), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecne), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_ECN_ECNE */ #define TYPE_SCTP_ECN_CWR { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_ecn_cwr), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_ECN_CWR */ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_do_4_C, .name = "sctp_sf_do_4_C"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_4_C), \ } /* TYPE_SCTP_SHUTDOWN_COMPLETE */ /* The primary index for this table is the chunk type. @@ -450,44 +447,44 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][ #define TYPE_SCTP_ASCONF { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_asconf, .name = "sctp_sf_do_asconf"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_asconf), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_ASCONF */ #define TYPE_SCTP_ASCONF_ACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_asconf_ack, .name = "sctp_sf_do_asconf_ack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_asconf_ack), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_ASCONF_ACK */ /* The primary index for this table is the chunk type. @@ -500,23 +497,23 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_ #define TYPE_SCTP_FWD_TSN { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ + TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_eat_fwd_tsn, .name = "sctp_sf_eat_fwd_tsn"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_eat_fwd_tsn, .name = "sctp_sf_eat_fwd_tsn"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_eat_fwd_tsn_fast, .name = "sctp_sf_eat_fwd_tsn_fast"}, \ + TYPE_SCTP_FUNC(sctp_sf_eat_fwd_tsn_fast), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ } /* TYPE_SCTP_FWD_TSN */ /* The primary index for this table is the chunk type. @@ -529,167 +526,150 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN static const sctp_sm_table_entry_t chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { /* SCTP_STATE_EMPTY */ - {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, + TYPE_SCTP_FUNC(sctp_sf_ootb), /* SCTP_STATE_CLOSED */ - {.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), /* SCTP_STATE_COOKIE_WAIT */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_COOKIE_ECHOED */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_ESTABLISHED */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_SHUTDOWN_PENDING */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_SHUTDOWN_SENT */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_SHUTDOWN_RECEIVED */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_SHUTDOWN_ACK_SENT */ - {.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"}, + TYPE_SCTP_FUNC(sctp_sf_unk_chunk), }; /* chunk unknown */ #define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_do_prm_asoc, .name = "sctp_sf_do_prm_asoc"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_asoc), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \ + TYPE_SCTP_FUNC(sctp_sf_not_impl), \ } /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */ #define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_cookie_wait_prm_shutdown, \ - .name = "sctp_sf_cookie_wait_prm_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_wait_prm_shutdown), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_cookie_echoed_prm_shutdown, \ - .name = "sctp_sf_cookie_echoed_prm_shutdown"},\ + TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_prm_shutdown),\ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_9_2_prm_shutdown, \ - .name = "sctp_sf_do_9_2_prm_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_prm_shutdown), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_primitive), \ } /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */ #define TYPE_SCTP_PRIMITIVE_ABORT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_cookie_wait_prm_abort, \ - .name = "sctp_sf_cookie_wait_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_wait_prm_abort), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_cookie_echoed_prm_abort, \ - .name = "sctp_sf_cookie_echoed_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_echoed_prm_abort), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_9_1_prm_abort, \ - .name = "sctp_sf_do_9_1_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_1_prm_abort), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_shutdown_pending_prm_abort, \ - .name = "sctp_sf_shutdown_pending_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_pending_prm_abort), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_shutdown_sent_prm_abort, \ - .name = "sctp_sf_shutdown_sent_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_sent_prm_abort), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_9_1_prm_abort, \ - .name = "sctp_sf_do_9_1_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_1_prm_abort), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_shutdown_ack_sent_prm_abort, \ - .name = "sctp_sf_shutdown_ack_sent_prm_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_shutdown_ack_sent_prm_abort), \ } /* TYPE_SCTP_PRIMITIVE_ABORT */ #define TYPE_SCTP_PRIMITIVE_SEND { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_send), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ } /* TYPE_SCTP_PRIMITIVE_SEND */ #define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_do_prm_requestheartbeat, \ - .name = "sctp_sf_do_prm_requestheartbeat"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_requestheartbeat), \ } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ #define TYPE_SCTP_PRIMITIVE_ASCONF { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_prm_asconf, .name = "sctp_sf_do_prm_asconf"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ /* The primary index for this table is the primitive type. @@ -706,47 +686,44 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_9_2_start_shutdown, \ - .name = "sctp_do_9_2_start_shutdown"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_start_shutdown), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_9_2_shutdown_ack, \ - .name = "sctp_sf_do_9_2_shutdown_ack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ } #define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_cookie_wait_icmp_abort, \ - .name = "sctp_sf_cookie_wait_icmp_abort"}, \ + TYPE_SCTP_FUNC(sctp_sf_cookie_wait_icmp_abort), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \ + TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ } static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = { @@ -756,215 +733,212 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ #define TYPE_SCTP_EVENT_TIMEOUT_NONE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_t1_cookie_timer_expire, \ - .name = "sctp_sf_t1_cookie_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t1_cookie_timer_expire), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_t1_init_timer_expire, \ - .name = "sctp_sf_t1_init_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t1_init_timer_expire), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t2_timer_expire), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t2_timer_expire), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_3_3_rtx), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_t4_timer_expire, .name = "sctp_sf_t4_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t4_timer_expire), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \ + TYPE_SCTP_FUNC(sctp_sf_sendbeat_8_3), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_SACK { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \ + TYPE_SCTP_FUNC(sctp_sf_do_6_2_sack), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } #define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \ /* SCTP_STATE_EMPTY */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_ECHOED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_ESTABLISHED */ \ - {.fn = sctp_sf_autoclose_timer_expire, \ - .name = "sctp_sf_autoclose_timer_expire"}, \ + TYPE_SCTP_FUNC(sctp_sf_autoclose_timer_expire), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = { -- cgit v1.2.3-70-g09d2 From b9df3cb8cf9a96e63dfdcd3056a9cbc71f2459e7 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Nov 2006 11:21:36 -0200 Subject: [TCP/DCCP]: Introduce net_xmit_eval Throughout the TCP/DCCP (and tunnelling) code, it often happens that the return code of a transmit function needs to be tested against NET_XMIT_CN which is a value that does not indicate a strict error condition. This patch uses a macro for these recurring situations which is consistent with the already existing macro net_xmit_errno, saving on duplicated code. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/netdevice.h | 4 ++++ include/net/ipip.h | 2 +- net/dccp/ipv4.c | 5 ++--- net/dccp/ipv6.c | 3 +-- net/dccp/output.c | 14 ++------------ net/ipv4/tcp_ipv4.c | 3 +-- net/ipv4/tcp_output.c | 8 +------- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/tcp_ipv6.c | 3 +-- 9 files changed, 14 insertions(+), 30 deletions(-) (limited to 'net') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4e967b2e22cc..caa3c2593719 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -66,6 +66,10 @@ struct netpoll_info; #define NET_RX_CN_HIGH 4 /* The storm is here */ #define NET_RX_BAD 5 /* packet dropped due to kernel error */ +/* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It + * indicates that the device will soon be dropping packets, or already drops + * some packets of the same priority; prompting us to send less aggressively. */ +#define net_xmit_eval(e) ((e) == NET_XMIT_CN? 0 : (e)) #define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0) #endif diff --git a/include/net/ipip.h b/include/net/ipip.h index f490c3cbe377..84058858eea7 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -35,7 +35,7 @@ struct ip_tunnel ip_send_check(iph); \ \ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\ - if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \ + if (net_xmit_eval(err) == 0) { \ stats->tx_bytes += pkt_len; \ stats->tx_packets++; \ } else { \ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index bc400b2ba25e..61c09014dade 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -501,8 +501,7 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } out: @@ -571,7 +570,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) rxskb->nh.iph->saddr, NULL); bh_unlock_sock(dccp_v4_ctl_socket->sk); - if (err == NET_XMIT_CN || err == 0) { + if (net_xmit_eval(err) == 0) { DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 8d6ddb6389a7..2165b1740c7c 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -294,8 +294,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, &ireq6->rmt_addr); ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); err = ip6_xmit(sk, skb, &fl, opt, 0); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } done: diff --git a/net/dccp/output.c b/net/dccp/output.c index 0994b13f0f15..ef22f3cc791a 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -125,16 +125,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0); - if (err <= 0) - return err; - - /* NET_XMIT_CN is special. It does not guarantee, - * that this packet is lost. It tells that device - * is about to start to drop packets or already - * drops some packets of the same priority and - * invokes us to send less aggressively. - */ - return err == NET_XMIT_CN ? 0 : err; + return net_xmit_eval(err); } return -ENOBUFS; } @@ -426,8 +417,7 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) if (skb != NULL) { memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0); - if (err == NET_XMIT_CN) - err = 0; + return net_xmit_eval(err); } } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2eb58844403c..0ad0904bf56c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -662,8 +662,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } out: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f63e99aac2d5..6a8581ab9a23 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -484,13 +484,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, tcp_enter_cwr(sk); - /* NET_XMIT_CN is special. It does not guarantee, - * that this packet is lost. It tells that device - * is about to start to drop packets or already - * drops some packets of the same priority and - * invokes us to send less aggressively. - */ - return err == NET_XMIT_CN ? 0 : err; + return net_xmit_eval(err); #undef SYSCTL_FLAG_TSTAMPS #undef SYSCTL_FLAG_WSCALE diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4919f9294e2a..80a11909159d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -748,7 +748,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); - if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { + if (net_xmit_eval(err) == 0) { stats->tx_bytes += pkt_len; stats->tx_packets++; } else { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9a8e690fdf7c..9a88395a7629 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -502,8 +502,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); err = ip6_xmit(sk, skb, &fl, opt, 0); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } done: -- cgit v1.2.3-70-g09d2 From 6a128e053e75a5f1be9fb53d0d53159f88197c61 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Nov 2006 11:50:36 -0200 Subject: [DCCPv6]: Resolve conditional build problem Resolves the problem that if IPv6 was configured `y' and DCCP `m' then dccp_ipv6 was not built as a module. With this change, dccp_ipv6 is built as a module whenever DCCP *OR* IPv6 are configured as modules; it will be built-in only if both DCCP = `y' and IPV6 = `y'. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/dccp/Makefile b/net/dccp/Makefile index 17ed99c46617..f4f8793aafff 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -1,13 +1,13 @@ -obj-$(CONFIG_IPV6) += dccp_ipv6.o - -dccp_ipv6-y := ipv6.o - obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o dccp_ipv4-y := ipv4.o +# build dccp_ipv6 as module whenever either IPv6 or DCCP is a module +obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o +dccp_ipv6-y := ipv6.o + dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o -- cgit v1.2.3-70-g09d2 From c02fdc0e81e9c735d8d895af1e201b235df326d8 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Nov 2006 12:48:10 -0200 Subject: [DCCP]: Make feature negotiation more readable This patch replaces cryptic feature negotiation messages of type Oct 31 15:42:20 kernel: dccp_feat_change: feat change type=32 feat=1 Oct 31 15:42:21 kernel: dccp_feat_change: feat change type=34 feat=1 Oct 31 15:42:21 kernel: dccp_feat_change: feat change type=32 feat=5 into ones of type: Nov 2 13:54:45 kernel: dccp_feat_change: ChangeL(CCID (1), 3) Nov 2 13:54:45 kernel: dccp_feat_change: ChangeR(CCID (1), 3) Nov 2 13:54:45 kernel: dccp_feat_change: ChangeL(Ack Ratio (5), 2) Also, * completed the feature number list wrt RFC 4340 sec. 6.4 * annotating which ones have been implemented so far * implemented rudimentary sanity checking in feat.c (FIXMEs) * some minor fixes Commiter note: uninlined dccp_feat_name and dccp_feat_typename, for consistency with dccp_{state,packet}_name, that, BTW, should be compiled only if CONFIG_IP_DCCP_DEBUG is selected, leaving this to another cset tho. Also shortened dccp_feat_negotiation_debug to dccp_feat_debug. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 25 ++++++----- net/dccp/feat.c | 116 +++++++++++++++++++++++++++++++++++++++------------ net/dccp/feat.h | 41 +++++++++++++++++- net/dccp/options.c | 4 +- 4 files changed, 145 insertions(+), 41 deletions(-) (limited to 'net') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 0502dfa7f32c..696319ee2d5b 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -175,18 +175,21 @@ enum { DCCPC_CCID3 = 3, }; -/* DCCP features */ -enum { - DCCPF_RESERVED = 0, - DCCPF_CCID = 1, - DCCPF_SEQUENCE_WINDOW = 3, - DCCPF_ACK_RATIO = 5, - DCCPF_SEND_ACK_VECTOR = 6, - DCCPF_SEND_NDP_COUNT = 7, +/* DCCP features (RFC 4340 section 6.4) */ + enum { + DCCPF_RESERVED = 0, + DCCPF_CCID = 1, + DCCPF_SHORT_SEQNOS = 2, /* XXX: not yet implemented */ + DCCPF_SEQUENCE_WINDOW = 3, + DCCPF_ECN_INCAPABLE = 4, /* XXX: not yet implemented */ + DCCPF_ACK_RATIO = 5, + DCCPF_SEND_ACK_VECTOR = 6, + DCCPF_SEND_NDP_COUNT = 7, DCCPF_MIN_CSUM_COVER = 8, - /* 10-127 reserved */ - DCCPF_MIN_CCID_SPECIFIC = 128, - DCCPF_MAX_CCID_SPECIFIC = 255, + DCCPF_DATA_CHECKSUM = 9, /* XXX: not yet implemented */ + /* 10-127 reserved */ + DCCPF_MIN_CCID_SPECIFIC = 128, + DCCPF_MAX_CCID_SPECIFIC = 255, }; /* this structure is argument to DCCP_SOCKOPT_CHANGE_X */ diff --git a/net/dccp/feat.c b/net/dccp/feat.c index a1b0682ee77c..12cde2f2f13b 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -12,7 +12,6 @@ #include -#include "dccp.h" #include "ccid.h" #include "feat.h" @@ -23,9 +22,17 @@ int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, { struct dccp_opt_pend *opt; - dccp_pr_debug("feat change type=%d feat=%d\n", type, feature); + dccp_feat_debug(type, feature, *val); - /* XXX sanity check feat change request */ + if (!dccp_feat_is_valid_type(type)) { + pr_info("option type %d invalid in negotiation\n", type); + return 1; + } + if (!dccp_feat_is_valid_length(type, feature, len)) { + pr_info("invalid length %d\n", len); + return 1; + } + /* XXX add further sanity checks */ /* check if that feature is already being negotiated */ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { @@ -95,14 +102,14 @@ static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) /* XXX taking only u8 vals */ static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) { - dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val); + dccp_feat_debug(type, feat, val); switch (feat) { case DCCPF_CCID: return dccp_feat_update_ccid(sk, type, val); default: - dccp_pr_debug("IMPLEMENT changing [%d] feat %d to %d\n", - type, feat, val); + dccp_pr_debug("UNIMPLEMENTED: %s(%d, ...)\n", + dccp_feat_typename(type), feat); break; } return 0; @@ -265,10 +272,10 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) u8 *copy; int rc; - /* NN features must be change L */ - if (type == DCCPO_CHANGE_R) { - dccp_pr_debug("received CHANGE_R %d for NN feat %d\n", - type, feature); + /* NN features must be Change L (sec. 6.3.2) */ + if (type != DCCPO_CHANGE_L) { + dccp_pr_debug("received %s for NN feature %d\n", + dccp_feat_typename(type), feature); return -EFAULT; } @@ -299,7 +306,8 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) return rc; } - dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy); + dccp_feat_debug(type, feature, *copy); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); return 0; @@ -318,14 +326,19 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, return; } - opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R : - DCCPO_CONFIRM_L; + switch (type) { + case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break; + case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break; + default: pr_info("invalid type %d\n", type); return; + + } opt->dccpop_feat = feature; opt->dccpop_val = NULL; opt->dccpop_len = 0; /* change feature */ - dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type); + dccp_pr_debug("Empty %s(%d)\n", dccp_feat_typename(type), feature); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); } @@ -359,7 +372,7 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) { int rc; - dccp_pr_debug("got feat change type=%d feat=%d\n", type, feature); + dccp_feat_debug(type, feature, *val); /* figure out if it's SP or NN feature */ switch (feature) { @@ -375,6 +388,8 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) /* XXX implement other features */ default: + dccp_pr_debug("UNIMPLEMENTED: not handling %s(%d, ...)\n", + dccp_feat_typename(type), feature); rc = -EFAULT; break; } @@ -403,20 +418,27 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, u8 t; struct dccp_opt_pend *opt; struct dccp_minisock *dmsk = dccp_msk(sk); - int rc = 1; + int found = 0; int all_confirmed = 1; - dccp_pr_debug("got feat confirm type=%d feat=%d\n", type, feature); - - /* XXX sanity check type & feat */ + dccp_feat_debug(type, feature, *val); /* locate our change request */ - t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L; + switch (type) { + case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break; + case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break; + default: pr_info("invalid type %d\n", type); + return 1; + + } + /* XXX sanity check feature value */ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (!opt->dccpop_conf && opt->dccpop_type == t && opt->dccpop_feat == feature) { - /* we found it */ + found = 1; + dccp_pr_debug("feature %d found\n", opt->dccpop_feat); + /* XXX do sanity check */ opt->dccpop_conf = 1; @@ -425,9 +447,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *val); - dccp_pr_debug("feat %d type %d confirmed %d\n", - feature, type, *val); - rc = 0; + /* XXX check the return value of dccp_feat_update */ break; } @@ -446,9 +466,9 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); } - if (rc) - dccp_pr_debug("feat %d type %d never requested\n", - feature, type); + if (!found) + dccp_pr_debug("%s(%d, ...) never requested\n", + dccp_feat_typename(type), feature); return 0; } @@ -583,3 +603,45 @@ out: } EXPORT_SYMBOL_GPL(dccp_feat_init); + +#ifdef CONFIG_IP_DCCP_DEBUG +const char *dccp_feat_typename(const u8 type) +{ + switch(type) { + case DCCPO_CHANGE_L: return("ChangeL"); + case DCCPO_CONFIRM_L: return("ConfirmL"); + case DCCPO_CHANGE_R: return("ChangeR"); + case DCCPO_CONFIRM_R: return("ConfirmR"); + /* the following case must not appear in feature negotation */ + default: dccp_pr_debug("unknown type %d [BUG!]\n", type); + } + return NULL; +} + +EXPORT_SYMBOL_GPL(dccp_feat_typename); + +const char *dccp_feat_name(const u8 feat) +{ + static const char *feature_names[] = { + [DCCPF_RESERVED] = "Reserved", + [DCCPF_CCID] = "CCID", + [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", + [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", + [DCCPF_ECN_INCAPABLE] = "ECN Incapable", + [DCCPF_ACK_RATIO] = "Ack Ratio", + [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", + [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", + [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", + [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", + }; + if (feat >= DCCPF_MIN_CCID_SPECIFIC) + return "CCID-specific"; + + if (dccp_feat_is_reserved(feat)) + return feature_names[DCCPF_RESERVED]; + + return feature_names[feat]; +} + +EXPORT_SYMBOL_GPL(dccp_feat_name); +#endif /* CONFIG_IP_DCCP_DEBUG */ diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 6048373c7186..2c373ad7edcf 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h @@ -12,9 +12,46 @@ */ #include +#include "dccp.h" -struct sock; -struct dccp_minisock; +static inline int dccp_feat_is_valid_length(u8 type, u8 feature, u8 len) +{ + /* sec. 6.1: Confirm has at least length 3, + * sec. 6.2: Change has at least length 4 */ + if (len < 3) + return 1; + if (len < 4 && (type == DCCPO_CHANGE_L || type == DCCPO_CHANGE_R)) + return 1; + /* XXX: add per-feature length validation (sec. 6.6.8) */ + return 0; +} + +static inline int dccp_feat_is_reserved(const u8 feat) +{ + return (feat > DCCPF_DATA_CHECKSUM && + feat < DCCPF_MIN_CCID_SPECIFIC) || + feat == DCCPF_RESERVED; +} + +/* feature negotiation knows only these four option types (RFC 4340, sec. 6) */ +static inline int dccp_feat_is_valid_type(const u8 optnum) +{ + return optnum >= DCCPO_CHANGE_L && optnum <= DCCPO_CONFIRM_R; + +} + +#ifdef CONFIG_IP_DCCP_DEBUG +extern const char *dccp_feat_typename(const u8 type); +extern const char *dccp_feat_name(const u8 feat); + +static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) +{ + dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type), + dccp_feat_name(feat), feat, val); +} +#else +#define dccp_feat_debug(type, feat, val) +#endif /* CONFIG_IP_DCCP_DEBUG */ extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, u8 *val, u8 len, gfp_t gfp); diff --git a/net/dccp/options.c b/net/dccp/options.c index 121e794fe454..2d0ef27f4ab9 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -465,8 +465,10 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, if (len) memcpy(to, val, len); - dccp_pr_debug("option %d feat %d len %d\n", type, feat, len); + dccp_pr_debug("%s(%s (%d), ...), length %d\n", + dccp_feat_typename(type), + dccp_feat_name(feat), feat, len); return 0; } -- cgit v1.2.3-70-g09d2 From 09dbc3895e3242346bd434dae743c456fd28fc6a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Nov 2006 12:57:34 -0200 Subject: [DCCP]: Miscellaneous code tidy-ups This patch does not change code; it performs some trivial clean/tidy-ups: * removal of a `debug_prefix' string in favour of the already existing dccp_role(sk) * add documentation of structures and constants * separated out the cases for invalid packets (step 1 of the packet validation) * removing duplicate statements * combining declaration & initialisation Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 18 +++++++++++++++++- net/dccp/ackvec.c | 27 ++++++--------------------- net/dccp/ipv4.c | 39 +++++++++++++++++++-------------------- net/dccp/ipv6.c | 6 ++---- net/dccp/options.c | 18 +++++++----------- net/dccp/output.c | 1 + net/dccp/proto.c | 8 ++------ 7 files changed, 54 insertions(+), 63 deletions(-) (limited to 'net') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 696319ee2d5b..d308f1228b61 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -209,6 +209,7 @@ struct dccp_so_feat { #define DCCP_SOCKOPT_CCID_RX_INFO 128 #define DCCP_SOCKOPT_CCID_TX_INFO 192 +/* maximum number of services provided on the same listening port */ #define DCCP_SERVICE_LIST_MAX_LEN 32 #ifdef __KERNEL__ @@ -355,6 +356,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) * @dccpms_ccid - Congestion Control Id (CCID) (section 10) * @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5) * @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2) + * @dccpms_ack_ratio - Ack Ratio Feature (section 11.3) + * @dccpms_pending - List of features being negotiated + * @dccpms_conf - */ struct dccp_minisock { __u64 dccpms_sequence_window; @@ -452,14 +456,26 @@ struct dccp_ackvec; * @dccps_gss - greatest sequence number sent * @dccps_gsr - greatest valid sequence number received * @dccps_gar - greatest valid ack number received on a non-Sync; initialized to %dccps_iss + * @dccps_service - first (passive sock) or unique (active sock) service code + * @dccps_service_list - second .. last service code on passive socket * @dccps_timestamp_time - time of latest TIMESTAMP option * @dccps_timestamp_echo - latest timestamp received on a TIMESTAMP option * @dccps_packet_size - Set thru setsockopt - * @dccps_role - Role of this sock, one of %dccp_role + * @dccps_l_ack_ratio - + * @dccps_r_ack_ratio - * @dccps_pcslen - sender partial checksum coverage (via sockopt) * @dccps_pcrlen - receiver partial checksum coverage (via sockopt) * @dccps_ndp_count - number of Non Data Packets since last data packet + * @dccps_mss_cache - + * @dccps_minisock - * @dccps_hc_rx_ackvec - rx half connection ack vector + * @dccps_hc_rx_ccid - + * @dccps_hc_tx_ccid - + * @dccps_options_received - + * @dccps_epoch - + * @dccps_role - Role of this sock, one of %dccp_role + * @dccps_hc_rx_insert_options - + * @dccps_hc_tx_insert_options - * @dccps_xmit_timer - timer for when CCID is not ready to send */ struct dccp_sock { diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index f8208874ac7d..0c54b89a4e9b 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -67,10 +67,6 @@ static void dccp_ackvec_insert_avr(struct dccp_ackvec *av, int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); -#ifdef CONFIG_IP_DCCP_DEBUG - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT tx: " : "server tx: "; -#endif struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; int len = av->dccpav_vec_len + 2; struct timeval now; @@ -129,9 +125,9 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) dccp_ackvec_insert_avr(av, avr); - dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " + dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, " "ack_ackno=%llu\n", - debug_prefix, avr->dccpavr_sent_len, + dccp_role(sk), avr->dccpavr_sent_len, (unsigned long long)avr->dccpavr_ack_seqno, (unsigned long long)avr->dccpavr_ack_ackno); return 0; @@ -380,14 +376,9 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, */ list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) { if (ackno == avr->dccpavr_ack_seqno) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " + dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, " "ack_ackno=%llu, ACKED!\n", - debug_prefix, 1, + dccp_role(sk), 1, (unsigned long long)avr->dccpavr_ack_seqno, (unsigned long long)avr->dccpavr_ack_ackno); dccp_ackvec_throw_record(av, avr); @@ -437,16 +428,10 @@ found: if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = - dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK vector 0, len=%d, " + dccp_pr_debug("%s ACK vector 0, len=%d, " "ack_seqno=%llu, ack_ackno=%llu, " "ACKED!\n", - debug_prefix, len, + dccp_role(sk), len, (unsigned long long) avr->dccpavr_ack_seqno, (unsigned long long) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 61c09014dade..34d6d197c3b2 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -518,7 +518,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) sizeof(struct dccp_hdr_reset); struct sk_buff *skb; struct dst_entry *dst; - u64 seqno; + u64 seqno = 0; /* Never send a reset in response to a reset. */ if (rxdh->dccph_type == DCCP_PKT_RESET) @@ -552,13 +552,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) DCCP_SKB_CB(rxskb)->dccpd_reset_code; /* See "8.3.1. Abnormal Termination" in RFC 4340 */ - seqno = 0; if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); dccp_hdr_set_seq(dh, seqno); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), - DCCP_SKB_CB(rxskb)->dccpd_seq); + dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); dccp_csum_outgoing(skb); dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr, @@ -734,6 +732,11 @@ discard: EXPORT_SYMBOL_GPL(dccp_v4_do_rcv); +/** + * dccp_invalid_packet - check for malformed packets + * Implements RFC 4340, 8.5: Step 1: Check header basics + * Packets that fail these checks are ignored and do not receive Resets. + */ int dccp_invalid_packet(struct sk_buff *skb) { const struct dccp_hdr *dh; @@ -742,6 +745,7 @@ int dccp_invalid_packet(struct sk_buff *skb) if (skb->pkt_type != PACKET_HOST) return 1; + /* If the packet is shorter than 12 bytes, drop packet and return */ if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) { LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n"); return 1; @@ -749,42 +753,37 @@ int dccp_invalid_packet(struct sk_buff *skb) dh = dccp_hdr(skb); - /* If the packet type is not understood, drop packet and return */ + /* If P.type is not understood, drop packet and return */ if (dh->dccph_type >= DCCP_PKT_INVALID) { LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n"); return 1; } /* - * If P.Data Offset is too small for packet type, or too large for - * packet, drop packet and return + * If P.Data Offset is too small for packet type, drop packet and return */ if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " - "too small 1\n", - dh->dccph_doff); + "too small\n", dh->dccph_doff); return 1; } - + /* + * If P.Data Offset is too too large for packet, drop packet and return + */ if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " - "too small 2\n", - dh->dccph_doff); + "too large\n", dh->dccph_doff); return 1; } - dh = dccp_hdr(skb); - /* * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet * has short sequence numbers), drop packet and return */ - if (dh->dccph_x == 0 && - dh->dccph_type != DCCP_PKT_DATA && - dh->dccph_type != DCCP_PKT_ACK && - dh->dccph_type != DCCP_PKT_DATAACK) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data, Ack " - "nor DataAck and P.X == 0\n", + if (dh->dccph_type >= DCCP_PKT_DATA && + dh->dccph_type <= DCCP_PKT_DATAACK && dh->dccph_x == 0) { + LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data||Ack||" + "DataAck, while P.X == 0\n", dccp_packet_name(dh->dccph_type)); return 1; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 2165b1740c7c..fc326173c215 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -318,7 +318,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) sizeof(struct dccp_hdr_reset); struct sk_buff *skb; struct flowi fl; - u64 seqno; + u64 seqno = 0; if (rxdh->dccph_type == DCCP_PKT_RESET) return; @@ -345,13 +345,11 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) DCCP_SKB_CB(rxskb)->dccpd_reset_code; /* See "8.3.1. Abnormal Termination" in RFC 4340 */ - seqno = 0; if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); dccp_hdr_set_seq(dh, seqno); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), - DCCP_SKB_CB(rxskb)->dccpd_seq); + dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); dccp_csum_outgoing(skb); dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr, diff --git a/net/dccp/options.c b/net/dccp/options.c index 2d0ef27f4ab9..7e50678e2471 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -60,10 +60,6 @@ static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) int dccp_parse_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); -#ifdef CONFIG_IP_DCCP_DEBUG - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx opt: " : "server rx opt: "; -#endif const struct dccp_hdr *dh = dccp_hdr(skb); const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); @@ -119,7 +115,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) goto out_invalid_option; opt_recv->dccpor_ndp = dccp_decode_value_var(value, len); - dccp_pr_debug("%sNDP count=%d\n", debug_prefix, + dccp_pr_debug("%s rx opt: NDP count=%d\n", dccp_role(sk), opt_recv->dccpor_ndp); break; case DCCPO_CHANGE_L: @@ -165,8 +161,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; dccp_timestamp(sk, &dp->dccps_timestamp_time); - dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n", - debug_prefix, opt_recv->dccpor_timestamp, + dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n", + dccp_role(sk), opt_recv->dccpor_timestamp, (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq); break; @@ -176,8 +172,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); - dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ", - debug_prefix, + dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " + "ackno=%llu, ", dccp_role(sk), opt_recv->dccpor_timestamp_echo, len + 2, (unsigned long long) @@ -211,8 +207,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (elapsed_time > opt_recv->dccpor_elapsed_time) opt_recv->dccpor_elapsed_time = elapsed_time; - dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix, - elapsed_time); + dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", + dccp_role(sk), elapsed_time); break; /* * From RFC 4340, sec. 10.3: diff --git a/net/dccp/output.c b/net/dccp/output.c index ef22f3cc791a..c34eada7f025 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -333,6 +333,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, return NULL; } + /* Build and checksum header */ dh = dccp_zeroed_hdr(skb, dccp_header_size); dh->dccph_sport = inet_sk(sk)->sport; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 9c9c08cffdaf..0225bdacd3b1 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -452,9 +452,8 @@ out_free_val: static int do_dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { - struct dccp_sock *dp; - int err; - int val; + struct dccp_sock *dp = dccp_sk(sk); + int val, err = 0; if (optlen < sizeof(int)) return -EINVAL; @@ -466,9 +465,6 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, return dccp_setsockopt_service(sk, val, optval, optlen); lock_sock(sk); - dp = dccp_sk(sk); - err = 0; - switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: dp->dccps_packet_size = val; -- cgit v1.2.3-70-g09d2 From d23ca15a21804631d8f787a0cc5646df81b9c2ea Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Tue, 14 Nov 2006 13:19:45 -0200 Subject: [DCCP] ACKVEC: Optimization - Do not traverse records if none will be found Do not traverse the list of ack vector records [proportional to window size] when we know we will not find what we are looking for. This is especially useful because ack vectors are checked twice: 1) Upon parsing of options. 2) Upon notification of a new ack. All of the work will occur during check #1. Therefore, when check #2 is performed, no new work will be done. This is now "detected" and there is no performance hit when doing #2. Signed-off-by: Andrea Bittau Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ackvec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 0c54b89a4e9b..bd20a2c55e25 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -383,7 +383,8 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, (unsigned long long)avr->dccpavr_ack_ackno); dccp_ackvec_throw_record(av, avr); break; - } + } else if (avr->dccpavr_ack_seqno > ackno) + break; /* old news */ } } -- cgit v1.2.3-70-g09d2 From a1bcfacd0577ff477e934731d4ceb3d26eab947d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 14 Nov 2006 10:43:58 -0800 Subject: netpoll: private skb pool (rev3) It was a dark and stormy night when Steve first saw the netpoll beast. The beast was odd, and misshapen but not extremely ugly. "Let me take off one of your warts" he said. This wart is where you tried to make an skb list yourself. If the beast had ever run out of memory, he would have stupefied himself unnecessarily. The first try was painful, so he tried again till the bleeding stopped. And again, and again... Signed-off-by: Stephen Hemminger --- net/core/netpoll.c | 53 +++++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) (limited to 'net') diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6589adb14cbf..4de62f1f4134 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -36,9 +36,7 @@ #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) #define MAX_RETRIES 20000 -static DEFINE_SPINLOCK(skb_list_lock); -static int nr_skbs; -static struct sk_buff *skbs; +static struct sk_buff_head skb_pool; static DEFINE_SPINLOCK(queue_lock); static int queue_depth; @@ -190,17 +188,15 @@ static void refill_skbs(void) struct sk_buff *skb; unsigned long flags; - spin_lock_irqsave(&skb_list_lock, flags); - while (nr_skbs < MAX_SKBS) { + spin_lock_irqsave(&skb_pool.lock, flags); + while (skb_pool.qlen < MAX_SKBS) { skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC); if (!skb) break; - skb->next = skbs; - skbs = skb; - nr_skbs++; + __skb_queue_tail(&skb_pool, skb); } - spin_unlock_irqrestore(&skb_list_lock, flags); + spin_unlock_irqrestore(&skb_pool.lock, flags); } static void zap_completion_queue(void) @@ -229,38 +225,25 @@ static void zap_completion_queue(void) put_cpu_var(softnet_data); } -static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve) +static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve) { - int once = 1, count = 0; - unsigned long flags; - struct sk_buff *skb = NULL; + int count = 0; + struct sk_buff *skb; zap_completion_queue(); + refill_skbs(); repeat: - if (nr_skbs < MAX_SKBS) - refill_skbs(); skb = alloc_skb(len, GFP_ATOMIC); - - if (!skb) { - spin_lock_irqsave(&skb_list_lock, flags); - skb = skbs; - if (skb) { - skbs = skb->next; - skb->next = NULL; - nr_skbs--; - } - spin_unlock_irqrestore(&skb_list_lock, flags); - } + if (!skb) + skb = skb_dequeue(&skb_pool); if(!skb) { - count++; - if (once && (count == 1000000)) { - printk("out of netpoll skbs!\n"); - once = 0; + if (++count < 10) { + netpoll_poll(np); + goto repeat; } - netpoll_poll(np); - goto repeat; + return NULL; } atomic_set(&skb->users, 1); @@ -770,6 +753,12 @@ int netpoll_setup(struct netpoll *np) return -1; } +static int __init netpoll_init(void) { + skb_queue_head_init(&skb_pool); + return 0; +} +core_initcall(netpoll_init); + void netpoll_cleanup(struct netpoll *np) { struct netpoll_info *npinfo; -- cgit v1.2.3-70-g09d2 From 93ec2c723e3f8a216dde2899aeb85c648672bc6b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:50 -0700 Subject: netpoll info leak After looking harder, Steve noticed that the netpoll beast leaked a little every time it shutdown for a nap. Not a big leak, but a nuisance kind of thing. He took out his refcount duct tape and patched the leak. It was overkill since there was already other locking in that area, but it looked clean and wouldn't attract fleas. Signed-off-by: Stephen Hemminger --- include/linux/netpoll.h | 1 + net/core/netpoll.c | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 1efe60c5c00c..39845fc975f9 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -25,6 +25,7 @@ struct netpoll { }; struct netpoll_info { + atomic_t refcnt; spinlock_t poll_lock; int poll_owner; int tries; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 4de62f1f4134..c66df2f45d26 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -658,8 +658,11 @@ int netpoll_setup(struct netpoll *np) npinfo->tries = MAX_RETRIES; spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); - } else + atomic_set(&npinfo->refcnt, 1); + } else { npinfo = ndev->npinfo; + atomic_inc(&npinfo->refcnt); + } if (!ndev->poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", @@ -766,12 +769,22 @@ void netpoll_cleanup(struct netpoll *np) if (np->dev) { npinfo = np->dev->npinfo; - if (npinfo && npinfo->rx_np == np) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - npinfo->rx_np = NULL; - npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; - spin_unlock_irqrestore(&npinfo->rx_lock, flags); + if (npinfo) { + if (npinfo->rx_np == np) { + spin_lock_irqsave(&npinfo->rx_lock, flags); + npinfo->rx_np = NULL; + npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; + spin_unlock_irqrestore(&npinfo->rx_lock, flags); + } + + np->dev->npinfo = NULL; + if (atomic_dec_and_test(&npinfo->refcnt)) { + skb_queue_purge(&npinfo->arp_tx); + + kfree(npinfo); + } } + dev_put(np->dev); } -- cgit v1.2.3-70-g09d2 From b6cd27ed33886a5ffaf0925a6d98e13e18e8a1af Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:51 -0700 Subject: netpoll per device txq When the netpoll beast got really busy, it tended to clog things, so it stored them for later. But the beast was putting all it's skb's in one basket. This was bad because maybe some pipes were clogged and others were not. Signed-off-by: Stephen Hemminger --- include/linux/netpoll.h | 2 ++ net/core/netpoll.c | 50 +++++++++++++++---------------------------------- 2 files changed, 17 insertions(+), 35 deletions(-) (limited to 'net') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 39845fc975f9..93a8b7664423 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -33,6 +33,8 @@ struct netpoll_info { spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ struct sk_buff_head arp_tx; /* list of arp requests to reply to */ + struct sk_buff_head txq; + struct work_struct tx_work; }; void netpoll_poll(struct netpoll *np); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c66df2f45d26..ac4e8b8f57d1 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -38,10 +38,6 @@ static struct sk_buff_head skb_pool; -static DEFINE_SPINLOCK(queue_lock); -static int queue_depth; -static struct sk_buff *queue_head, *queue_tail; - static atomic_t trapped; #define NETPOLL_RX_ENABLED 1 @@ -56,46 +52,25 @@ static void arp_reply(struct sk_buff *skb); static void queue_process(void *p) { - unsigned long flags; + struct netpoll_info *npinfo = p; struct sk_buff *skb; - while (queue_head) { - spin_lock_irqsave(&queue_lock, flags); - - skb = queue_head; - queue_head = skb->next; - if (skb == queue_tail) - queue_head = NULL; - - queue_depth--; - - spin_unlock_irqrestore(&queue_lock, flags); - + while ((skb = skb_dequeue(&npinfo->txq))) dev_queue_xmit(skb); - } -} -static DECLARE_WORK(send_queue, queue_process, NULL); +} void netpoll_queue(struct sk_buff *skb) { - unsigned long flags; + struct net_device *dev = skb->dev; + struct netpoll_info *npinfo = dev->npinfo; - if (queue_depth == MAX_QUEUE_DEPTH) { - __kfree_skb(skb); - return; + if (!npinfo) + kfree_skb(skb); + else { + skb_queue_tail(&npinfo->txq, skb); + schedule_work(&npinfo->tx_work); } - - spin_lock_irqsave(&queue_lock, flags); - if (!queue_head) - queue_head = skb; - else - queue_tail->next = skb; - queue_tail = skb; - queue_depth++; - spin_unlock_irqrestore(&queue_lock, flags); - - schedule_work(&send_queue); } static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, @@ -658,6 +633,9 @@ int netpoll_setup(struct netpoll *np) npinfo->tries = MAX_RETRIES; spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); + skb_queue_head_init(&npinfo->txq); + INIT_WORK(&npinfo->tx_work, queue_process, npinfo); + atomic_set(&npinfo->refcnt, 1); } else { npinfo = ndev->npinfo; @@ -780,6 +758,8 @@ void netpoll_cleanup(struct netpoll *np) np->dev->npinfo = NULL; if (atomic_dec_and_test(&npinfo->refcnt)) { skb_queue_purge(&npinfo->arp_tx); + skb_queue_purge(&npinfo->txq); + flush_scheduled_work(); kfree(npinfo); } -- cgit v1.2.3-70-g09d2 From b41848b61bae30e3661efd4ec62ea380cedef687 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:52 -0700 Subject: netpoll setup error handling The beast was not always healthy. When it was sick, it tended to be laconic and not tell anyone the real problem. A few small changes had it telling the world about its problems, if they really wanted to hear. Signed-off-by: Stephen Hemminger --- drivers/net/netconsole.c | 7 +++++-- net/core/netpoll.c | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index bf58db29e2ed..e6e8a9797b6d 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -102,6 +102,8 @@ __setup("netconsole=", option_setup); static int init_netconsole(void) { + int err; + if(strlen(config)) option_setup(config); @@ -110,8 +112,9 @@ static int init_netconsole(void) return 0; } - if(netpoll_setup(&np)) - return -EINVAL; + err = netpoll_setup(&np); + if (err) + return err; register_console(&netconsole); printk(KERN_INFO "netconsole: network logging started\n"); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ac4e8b8f57d1..621baa5da49f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -611,20 +611,23 @@ int netpoll_setup(struct netpoll *np) struct in_device *in_dev; struct netpoll_info *npinfo; unsigned long flags; + int err; if (np->dev_name) ndev = dev_get_by_name(np->dev_name); if (!ndev) { printk(KERN_ERR "%s: %s doesn't exist, aborting.\n", np->name, np->dev_name); - return -1; + return -ENODEV; } np->dev = ndev; if (!ndev->npinfo) { npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); - if (!npinfo) + if (!npinfo) { + err = -ENOMEM; goto release; + } npinfo->rx_flags = 0; npinfo->rx_np = NULL; @@ -645,6 +648,7 @@ int netpoll_setup(struct netpoll *np) if (!ndev->poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", np->name, np->dev_name); + err = -ENOTSUPP; goto release; } @@ -655,13 +659,14 @@ int netpoll_setup(struct netpoll *np) np->name, np->dev_name); rtnl_lock(); - if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) { + err = dev_open(ndev); + rtnl_unlock(); + + if (err) { printk(KERN_ERR "%s: failed to open %s\n", - np->name, np->dev_name); - rtnl_unlock(); + np->name, ndev->name); goto release; } - rtnl_unlock(); atleast = jiffies + HZ/10; atmost = jiffies + 4*HZ; @@ -699,6 +704,7 @@ int netpoll_setup(struct netpoll *np) rcu_read_unlock(); printk(KERN_ERR "%s: no IP address for %s, aborting\n", np->name, np->dev_name); + err = -EDESTADDRREQ; goto release; } @@ -731,7 +737,7 @@ int netpoll_setup(struct netpoll *np) kfree(npinfo); np->dev = NULL; dev_put(ndev); - return -1; + return err; } static int __init netpoll_init(void) { -- cgit v1.2.3-70-g09d2 From 6c43ff18f91e54aa7555d8ae4f26eab7da5bce68 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:53 -0700 Subject: netpoll deferred transmit path When the netpoll beast got busy, he tended to babble. Instead of talking out of his large mouth as normal, he tended to try to snort out other orifices. This lead to words (skbs) ending up in odd places (like NIT) that he did not intend. The normal way of talking wouldn't work, but he could at least change to using the same tone all the time. Signed-off-by: Stephen Hemminger --- net/core/netpoll.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 621baa5da49f..93cb828f3aaf 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -55,9 +55,25 @@ static void queue_process(void *p) struct netpoll_info *npinfo = p; struct sk_buff *skb; - while ((skb = skb_dequeue(&npinfo->txq))) - dev_queue_xmit(skb); + while ((skb = skb_dequeue(&npinfo->txq))) { + struct net_device *dev = skb->dev; + if (!netif_device_present(dev) || !netif_running(dev)) { + __kfree_skb(skb); + continue; + } + + netif_tx_lock_bh(dev); + if (netif_queue_stopped(dev) || + dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { + skb_queue_head(&npinfo->txq, skb); + netif_tx_unlock_bh(dev); + + schedule_delayed_work(&npinfo->tx_work, HZ/10); + return; + } + netif_tx_unlock_bh(dev); + } } void netpoll_queue(struct sk_buff *skb) @@ -765,6 +781,7 @@ void netpoll_cleanup(struct netpoll *np) if (atomic_dec_and_test(&npinfo->refcnt)) { skb_queue_purge(&npinfo->arp_tx); skb_queue_purge(&npinfo->txq); + cancel_rearming_delayed_work(&npinfo->tx_work); flush_scheduled_work(); kfree(npinfo); -- cgit v1.2.3-70-g09d2 From 2bdfe0baeca0e2750037b8fba71905c00ac3c515 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:54 -0700 Subject: netpoll retry cleanup The netpoll beast was still not happy. If the beast got clogged pipes, it tended to stare blankly off in space for a long time. The problem couldn't be completely fixed because the beast talked with irq's disabled. But it could be made less painful and shorter. Signed-off-by: Stephen Hemminger --- include/linux/netpoll.h | 1 - net/core/netpoll.c | 71 +++++++++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 39 deletions(-) (limited to 'net') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 93a8b7664423..c65d12ec7bb0 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -28,7 +28,6 @@ struct netpoll_info { atomic_t refcnt; spinlock_t poll_lock; int poll_owner; - int tries; int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 93cb828f3aaf..6b34c394672f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -34,12 +34,12 @@ #define MAX_UDP_CHUNK 1460 #define MAX_SKBS 32 #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) -#define MAX_RETRIES 20000 static struct sk_buff_head skb_pool; static atomic_t trapped; +#define USEC_PER_POLL 50 #define NETPOLL_RX_ENABLED 1 #define NETPOLL_RX_DROP 2 @@ -72,6 +72,7 @@ static void queue_process(void *p) schedule_delayed_work(&npinfo->tx_work, HZ/10); return; } + netif_tx_unlock_bh(dev); } } @@ -244,50 +245,44 @@ repeat: static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { - int status; - struct netpoll_info *npinfo; + int status = NETDEV_TX_BUSY; + unsigned long tries; + struct net_device *dev = np->dev; + struct netpoll_info *npinfo = np->dev->npinfo; + + if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { + __kfree_skb(skb); + return; + } + + /* don't get messages out of order, and no recursion */ + if ( !(np->drop == netpoll_queue && skb_queue_len(&npinfo->txq)) + && npinfo->poll_owner != smp_processor_id() + && netif_tx_trylock(dev)) { + + /* try until next clock tick */ + for(tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { + if (!netif_queue_stopped(dev)) + status = dev->hard_start_xmit(skb, dev); + + if (status == NETDEV_TX_OK) + break; - if (!np || !np->dev || !netif_running(np->dev)) { - __kfree_skb(skb); - return; - } + /* tickle device maybe there is some cleanup */ + netpoll_poll(np); - npinfo = np->dev->npinfo; + udelay(USEC_PER_POLL); + } + netif_tx_unlock(dev); + } - /* avoid recursion */ - if (npinfo->poll_owner == smp_processor_id() || - np->dev->xmit_lock_owner == smp_processor_id()) { + if (status != NETDEV_TX_OK) { + /* requeue for later */ if (np->drop) np->drop(skb); else __kfree_skb(skb); - return; } - - do { - npinfo->tries--; - netif_tx_lock(np->dev); - - /* - * network drivers do not expect to be called if the queue is - * stopped. - */ - status = NETDEV_TX_BUSY; - if (!netif_queue_stopped(np->dev)) - status = np->dev->hard_start_xmit(skb, np->dev); - - netif_tx_unlock(np->dev); - - /* success */ - if(!status) { - npinfo->tries = MAX_RETRIES; /* reset */ - return; - } - - /* transmit busy */ - netpoll_poll(np); - udelay(50); - } while (npinfo->tries > 0); } void netpoll_send_udp(struct netpoll *np, const char *msg, int len) @@ -649,7 +644,7 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = NULL; spin_lock_init(&npinfo->poll_lock); npinfo->poll_owner = -1; - npinfo->tries = MAX_RETRIES; + spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); skb_queue_head_init(&npinfo->txq); -- cgit v1.2.3-70-g09d2 From 5de4a473bda49554e4e9bd93b78f43c49a7ea69c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:55 -0700 Subject: netpoll queue cleanup The beast had a long and not very happy history. At one point, a friend (netdump) had asked that he open up a little. Well, the friend was long gone now, and the beast had this dangling piece hanging (netpoll_queue). It wasn't hard to stitch the netpoll_queue back in where it belonged and make everything tidy. Signed-off-by: Stephen Hemminger --- drivers/net/netconsole.c | 1 - include/linux/netpoll.h | 4 ++-- net/core/netpoll.c | 23 +++-------------------- 3 files changed, 5 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index e6e8a9797b6d..69233f6aa05c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -60,7 +60,6 @@ static struct netpoll np = { .local_port = 6665, .remote_port = 6666, .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - .drop = netpoll_queue, }; static int configured = 0; diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index c65d12ec7bb0..b7eb008c43de 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -18,7 +18,7 @@ struct netpoll { struct net_device *dev; char dev_name[16], *name; void (*rx_hook)(struct netpoll *, int, char *, int); - void (*drop)(struct sk_buff *skb); + u32 local_ip, remote_ip; u16 local_port, remote_port; unsigned char local_mac[6], remote_mac[6]; @@ -44,7 +44,7 @@ int netpoll_trap(void); void netpoll_set_trap(int trap); void netpoll_cleanup(struct netpoll *np); int __netpoll_rx(struct sk_buff *skb); -void netpoll_queue(struct sk_buff *skb); + #ifdef CONFIG_NETPOLL static inline int netpoll_rx(struct sk_buff *skb) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6b34c394672f..0d1de3c47a01 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -77,19 +77,6 @@ static void queue_process(void *p) } } -void netpoll_queue(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct netpoll_info *npinfo = dev->npinfo; - - if (!npinfo) - kfree_skb(skb); - else { - skb_queue_tail(&npinfo->txq, skb); - schedule_work(&npinfo->tx_work); - } -} - static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, u32 saddr, u32 daddr) { @@ -256,7 +243,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } /* don't get messages out of order, and no recursion */ - if ( !(np->drop == netpoll_queue && skb_queue_len(&npinfo->txq)) + if ( skb_queue_len(&npinfo->txq) == 0 && npinfo->poll_owner != smp_processor_id() && netif_tx_trylock(dev)) { @@ -277,11 +264,8 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } if (status != NETDEV_TX_OK) { - /* requeue for later */ - if (np->drop) - np->drop(skb); - else - __kfree_skb(skb); + skb_queue_tail(&npinfo->txq, skb); + schedule_work(&npinfo->tx_work); } } @@ -809,4 +793,3 @@ EXPORT_SYMBOL(netpoll_setup); EXPORT_SYMBOL(netpoll_cleanup); EXPORT_SYMBOL(netpoll_send_udp); EXPORT_SYMBOL(netpoll_poll); -EXPORT_SYMBOL(netpoll_queue); -- cgit v1.2.3-70-g09d2 From cfb6eeb4c860592edd123fdea908d23c6ad1c7dc Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 14 Nov 2006 19:07:45 -0800 Subject: [TCP]: MD5 Signature Option (RFC2385) support. Based on implementation by Rick Payne. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- CREDITS | 3 + include/linux/tcp.h | 35 ++- include/net/request_sock.h | 3 +- include/net/tcp.h | 143 ++++++++++ include/net/timewait_sock.h | 3 + net/dccp/ipv4.c | 6 +- net/dccp/ipv6.c | 6 +- net/dccp/minisocks.c | 2 +- net/ipv4/Kconfig | 16 ++ net/ipv4/tcp.c | 137 +++++++++ net/ipv4/tcp_input.c | 8 + net/ipv4/tcp_ipv4.c | 673 ++++++++++++++++++++++++++++++++++++++++++-- net/ipv4/tcp_minisocks.c | 64 ++++- net/ipv4/tcp_output.c | 111 +++++++- net/ipv6/tcp_ipv6.c | 568 +++++++++++++++++++++++++++++++++++-- 15 files changed, 1714 insertions(+), 64 deletions(-) (limited to 'net') diff --git a/CREDITS b/CREDITS index ccd4f9f4dd71..d0880082c19b 100644 --- a/CREDITS +++ b/CREDITS @@ -2598,6 +2598,9 @@ S: Ucitelska 1576 S: Prague 8 S: 182 00 Czech Republic +N: Rick Payne +D: RFC2385 Support for TCP + N: Barak A. Pearlmutter E: bap@cs.unm.edu W: http://www.cs.unm.edu/~bap/ diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 2d36f6db3706..0aecfc955591 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -19,6 +19,7 @@ #include #include +#include struct tcphdr { __be16 source; @@ -94,6 +95,7 @@ enum { #define TCP_INFO 11 /* Information about this connection. */ #define TCP_QUICKACK 12 /* Block/reenable quick acks */ #define TCP_CONGESTION 13 /* Congestion control algorithm */ +#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ #define TCPI_OPT_TIMESTAMPS 1 #define TCPI_OPT_SACK 2 @@ -157,6 +159,17 @@ struct tcp_info __u32 tcpi_total_retrans; }; +/* for TCP_MD5SIG socket option */ +#define TCP_MD5SIG_MAXKEYLEN 80 + +struct tcp_md5sig { + struct __kernel_sockaddr_storage tcpm_addr; /* address associated */ + __u16 __tcpm_pad1; /* zero */ + __u16 tcpm_keylen; /* key length */ + __u32 __tcpm_pad2; /* zero */ + __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ +}; + #ifdef __KERNEL__ #include @@ -197,9 +210,13 @@ struct tcp_options_received { }; struct tcp_request_sock { - struct inet_request_sock req; - __u32 rcv_isn; - __u32 snt_isn; + struct inet_request_sock req; +#ifdef CONFIG_TCP_MD5SIG + /* Only used by TCP MD5 Signature so far. */ + struct tcp_request_sock_ops *af_specific; +#endif + __u32 rcv_isn; + __u32 snt_isn; }; static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req) @@ -363,6 +380,14 @@ struct tcp_sock { __u32 probe_seq_start; __u32 probe_seq_end; } mtu_probe; + +#ifdef CONFIG_TCP_MD5SIG +/* TCP AF-Specific parts; only used by MD5 Signature support so far */ + struct tcp_sock_af_ops *af_specific; + +/* TCP MD5 Signagure Option information */ + struct tcp_md5sig_info *md5sig_info; +#endif }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) @@ -377,6 +402,10 @@ struct tcp_timewait_sock { __u32 tw_rcv_wnd; __u32 tw_ts_recent; long tw_ts_recent_stamp; +#ifdef CONFIG_TCP_MD5SIG + __u16 tw_md5_keylen; + __u8 tw_md5_key[TCP_MD5SIG_MAXKEYLEN]; +#endif }; static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk) diff --git a/include/net/request_sock.h b/include/net/request_sock.h index b5b023e79e5f..e37baaf2080b 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -35,7 +35,8 @@ struct request_sock_ops { struct dst_entry *dst); void (*send_ack)(struct sk_buff *skb, struct request_sock *req); - void (*send_reset)(struct sk_buff *skb); + void (*send_reset)(struct sock *sk, + struct sk_buff *skb); void (*destructor)(struct request_sock *req); }; diff --git a/include/net/tcp.h b/include/net/tcp.h index e1a5d29d0a1f..363960872de0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOPT_SACK_PERM 4 /* SACK Permitted */ #define TCPOPT_SACK 5 /* SACK Block */ #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ +#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ /* * TCP option lengths @@ -170,6 +172,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOLEN_WINDOW 3 #define TCPOLEN_SACK_PERM 2 #define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_MD5SIG 18 /* But this is what stacks really send out. */ #define TCPOLEN_TSTAMP_ALIGNED 12 @@ -178,6 +181,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOLEN_SACK_BASE 2 #define TCPOLEN_SACK_BASE_ALIGNED 4 #define TCPOLEN_SACK_PERBLOCK 8 +#define TCPOLEN_MD5SIG_ALIGNED 20 /* Flags in tp->nonagle */ #define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */ @@ -299,6 +303,8 @@ extern void tcp_cleanup_rbuf(struct sock *sk, int copied); extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp); +extern void tcp_twsk_destructor(struct sock *sk); + static inline void tcp_dec_quickack_mode(struct sock *sk, const unsigned int pkts) { @@ -1064,6 +1070,114 @@ static inline void clear_all_retrans_hints(struct tcp_sock *tp){ tp->fastpath_skb_hint = NULL; } +/* MD5 Signature */ +struct crypto_hash; + +/* - key database */ +struct tcp_md5sig_key { + u8 *key; + u8 keylen; +}; + +struct tcp4_md5sig_key { + u8 *key; + u16 keylen; + __be32 addr; +}; + +struct tcp6_md5sig_key { + u8 *key; + u16 keylen; +#if 0 + u32 scope_id; /* XXX */ +#endif + struct in6_addr addr; +}; + +/* - sock block */ +struct tcp_md5sig_info { + struct tcp4_md5sig_key *keys4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct tcp6_md5sig_key *keys6; + u32 entries6; + u32 alloced6; +#endif + u32 entries4; + u32 alloced4; +}; + +/* - pseudo header */ +struct tcp4_pseudohdr { + __be32 saddr; + __be32 daddr; + __u8 pad; + __u8 protocol; + __be16 len; +}; + +struct tcp6_pseudohdr { + struct in6_addr saddr; + struct in6_addr daddr; + __be32 len; + __be32 protocol; /* including padding */ +}; + +union tcp_md5sum_block { + struct tcp4_pseudohdr ip4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct tcp6_pseudohdr ip6; +#endif +}; + +/* - pool: digest algorithm, hash description and scratch buffer */ +struct tcp_md5sig_pool { + struct hash_desc md5_desc; + union tcp_md5sum_block md5_blk; +}; + +#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */ + +/* - functions */ +extern int tcp_v4_calc_md5_hash(char *md5_hash, + struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, + int protocol, int tcplen); +extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, + struct sock *addr_sk); + +extern int tcp_v4_md5_do_add(struct sock *sk, + __be32 addr, + u8 *newkey, + u8 newkeylen); + +extern int tcp_v4_md5_do_del(struct sock *sk, + u32 addr); + +extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); +extern void tcp_free_md5sig_pool(void); + +extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); +extern void __tcp_put_md5sig_pool(void); + +static inline +struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) +{ + int cpu = get_cpu(); + struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu); + if (!ret) + put_cpu(); + return ret; +} + +static inline void tcp_put_md5sig_pool(void) +{ + __tcp_put_md5sig_pool(); + put_cpu(); +} + /* /proc */ enum tcp_seq_states { TCP_SEQ_STATE_LISTENING, @@ -1103,6 +1217,35 @@ extern int tcp4_proc_init(void); extern void tcp4_proc_exit(void); #endif +/* TCP af-specific functions */ +struct tcp_sock_af_ops { +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, + struct sock *addr_sk); + int (*calc_md5_hash) (char *location, + struct tcp_md5sig_key *md5, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, + int protocol, int len); + int (*md5_add) (struct sock *sk, + struct sock *addr_sk, + u8 *newkey, + u8 len); + int (*md5_parse) (struct sock *sk, + char __user *optval, + int optlen); +#endif +}; + +struct tcp_request_sock_ops { +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, + struct request_sock *req); +#endif +}; + extern void tcp_v4_init(struct net_proto_family *ops); extern void tcp_init(void); diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h index be293d795e38..d7a306ea560d 100644 --- a/include/net/timewait_sock.h +++ b/include/net/timewait_sock.h @@ -31,6 +31,9 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) static inline void twsk_destructor(struct sock *sk) { + BUG_ON(sk == NULL); + BUG_ON(sk->sk_prot == NULL); + BUG_ON(sk->sk_prot->twsk_prot == NULL); if (sk->sk_prot->twsk_prot->twsk_destructor != NULL) sk->sk_prot->twsk_prot->twsk_destructor(sk); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 34d6d197c3b2..35985334daee 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -509,7 +509,7 @@ out: return err; } -static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) +static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) { int err; struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; @@ -724,7 +724,7 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - dccp_v4_ctl_send_reset(skb); + dccp_v4_ctl_send_reset(sk, skb); discard: kfree_skb(skb); return 0; @@ -913,7 +913,7 @@ no_dccp_socket: if (dh->dccph_type != DCCP_PKT_RESET) { DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; - dccp_v4_ctl_send_reset(skb); + dccp_v4_ctl_send_reset(sk, skb); } discard_it: diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index fc326173c215..e0a0607862ef 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -310,7 +310,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) +static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) { struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) + @@ -805,7 +805,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - dccp_v6_ctl_send_reset(skb); + dccp_v6_ctl_send_reset(sk, skb); discard: if (opt_skb != NULL) __kfree_skb(opt_skb); @@ -902,7 +902,7 @@ no_dccp_socket: if (dh->dccph_type != DCCP_PKT_RESET) { DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; - dccp_v6_ctl_send_reset(skb); + dccp_v6_ctl_send_reset(sk, skb); } discard_it: diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 0c49733f5be1..3975048d8094 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -246,7 +246,7 @@ listen_overflow: DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY; drop: if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET) - req->rsk_ops->send_reset(skb); + req->rsk_ops->send_reset(sk, skb); inet_csk_reqsk_queue_drop(sk, req, prev); goto out; diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index bc298bcc344e..39e0cb763588 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -618,5 +618,21 @@ config DEFAULT_TCP_CONG default "reno" if DEFAULT_RENO default "cubic" +config TCP_MD5SIG + bool "TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)" + depends on EXPERIMENTAL + select CRYPTO + select CRYPTO_MD5 + ---help--- + RFC2385 specifices a method of giving MD5 protection to TCP sessions. + Its main (only?) use is to protect BGP sessions between core routers + on the Internet. + + If unsure, say N. + +config TCP_MD5SIG_DEBUG + bool "TCP: MD5 Signature Option debugging" + depends on TCP_MD5SIG + source "net/ipv4/ipvs/Kconfig" diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c05e8edaf544..dadef867a3bb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -258,6 +258,7 @@ #include #include #include +#include #include #include @@ -1942,6 +1943,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, } break; +#ifdef CONFIG_TCP_MD5SIG + case TCP_MD5SIG: + /* Read the IP->Key mappings from userspace */ + err = tp->af_specific->md5_parse(sk, optval, optlen); + break; +#endif + default: err = -ENOPROTOOPT; break; @@ -2231,6 +2239,135 @@ out: } EXPORT_SYMBOL(tcp_tso_segment); +#ifdef CONFIG_TCP_MD5SIG +static unsigned long tcp_md5sig_users; +static struct tcp_md5sig_pool **tcp_md5sig_pool; +static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); + +static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) +{ + int cpu; + for_each_possible_cpu(cpu) { + struct tcp_md5sig_pool *p = *per_cpu_ptr(pool, cpu); + if (p) { + if (p->md5_desc.tfm) + crypto_free_hash(p->md5_desc.tfm); + kfree(p); + p = NULL; + } + } + free_percpu(pool); +} + +void tcp_free_md5sig_pool(void) +{ + struct tcp_md5sig_pool **pool = NULL; + + spin_lock(&tcp_md5sig_pool_lock); + if (--tcp_md5sig_users == 0) { + pool = tcp_md5sig_pool; + tcp_md5sig_pool = NULL; + } + spin_unlock(&tcp_md5sig_pool_lock); + if (pool) + __tcp_free_md5sig_pool(pool); +} + +EXPORT_SYMBOL(tcp_free_md5sig_pool); + +struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) +{ + int cpu; + struct tcp_md5sig_pool **pool; + + pool = alloc_percpu(struct tcp_md5sig_pool *); + if (!pool) + return NULL; + + for_each_possible_cpu(cpu) { + struct tcp_md5sig_pool *p; + struct crypto_hash *hash; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + goto out_free; + *per_cpu_ptr(pool, cpu) = p; + + hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + if (!hash || IS_ERR(hash)) + goto out_free; + + p->md5_desc.tfm = hash; + } + return pool; +out_free: + __tcp_free_md5sig_pool(pool); + return NULL; +} + +struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void) +{ + struct tcp_md5sig_pool **pool; + int alloc = 0; + +retry: + spin_lock(&tcp_md5sig_pool_lock); + pool = tcp_md5sig_pool; + if (tcp_md5sig_users++ == 0) { + alloc = 1; + spin_unlock(&tcp_md5sig_pool_lock); + } else if (!pool) { + tcp_md5sig_users--; + spin_unlock(&tcp_md5sig_pool_lock); + cpu_relax(); + goto retry; + } else + spin_unlock(&tcp_md5sig_pool_lock); + + if (alloc) { + /* we cannot hold spinlock here because this may sleep. */ + struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(); + spin_lock(&tcp_md5sig_pool_lock); + if (!p) { + tcp_md5sig_users--; + spin_unlock(&tcp_md5sig_pool_lock); + return NULL; + } + pool = tcp_md5sig_pool; + if (pool) { + /* oops, it has already been assigned. */ + spin_unlock(&tcp_md5sig_pool_lock); + __tcp_free_md5sig_pool(p); + } else { + tcp_md5sig_pool = pool = p; + spin_unlock(&tcp_md5sig_pool_lock); + } + } + return pool; +} + +EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + +struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) +{ + struct tcp_md5sig_pool **p; + spin_lock(&tcp_md5sig_pool_lock); + p = tcp_md5sig_pool; + if (p) + tcp_md5sig_users++; + spin_unlock(&tcp_md5sig_pool_lock); + return (p ? *per_cpu_ptr(p, cpu) : NULL); +} + +EXPORT_SYMBOL(__tcp_get_md5sig_pool); + +void __tcp_put_md5sig_pool(void) { + __tcp_free_md5sig_pool(tcp_md5sig_pool); +} + +EXPORT_SYMBOL(__tcp_put_md5sig_pool); +#endif + extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4a8c96cdec7d..6ab3423674bb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2677,6 +2677,14 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, opt_rx->sack_ok) { TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; } +#ifdef CONFIG_TCP_MD5SIG + case TCPOPT_MD5SIG: + /* + * The MD5 Hash has already been + * checked (see tcp_v{4,6}_do_rcv()). + */ + break; +#endif }; ptr+=opsize-2; length-=opsize; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0ad0904bf56c..8c8e8112f98d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -78,6 +78,9 @@ #include #include +#include +#include + int sysctl_tcp_tw_reuse __read_mostly; int sysctl_tcp_low_latency __read_mostly; @@ -89,6 +92,13 @@ static struct socket *tcp_socket; void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); +#ifdef CONFIG_TCP_MD5SIG +static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr); +static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + __be32 saddr, __be32 daddr, struct tcphdr *th, + int protocol, int tcplen); +#endif + struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), .lhash_users = ATOMIC_INIT(0), @@ -526,11 +536,19 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) * Exception: precedence violation. We do not implement it in any case. */ -static void tcp_v4_send_reset(struct sk_buff *skb) +static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = skb->h.th; - struct tcphdr rth; + struct { + struct tcphdr th; +#ifdef CONFIG_TCP_MD5SIG + u32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)]; +#endif + } rep; struct ip_reply_arg arg; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif /* Never send a reset in response to a reset. */ if (th->rst) @@ -540,29 +558,50 @@ static void tcp_v4_send_reset(struct sk_buff *skb) return; /* Swap the send and the receive. */ - memset(&rth, 0, sizeof(struct tcphdr)); - rth.dest = th->source; - rth.source = th->dest; - rth.doff = sizeof(struct tcphdr) / 4; - rth.rst = 1; + memset(&rep, 0, sizeof(rep)); + rep.th.dest = th->source; + rep.th.source = th->dest; + rep.th.doff = sizeof(struct tcphdr) / 4; + rep.th.rst = 1; if (th->ack) { - rth.seq = th->ack_seq; + rep.th.seq = th->ack_seq; } else { - rth.ack = 1; - rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + - skb->len - (th->doff << 2)); + rep.th.ack = 1; + rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + + skb->len - (th->doff << 2)); } memset(&arg, 0, sizeof arg); - arg.iov[0].iov_base = (unsigned char *)&rth; - arg.iov[0].iov_len = sizeof rth; + arg.iov[0].iov_base = (unsigned char *)&rep; + arg.iov[0].iov_len = sizeof(rep.th); + +#ifdef CONFIG_TCP_MD5SIG + key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL; + if (key) { + rep.opt[0] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + /* Update length and the length the header thinks exists */ + arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; + rep.th.doff = arg.iov[0].iov_len / 4; + + tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1], + key, + skb->nh.iph->daddr, + skb->nh.iph->saddr, + &rep.th, IPPROTO_TCP, + arg.iov[0].iov_len); + } +#endif + arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, skb->nh.iph->saddr, /*XXX*/ sizeof(struct tcphdr), IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr, check) / 2; - ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth); + ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); @@ -572,15 +611,24 @@ static void tcp_v4_send_reset(struct sk_buff *skb) outside socket context is ugly, certainly. What can I do? */ -static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, +static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, + struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) { struct tcphdr *th = skb->h.th; struct { struct tcphdr th; - u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2]; + u32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2) +#ifdef CONFIG_TCP_MD5SIG + + (TCPOLEN_MD5SIG_ALIGNED >> 2) +#endif + ]; } rep; struct ip_reply_arg arg; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; + struct tcp_md5sig_key tw_key; +#endif memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&arg, 0, sizeof arg); @@ -588,12 +636,12 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, arg.iov[0].iov_base = (unsigned char *)&rep; arg.iov[0].iov_len = sizeof(rep.th); if (ts) { - rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | - TCPOLEN_TIMESTAMP); - rep.tsopt[1] = htonl(tcp_time_stamp); - rep.tsopt[2] = htonl(ts); - arg.iov[0].iov_len = sizeof(rep); + rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | + TCPOLEN_TIMESTAMP); + rep.opt[1] = htonl(tcp_time_stamp); + rep.opt[2] = htonl(ts); + arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED; } /* Swap the send and the receive. */ @@ -605,6 +653,44 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, rep.th.ack = 1; rep.th.window = htons(win); +#ifdef CONFIG_TCP_MD5SIG + /* + * The SKB holds an imcoming packet, but may not have a valid ->sk + * pointer. This is especially the case when we're dealing with a + * TIME_WAIT ack, because the sk structure is long gone, and only + * the tcp_timewait_sock remains. So the md5 key is stashed in that + * structure, and we use it in preference. I believe that (twsk || + * skb->sk) holds true, but we program defensively. + */ + if (!twsk && skb->sk) { + key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr); + } else if (twsk && twsk->tw_md5_keylen) { + tw_key.key = twsk->tw_md5_key; + tw_key.keylen = twsk->tw_md5_keylen; + key = &tw_key; + } else { + key = NULL; + } + + if (key) { + int offset = (ts) ? 3 : 0; + + rep.opt[offset++] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; + rep.th.doff = arg.iov[0].iov_len/4; + + tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset], + key, + skb->nh.iph->daddr, + skb->nh.iph->saddr, + &rep.th, IPPROTO_TCP, + arg.iov[0].iov_len); + } +#endif + arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, skb->nh.iph->saddr, /*XXX*/ arg.iov[0].iov_len, IPPROTO_TCP, 0); @@ -618,9 +704,9 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) { struct inet_timewait_sock *tw = inet_twsk(sk); - const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); + struct tcp_timewait_sock *tcptw = tcp_twsk(sk); - tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, + tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); inet_twsk_put(tw); @@ -628,7 +714,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) { - tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, + tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, + tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); } @@ -714,6 +801,461 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, return dopt; } +#ifdef CONFIG_TCP_MD5SIG +/* + * RFC2385 MD5 checksumming requires a mapping of + * IP address->MD5 Key. + * We need to maintain these in the sk structure. + */ + +/* Find the Key structure for an address. */ +static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + if (!tp->md5sig_info || !tp->md5sig_info->entries4) + return NULL; + for (i = 0; i < tp->md5sig_info->entries4; i++) { + if (tp->md5sig_info->keys4[i].addr == addr) + return (struct tcp_md5sig_key *)&tp->md5sig_info->keys4[i]; + } + return NULL; +} + +struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, + struct sock *addr_sk) +{ + return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr); +} + +EXPORT_SYMBOL(tcp_v4_md5_lookup); + +struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) +{ + return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); +} + +/* This can be called on a newly created socket, from other files */ +int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, + u8 *newkey, u8 newkeylen) +{ + /* Add Key to the list */ + struct tcp4_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + struct tcp4_md5sig_key *keys; + + key = (struct tcp4_md5sig_key *) tcp_v4_md5_do_lookup(sk, addr); + if (key) { + /* Pre-existing entry - just update that one. */ + kfree (key->key); + key->key = newkey; + key->keylen = newkeylen; + } else { + if (!tp->md5sig_info) { + tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); + if (!tp->md5sig_info) { + kfree(newkey); + return -ENOMEM; + } + } + if (tcp_alloc_md5sig_pool() == NULL) { + kfree(newkey); + return -ENOMEM; + } + if (tp->md5sig_info->alloced4 == tp->md5sig_info->entries4) { + keys = kmalloc((sizeof(struct tcp4_md5sig_key) * + (tp->md5sig_info->entries4 + 1)), GFP_ATOMIC); + if (!keys) { + kfree(newkey); + tcp_free_md5sig_pool(); + return -ENOMEM; + } + + if (tp->md5sig_info->entries4) + memcpy(keys, tp->md5sig_info->keys4, + (sizeof (struct tcp4_md5sig_key) * + tp->md5sig_info->entries4)); + + /* Free old key list, and reference new one */ + if (tp->md5sig_info->keys4) + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = keys; + tp->md5sig_info->alloced4++; + } + tp->md5sig_info->entries4++; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].addr = addr; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].key = newkey; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].keylen = newkeylen; + } + return 0; +} + +EXPORT_SYMBOL(tcp_v4_md5_do_add); + +static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk, + u8 *newkey, u8 newkeylen) +{ + return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr, + newkey, newkeylen); +} + +int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + for (i = 0; i < tp->md5sig_info->entries4; i++) { + if (tp->md5sig_info->keys4[i].addr == addr) { + /* Free the key */ + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4--; + + if (tp->md5sig_info->entries4 == 0) { + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + } else { + /* Need to do some manipulation */ + if (tp->md5sig_info->entries4 != i) + memcpy(&tp->md5sig_info->keys4[i], + &tp->md5sig_info->keys4[i+1], + (tp->md5sig_info->entries4 - i) + * sizeof (struct tcp4_md5sig_key)); + } + tcp_free_md5sig_pool(); + return 0; + } + } + return -ENOENT; +} + +EXPORT_SYMBOL(tcp_v4_md5_do_del); + +static void tcp_v4_clear_md5_list (struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + + /* Free each key, then the set of key keys, + * the crypto element, and then decrement our + * hold on the last resort crypto. + */ + if (tp->md5sig_info->entries4) { + int i; + for (i = 0; i < tp->md5sig_info->entries4; i++) + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4 = 0; + tcp_free_md5sig_pool(); + } + if (tp->md5sig_info->keys4) { + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + tp->md5sig_info->alloced4 = 0; + } +} + +static int tcp_v4_parse_md5_keys (struct sock *sk, char __user *optval, + int optlen) +{ + struct tcp_md5sig cmd; + struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; + u8 *newkey; + + if (optlen < sizeof(cmd)) + return -EINVAL; + + if (copy_from_user (&cmd, optval, sizeof(cmd))) + return -EFAULT; + + if (sin->sin_family != AF_INET) + return -EINVAL; + + if (!cmd.tcpm_key || !cmd.tcpm_keylen) { + if (!tcp_sk(sk)->md5sig_info) + return -ENOENT; + return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); + } + + if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) + return -EINVAL; + + if (!tcp_sk(sk)->md5sig_info) { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_md5sig_info *p; + + p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); + if (!p) + return -EINVAL; + + tp->md5sig_info = p; + + } + + newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + if (!newkey) + return -ENOMEM; + memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); + return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, + newkey, cmd.tcpm_keylen); +} + +static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + __be32 saddr, __be32 daddr, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct scatterlist sg[4]; + __u16 data_len; + int block = 0; +#ifdef CONFIG_TCP_MD5SIG_DEBUG + int i; +#endif + __u16 old_checksum; + struct tcp_md5sig_pool *hp; + struct tcp4_pseudohdr *bp; + struct hash_desc *desc; + int err; + unsigned int nbytes = 0; + + /* + * Okay, so RFC2385 is turned on for this connection, + * so we need to generate the MD5 hash for the packet now. + */ + + hp = tcp_get_md5sig_pool(); + if (!hp) + goto clear_hash_noput; + + bp = &hp->md5_blk.ip4; + desc = &hp->md5_desc; + + /* + * 1. the TCP pseudo-header (in the order: source IP address, + * destination IP address, zero-padded protocol number, and + * segment length) + */ + bp->saddr = saddr; + bp->daddr = daddr; + bp->pad = 0; + bp->protocol = protocol; + bp->len = htons(tcplen); + sg_set_buf(&sg[block++], bp, sizeof(*bp)); + nbytes += sizeof(*bp); + +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk("Calcuating hash for: "); + for (i = 0; i < sizeof (*bp); i++) + printk ("%02x ", (unsigned int)((unsigned char *)bp)[i]); + printk(" "); +#endif + + /* 2. the TCP header, excluding options, and assuming a + * checksum of zero/ + */ + old_checksum = th->check; + th->check = 0; + sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); + nbytes += sizeof(struct tcphdr); +#ifdef CONFIG_TCP_MD5SIG_DEBUG + for (i = 0; i < sizeof (struct tcphdr); i++) + printk (" %02x", (unsigned int)((unsigned char *)th)[i]); +#endif + /* 3. the TCP segment data (if any) */ + data_len = tcplen - (th->doff << 2); + if (data_len > 0) { + unsigned char *data = (unsigned char *)th + (th->doff << 2); + sg_set_buf(&sg[block++], data, data_len); + nbytes += data_len; + } + + /* 4. an independently-specified key or password, known to both + * TCPs and presumably connection-specific + */ + sg_set_buf(&sg[block++], key->key, key->keylen); + nbytes += key->keylen; + +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk (" and password: "); + for (i = 0; i < key->keylen; i++) + printk ("%02x ", (unsigned int)key->key[i]); +#endif + + /* Now store the Hash into the packet */ + err = crypto_hash_init(desc); + if (err) + goto clear_hash; + err = crypto_hash_update(desc, sg, nbytes); + if (err) + goto clear_hash; + err = crypto_hash_final(desc, md5_hash); + if (err) + goto clear_hash; + + /* Reset header, and free up the crypto */ + tcp_put_md5sig_pool(); + th->check = old_checksum; + +out: +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk(" result:"); + for (i = 0; i < 16; i++) + printk (" %02x", (unsigned int)(((u8*)md5_hash)[i])); + printk("\n"); +#endif + return 0; +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + goto out; +} + +int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, int protocol, + int tcplen) +{ + __be32 saddr, daddr; + + if (sk) { + saddr = inet_sk(sk)->saddr; + daddr = inet_sk(sk)->daddr; + } else { + struct rtable *rt = (struct rtable *)dst; + BUG_ON(!rt); + saddr = rt->rt_src; + daddr = rt->rt_dst; + } + return tcp_v4_do_calc_md5_hash(md5_hash, key, + saddr, daddr, + th, protocol, tcplen); +} + +EXPORT_SYMBOL(tcp_v4_calc_md5_hash); + +static int tcp_v4_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) +{ + /* + * This gets called for each TCP segment that arrives + * so we want to be efficient. + * We have 3 drop cases: + * o No MD5 hash and one expected. + * o MD5 hash and we're not expecting one. + * o MD5 hash and its wrong. + */ + __u8 *hash_location = NULL; + struct tcp_md5sig_key *hash_expected; + struct iphdr *iph = skb->nh.iph; + struct tcphdr *th = skb->h.th; + int length = (th->doff << 2) - sizeof (struct tcphdr); + int genhash; + unsigned char *ptr; + unsigned char newhash[16]; + + hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); + + /* + * If the TCP option length is less than the TCP_MD5SIG + * option length, then we can shortcut + */ + if (length < TCPOLEN_MD5SIG) { + if (hash_expected) + return 1; + else + return 0; + } + + /* Okay, we can't shortcut - we have to grub through the options */ + ptr = (unsigned char *)(th + 1); + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCPOPT_EOL: + goto done_opts; + case TCPOPT_NOP: + length--; + continue; + default: + opsize = *ptr++; + if (opsize < 2) + goto done_opts; + if (opsize > length) + goto done_opts; + + if (opcode == TCPOPT_MD5SIG) { + hash_location = ptr; + goto done_opts; + } + } + ptr += opsize-2; + length -= opsize; + } +done_opts: + /* We've parsed the options - do we have a hash? */ + if (!hash_expected && !hash_location) + return 0; + + if (hash_expected && !hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest)); + } + return 1; + } + + if (!hash_expected && hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest)); + } + return 1; + } + + /* Okay, so this is hash_expected and hash_location - + * so we need to calculate the checksum. + */ + genhash = tcp_v4_do_calc_md5_hash(newhash, + hash_expected, + iph->saddr, iph->daddr, + th, sk->sk_protocol, + skb->len); + + if (genhash || memcmp(hash_location, newhash, 16) != 0) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash failed for " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest), + genhash ? " tcp_v4_calc_md5_hash failed" : ""); +#ifdef CONFIG_TCP_MD5SIG_DEBUG + do { + int i; + printk("Received: "); + for (i = 0; i < 16; i++) + printk("%02x ", 0xff & (int)hash_location[i]); + printk("\n"); + printk("Calculated: "); + for (i = 0; i < 16; i++) + printk("%02x ", 0xff & (int)newhash[i]); + printk("\n"); + } while(0); +#endif + } + return 1; + } + return 0; +} + +#endif + struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), @@ -723,9 +1265,16 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; +struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_reqsk_md5_lookup, +#endif +}; + static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp_timewait_sock), .twsk_unique = tcp_twsk_unique, + .twsk_destructor= tcp_twsk_destructor, }; int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) @@ -773,6 +1322,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (!req) goto drop; +#ifdef CONFIG_TCP_MD5SIG + tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; +#endif + tcp_clear_options(&tmp_opt); tmp_opt.mss_clamp = 536; tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; @@ -891,6 +1444,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct inet_sock *newinet; struct tcp_sock *newtp; struct sock *newsk; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (sk_acceptq_is_full(sk)) goto exit_overflow; @@ -925,6 +1481,24 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->advmss = dst_metric(dst, RTAX_ADVMSS); tcp_initialize_rcv_mss(newsk); +#ifdef CONFIG_TCP_MD5SIG + /* Copy over the MD5 key from the original socket */ + if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) { + /* + * We're using one, so create a matching key + * on the newsk structure. If we fail to get + * memory, then we end up not copying the key + * across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + memcpy(newkey, key->key, key->keylen); + tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, + newkey, key->keylen); + } + } +#endif + __inet_hash(&tcp_hashinfo, newsk, 0); __inet_inherit_port(&tcp_hashinfo, sk, newsk); @@ -1000,10 +1574,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb) */ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) { + struct sock *rsk; +#ifdef CONFIG_TCP_MD5SIG + /* + * We really want to reject the packet as early as possible + * if: + * o We're expecting an MD5'd packet and this is no MD5 tcp option + * o There is an MD5 option and we're not expecting one + */ + if (tcp_v4_inbound_md5_hash (sk, skb)) + goto discard; +#endif + if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ TCP_CHECK_TIMER(sk); - if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) + if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) { + rsk = sk; goto reset; + } TCP_CHECK_TIMER(sk); return 0; } @@ -1017,20 +1605,24 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) goto discard; if (nsk != sk) { - if (tcp_child_process(sk, nsk, skb)) + if (tcp_child_process(sk, nsk, skb)) { + rsk = nsk; goto reset; + } return 0; } } TCP_CHECK_TIMER(sk); - if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) + if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) { + rsk = sk; goto reset; + } TCP_CHECK_TIMER(sk); return 0; reset: - tcp_v4_send_reset(skb); + tcp_v4_send_reset(rsk, skb); discard: kfree_skb(skb); /* Be careful here. If this function gets more complicated and @@ -1139,7 +1731,7 @@ no_tcp_socket: bad_packet: TCP_INC_STATS_BH(TCP_MIB_INERRS); } else { - tcp_v4_send_reset(skb); + tcp_v4_send_reset(NULL, skb); } discard_it: @@ -1262,6 +1854,15 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; +struct tcp_sock_af_ops tcp_sock_ipv4_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_md5_lookup, + .calc_md5_hash = tcp_v4_calc_md5_hash, + .md5_add = tcp_v4_md5_add_func, + .md5_parse = tcp_v4_parse_md5_keys, +#endif +}; + /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. */ @@ -1301,6 +1902,9 @@ static int tcp_v4_init_sock(struct sock *sk) icsk->icsk_af_ops = &ipv4_specific; icsk->icsk_sync_mss = tcp_sync_mss; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv4_specific; +#endif sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; @@ -1324,6 +1928,15 @@ int tcp_v4_destroy_sock(struct sock *sk) /* Cleans up our, hopefully empty, out_of_order_queue. */ __skb_queue_purge(&tp->out_of_order_queue); +#ifdef CONFIG_TCP_MD5SIG + /* Clean up the MD5 key list, if any */ + if (tp->md5sig_info) { + tcp_v4_clear_md5_list(sk); + kfree(tp->md5sig_info); + tp->md5sig_info = NULL; + } +#endif + #ifdef CONFIG_NET_DMA /* Cleans up our sk_async_wait_queue */ __skb_queue_purge(&sk->sk_async_wait_queue); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0163d9826907..ac55d8892cf1 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -306,6 +306,28 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) tw->tw_ipv6only = np->ipv6only; } #endif + +#ifdef CONFIG_TCP_MD5SIG + /* + * The timewait bucket does not have the key DB from the + * sock structure. We just make a quick copy of the + * md5 key being used (if indeed we are using one) + * so the timewait ack generating code has the key. + */ + do { + struct tcp_md5sig_key *key; + memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key)); + tcptw->tw_md5_keylen = 0; + key = tp->af_specific->md5_lookup(sk, sk); + if (key != NULL) { + memcpy(&tcptw->tw_md5_key, key->key, key->keylen); + tcptw->tw_md5_keylen = key->keylen; + if (tcp_alloc_md5sig_pool() == NULL) + BUG(); + } + } while(0); +#endif + /* Linkage updates. */ __inet_twsk_hashdance(tw, sk, &tcp_hashinfo); @@ -337,6 +359,17 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) tcp_done(sk); } +void tcp_twsk_destructor(struct sock *sk) +{ + struct tcp_timewait_sock *twsk = tcp_twsk(sk); +#ifdef CONFIG_TCP_MD5SIG + if (twsk->tw_md5_keylen) + tcp_put_md5sig_pool(); +#endif +} + +EXPORT_SYMBOL_GPL(tcp_twsk_destructor); + /* This is not only more efficient than what we used to do, it eliminates * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM * @@ -435,6 +468,11 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->rx_opt.ts_recent_stamp = 0; newtp->tcp_header_len = sizeof(struct tcphdr); } +#ifdef CONFIG_TCP_MD5SIG + newtp->md5sig_info = NULL; /*XXX*/ + if (newtp->af_specific->md5_lookup(sk, newsk)) + newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; +#endif if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len) newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; @@ -617,6 +655,30 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, req, NULL); if (child == NULL) goto listen_overflow; +#ifdef CONFIG_TCP_MD5SIG + else { + /* Copy over the MD5 key from the original socket */ + struct tcp_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + key = tp->af_specific->md5_lookup(sk, child); + if (key != NULL) { + /* + * We're using one, so create a matching key on the + * newsk structure. If we fail to get memory then we + * end up not copying the key across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + if (!tcp_alloc_md5sig_pool()) + BUG(); + memcpy(newkey, key->key, key->keylen); + tp->af_specific->md5_add(child, child, + newkey, + key->keylen); + } + } + } +#endif inet_csk_reqsk_queue_unlink(sk, req, prev); inet_csk_reqsk_queue_removed(sk, req); @@ -633,7 +695,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, embryonic_reset: NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS); if (!(flg & TCP_FLAG_RST)) - req->rsk_ops->send_reset(skb); + req->rsk_ops->send_reset(sk, skb); inet_csk_reqsk_queue_drop(sk, req, prev); return NULL; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6a8581ab9a23..32c1a972fa31 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -270,7 +270,7 @@ static u16 tcp_select_window(struct sock *sk) } static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, - __u32 tstamp) + __u32 tstamp, __u8 **md5_hash) { if (tp->rx_opt.tstamp_ok) { *ptr++ = htonl((TCPOPT_NOP << 24) | @@ -298,16 +298,29 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, tp->rx_opt.eff_sacks--; } } +#ifdef CONFIG_TCP_MD5SIG + if (md5_hash) { + *ptr++ = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + *md5_hash = (__u8 *)ptr; + } +#endif } /* Construct a tcp options header for a SYN or SYN_ACK packet. * If this is every changed make sure to change the definition of * MAX_SYN_SIZE to match the new maximum number of options that you * can generate. + * + * Note - that with the RFC2385 TCP option, we make room for the + * 16 byte MD5 hash. This will be filled in later, so the pointer for the + * location to be filled is passed back up. */ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, int offer_wscale, int wscale, __u32 tstamp, - __u32 ts_recent) + __u32 ts_recent, __u8 **md5_hash) { /* We always get an MSS option. * The option bytes which will be seen in normal data @@ -346,6 +359,20 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale)); +#ifdef CONFIG_TCP_MD5SIG + /* + * If MD5 is enabled, then we set the option, and include the size + * (always 18). The actual MD5 hash is added just before the + * packet is sent. + */ + if (md5_hash) { + *ptr++ = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + *md5_hash = (__u8 *) ptr; + } +#endif } /* This routine actually transmits TCP packets queued in by @@ -366,6 +393,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, struct tcp_sock *tp; struct tcp_skb_cb *tcb; int tcp_header_size; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *md5; + __u8 *md5_hash_location; +#endif struct tcphdr *th; int sysctl_flags; int err; @@ -424,6 +455,16 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (tcp_packets_in_flight(tp) == 0) tcp_ca_event(sk, CA_EVENT_TX_START); +#ifdef CONFIG_TCP_MD5SIG + /* + * Are we doing MD5 on this segment? If so - make + * room for it. + */ + md5 = tp->af_specific->md5_lookup(sk, sk); + if (md5) + tcp_header_size += TCPOLEN_MD5SIG_ALIGNED; +#endif + th = (struct tcphdr *) skb_push(skb, tcp_header_size); skb->h.th = th; @@ -460,13 +501,34 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, (sysctl_flags & SYSCTL_FLAG_WSCALE), tp->rx_opt.rcv_wscale, tcb->when, - tp->rx_opt.ts_recent); + tp->rx_opt.ts_recent, + +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL); } else { tcp_build_and_update_options((__be32 *)(th + 1), - tp, tcb->when); + tp, tcb->when, +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL); TCP_ECN_send(sk, tp, skb, tcp_header_size); } +#ifdef CONFIG_TCP_MD5SIG + /* Calculate the MD5 hash, as we have all we need now */ + if (md5) { + tp->af_specific->calc_md5_hash(md5_hash_location, + md5, + sk, NULL, NULL, + skb->h.th, + sk->sk_protocol, + skb->len); + } +#endif + icsk->icsk_af_ops->send_check(sk, skb->len, skb); if (likely(tcb->flags & TCPCB_FLAG_ACK)) @@ -840,6 +902,11 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) mss_now -= (TCPOLEN_SACK_BASE_ALIGNED + (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK)); +#ifdef CONFIG_TCP_MD5SIG + if (tp->af_specific->md5_lookup(sk, sk)) + mss_now -= TCPOLEN_MD5SIG_ALIGNED; +#endif + xmit_size_goal = mss_now; if (doing_tso) { @@ -2033,6 +2100,10 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct tcphdr *th; int tcp_header_size; struct sk_buff *skb; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *md5; + __u8 *md5_hash_location; +#endif skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); if (skb == NULL) @@ -2048,6 +2119,13 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) + /* SACK_PERM is in the place of NOP NOP of TS */ ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0)); + +#ifdef CONFIG_TCP_MD5SIG + /* Are we doing MD5 on this segment? If so - make room for it */ + md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); + if (md5) + tcp_header_size += TCPOLEN_MD5SIG_ALIGNED; +#endif skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size); memset(th, 0, sizeof(struct tcphdr)); @@ -2085,11 +2163,29 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok, ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale, TCP_SKB_CB(skb)->when, - req->ts_recent); + req->ts_recent, + ( +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL) + ); skb->csum = 0; th->doff = (tcp_header_size >> 2); TCP_INC_STATS(TCP_MIB_OUTSEGS); + +#ifdef CONFIG_TCP_MD5SIG + /* Okay, we have all we need - do the md5 hash if needed */ + if (md5) { + tp->af_specific->calc_md5_hash(md5_hash_location, + md5, + NULL, dst, req, + skb->h.th, sk->sk_protocol, + skb->len); + } +#endif + return skb; } @@ -2108,6 +2204,11 @@ static void tcp_connect_init(struct sock *sk) tp->tcp_header_len = sizeof(struct tcphdr) + (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0); +#ifdef CONFIG_TCP_MD5SIG + if (tp->af_specific->md5_lookup(sk, sk) != NULL) + tp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; +#endif + /* If user gave his TCP_MAXSEG, record it to clamp */ if (tp->rx_opt.user_mss) tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9a88395a7629..663d1d238014 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -66,10 +66,13 @@ #include #include +#include +#include + /* Socket used for sending RSTs and ACKs */ static struct socket *tcp6_socket; -static void tcp_v6_send_reset(struct sk_buff *skb); +static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb); @@ -78,6 +81,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); static struct inet_connection_sock_af_ops ipv6_mapped; static struct inet_connection_sock_af_ops ipv6_specific; +static struct tcp_sock_af_ops tcp_sock_ipv6_specific; +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; static int tcp_v6_get_port(struct sock *sk, unsigned short snum) { @@ -208,6 +213,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_af_ops = &ipv6_mapped; sk->sk_backlog_rcv = tcp_v4_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_mapped_specific; +#endif err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); @@ -215,6 +223,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_ext_hdr_len = exthdrlen; icsk->icsk_af_ops = &ipv6_specific; sk->sk_backlog_rcv = tcp_v6_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_specific; +#endif goto failure; } else { ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), @@ -518,6 +529,396 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } +#ifdef CONFIG_TCP_MD5SIG +static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, + struct in6_addr *addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + BUG_ON(tp == NULL); + + if (!tp->md5sig_info || !tp->md5sig_info->entries6) + return NULL; + + for (i = 0; i < tp->md5sig_info->entries6; i++) { + if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) + return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; + } + return NULL; +} + +static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, + struct sock *addr_sk) +{ + return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr); +} + +static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) +{ + return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); +} + +static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, + char *newkey, u8 newkeylen) +{ + /* Add key to the list */ + struct tcp6_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + struct tcp6_md5sig_key *keys; + + key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); + if (key) { + /* modify existing entry - just update that one */ + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; + } else { + /* reallocate new list if current one is full. */ + if (!tp->md5sig_info) { + tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); + if (!tp->md5sig_info) { + kfree(newkey); + return -ENOMEM; + } + } + tcp_alloc_md5sig_pool(); + if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) { + keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) * + (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); + + if (!keys) { + tcp_free_md5sig_pool(); + kfree(newkey); + return -ENOMEM; + } + + if (tp->md5sig_info->entries6) + memmove(keys, tp->md5sig_info->keys6, + (sizeof (tp->md5sig_info->keys6[0]) * + tp->md5sig_info->entries6)); + + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = keys; + tp->md5sig_info->alloced6++; + } + + ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, + peer); + tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; + tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; + + tp->md5sig_info->entries6++; + } + return 0; +} + +static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, + u8 *newkey, __u8 newkeylen) +{ + return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr, + newkey, newkeylen); +} + +static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + for (i = 0; i < tp->md5sig_info->entries6; i++) { + if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { + /* Free the key */ + kfree(tp->md5sig_info->keys6[i].key); + tp->md5sig_info->entries6--; + + if (tp->md5sig_info->entries6 == 0) { + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = NULL; + + tcp_free_md5sig_pool(); + + return 0; + } else { + /* shrink the database */ + if (tp->md5sig_info->entries6 != i) + memmove(&tp->md5sig_info->keys6[i], + &tp->md5sig_info->keys6[i+1], + (tp->md5sig_info->entries6 - i) + * sizeof (tp->md5sig_info->keys6[0])); + } + } + } + return -ENOENT; +} + +static void tcp_v6_clear_md5_list (struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + if (tp->md5sig_info->entries6) { + for (i = 0; i < tp->md5sig_info->entries6; i++) + kfree(tp->md5sig_info->keys6[i].key); + tp->md5sig_info->entries6 = 0; + tcp_free_md5sig_pool(); + } + + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = NULL; + tp->md5sig_info->alloced6 = 0; + + if (tp->md5sig_info->entries4) { + for (i = 0; i < tp->md5sig_info->entries4; i++) + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4 = 0; + tcp_free_md5sig_pool(); + } + + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + tp->md5sig_info->alloced4 = 0; +} + +static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, + int optlen) +{ + struct tcp_md5sig cmd; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; + u8 *newkey; + + if (optlen < sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, optval, sizeof(cmd))) + return -EFAULT; + + if (sin6->sin6_family != AF_INET6) + return -EINVAL; + + if (!cmd.tcpm_keylen) { + if (!tcp_sk(sk)->md5sig_info) + return -ENOENT; + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) + return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]); + return tcp_v6_md5_do_del(sk, &sin6->sin6_addr); + } + + if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) + return -EINVAL; + + if (!tcp_sk(sk)->md5sig_info) { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_md5sig_info *p; + + p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); + if (!p) + return -ENOMEM; + + tp->md5sig_info = p; + } + + newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + if (!newkey) + return -ENOMEM; + memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { + return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], + newkey, cmd.tcpm_keylen); + } + return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); +} + +static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct in6_addr *saddr, + struct in6_addr *daddr, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct scatterlist sg[4]; + __u16 data_len; + int block = 0; + __u16 cksum; + struct tcp_md5sig_pool *hp; + struct tcp6_pseudohdr *bp; + struct hash_desc *desc; + int err; + unsigned int nbytes = 0; + + hp = tcp_get_md5sig_pool(); + if (!hp) { + printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); + goto clear_hash_noput; + } + bp = &hp->md5_blk.ip6; + desc = &hp->md5_desc; + + /* 1. TCP pseudo-header (RFC2460) */ + ipv6_addr_copy(&bp->saddr, saddr); + ipv6_addr_copy(&bp->daddr, daddr); + bp->len = htonl(tcplen); + bp->protocol = htonl(protocol); + + sg_set_buf(&sg[block++], bp, sizeof(*bp)); + nbytes += sizeof(*bp); + + /* 2. TCP header, excluding options */ + cksum = th->check; + th->check = 0; + sg_set_buf(&sg[block++], th, sizeof(*th)); + nbytes += sizeof(*th); + + /* 3. TCP segment data (if any) */ + data_len = tcplen - (th->doff << 2); + if (data_len > 0) { + u8 *data = (u8 *)th + (th->doff << 2); + sg_set_buf(&sg[block++], data, data_len); + nbytes += data_len; + } + + /* 4. shared key */ + sg_set_buf(&sg[block++], key->key, key->keylen); + nbytes += key->keylen; + + /* Now store the hash into the packet */ + err = crypto_hash_init(desc); + if (err) { + printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); + goto clear_hash; + } + err = crypto_hash_update(desc, sg, nbytes); + if (err) { + printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); + goto clear_hash; + } + err = crypto_hash_final(desc, md5_hash); + if (err) { + printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); + goto clear_hash; + } + + /* Reset header, and free up the crypto */ + tcp_put_md5sig_pool(); + th->check = cksum; +out: + return 0; +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + goto out; +} + +static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct in6_addr *saddr, *daddr; + + if (sk) { + saddr = &inet6_sk(sk)->saddr; + daddr = &inet6_sk(sk)->daddr; + } else { + saddr = &inet6_rsk(req)->loc_addr; + daddr = &inet6_rsk(req)->rmt_addr; + } + return tcp_v6_do_calc_md5_hash(md5_hash, key, + saddr, daddr, + th, protocol, tcplen); +} + +static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) +{ + __u8 *hash_location = NULL; + struct tcp_md5sig_key *hash_expected; + struct ipv6hdr *ip6h = skb->nh.ipv6h; + struct tcphdr *th = skb->h.th; + int length = (th->doff << 2) - sizeof (*th); + int genhash; + u8 *ptr; + u8 newhash[16]; + + hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); + + /* If the TCP option is too short, we can short cut */ + if (length < TCPOLEN_MD5SIG) + return hash_expected ? 1 : 0; + + /* parse options */ + ptr = (u8*)(th + 1); + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch(opcode) { + case TCPOPT_EOL: + goto done_opts; + case TCPOPT_NOP: + length--; + continue; + default: + opsize = *ptr++; + if (opsize < 2 || opsize > length) + goto done_opts; + if (opcode == TCPOPT_MD5SIG) { + hash_location = ptr; + goto done_opts; + } + } + ptr += opsize - 2; + length -= opsize; + } + +done_opts: + /* do we have a hash as expected? */ + if (!hash_expected) { + if (!hash_location) + return 0; + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + + if (!hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash expected but NOT found " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + + /* check the signature */ + genhash = tcp_v6_do_calc_md5_hash(newhash, + hash_expected, + &ip6h->saddr, &ip6h->daddr, + th, sk->sk_protocol, + skb->len); + if (genhash || memcmp(hash_location, newhash, 16) != 0) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash %s for " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + genhash ? "failed" : "mismatch", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + return 0; +} +#endif + static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), @@ -527,9 +928,16 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; +struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v6_reqsk_md5_lookup, +#endif +}; + static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp6_timewait_sock), .twsk_unique = tcp_twsk_unique, + .twsk_destructor= tcp_twsk_destructor, }; static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) @@ -566,11 +974,15 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } -static void tcp_v6_send_reset(struct sk_buff *skb) +static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = skb->h.th, *t1; struct sk_buff *buff; struct flowi fl; + int tot_len = sizeof(*th); +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (th->rst) return; @@ -578,25 +990,35 @@ static void tcp_v6_send_reset(struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) return; +#ifdef CONFIG_TCP_MD5SIG + if (sk) + key = tcp_v6_md5_do_lookup(sk, &skb->nh.ipv6h->daddr); + else + key = NULL; + + if (key) + tot_len += TCPOLEN_MD5SIG_ALIGNED; +#endif + /* * We need to grab some memory, and put together an RST, * and then put it into the queue to be sent. */ - buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr), + buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (buff == NULL) return; - skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr)); + skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); - t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr)); + t1 = (struct tcphdr *) skb_push(buff, tot_len); /* Swap the send and the receive. */ memset(t1, 0, sizeof(*t1)); t1->dest = th->source; t1->source = th->dest; - t1->doff = sizeof(*t1)/4; + t1->doff = tot_len / 4; t1->rst = 1; if(th->ack) { @@ -607,6 +1029,22 @@ static void tcp_v6_send_reset(struct sk_buff *skb) + skb->len - (th->doff<<2)); } +#ifdef CONFIG_TCP_MD5SIG + if (key) { + u32 *opt = (u32*)(t1 + 1); + opt[0] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + tcp_v6_do_calc_md5_hash((__u8*)&opt[1], + key, + &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr, + t1, IPPROTO_TCP, + tot_len); + } +#endif + buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); memset(&fl, 0, sizeof(fl)); @@ -637,15 +1075,37 @@ static void tcp_v6_send_reset(struct sk_buff *skb) kfree_skb(buff); } -static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) +static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, + struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) { struct tcphdr *th = skb->h.th, *t1; struct sk_buff *buff; struct flowi fl; int tot_len = sizeof(struct tcphdr); + u32 *topt; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; + struct tcp_md5sig_key tw_key; +#endif + +#ifdef CONFIG_TCP_MD5SIG + if (!tw && skb->sk) { + key = tcp_v6_md5_do_lookup(skb->sk, &skb->nh.ipv6h->daddr); + } else if (tw && tw->tw_md5_keylen) { + tw_key.key = tw->tw_md5_key; + tw_key.keylen = tw->tw_md5_keylen; + key = &tw_key; + } else { + key = NULL; + } +#endif if (ts) tot_len += TCPOLEN_TSTAMP_ALIGNED; +#ifdef CONFIG_TCP_MD5SIG + if (key) + tot_len += TCPOLEN_MD5SIG_ALIGNED; +#endif buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); @@ -665,15 +1125,29 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 t1->ack_seq = htonl(ack); t1->ack = 1; t1->window = htons(win); + + topt = (u32*)(t1 + 1); if (ts) { - u32 *ptr = (u32*)(t1 + 1); - *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); - *ptr++ = htonl(tcp_time_stamp); - *ptr = htonl(ts); + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); + *topt++ = htonl(tcp_time_stamp); + *topt = htonl(ts); } +#ifdef CONFIG_TCP_MD5SIG + if (key) { + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); + tcp_v6_do_calc_md5_hash((__u8 *)topt, + key, + &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr, + t1, IPPROTO_TCP, + tot_len); + } +#endif + buff->csum = csum_partial((char *)t1, tot_len, 0); memset(&fl, 0, sizeof(fl)); @@ -704,9 +1178,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) { struct inet_timewait_sock *tw = inet_twsk(sk); - const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); + struct tcp_timewait_sock *tcptw = tcp_twsk(sk); - tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, + tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); @@ -715,7 +1189,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) { - tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); + tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); } @@ -786,6 +1260,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (req == NULL) goto drop; +#ifdef CONFIG_TCP_MD5SIG + tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; +#endif + tcp_clear_options(&tmp_opt); tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); tmp_opt.user_mss = tp->rx_opt.user_mss; @@ -844,6 +1322,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct tcp_sock *newtp; struct sock *newsk; struct ipv6_txoptions *opt; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (skb->protocol == htons(ETH_P_IP)) { /* @@ -874,6 +1355,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; newsk->sk_backlog_rcv = tcp_v4_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + newtp->af_specific = &tcp_sock_ipv6_mapped_specific; +#endif + newnp->pktoptions = NULL; newnp->opt = NULL; newnp->mcast_oif = inet6_iif(skb); @@ -1008,6 +1493,23 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; +#ifdef CONFIG_TCP_MD5SIG + /* Copy over the MD5 key from the original socket */ + if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) { + /* We're using one, so create a matching key + * on the newsk structure. If we fail to get + * memory, then we end up not copying the key + * across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + memcpy(newkey, key->key, key->keylen); + tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, + newkey, key->keylen); + } + } +#endif + __inet6_hash(&tcp_hashinfo, newsk); inet_inherit_port(&tcp_hashinfo, sk, newsk); @@ -1067,6 +1569,11 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_do_rcv(sk, skb); +#ifdef CONFIG_TCP_MD5SIG + if (tcp_v6_inbound_md5_hash (sk, skb)) + goto discard; +#endif + if (sk_filter(sk, skb)) goto discard; @@ -1132,7 +1639,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - tcp_v6_send_reset(skb); + tcp_v6_send_reset(sk, skb); discard: if (opt_skb) __kfree_skb(opt_skb); @@ -1257,7 +1764,7 @@ no_tcp_socket: bad_packet: TCP_INC_STATS_BH(TCP_MIB_INERRS); } else { - tcp_v6_send_reset(skb); + tcp_v6_send_reset(NULL, skb); } discard_it: @@ -1336,6 +1843,15 @@ static struct inet_connection_sock_af_ops ipv6_specific = { #endif }; +static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v6_md5_lookup, + .calc_md5_hash = tcp_v6_calc_md5_hash, + .md5_add = tcp_v6_md5_add_func, + .md5_parse = tcp_v6_parse_md5_keys, +#endif +}; + /* * TCP over IPv4 via INET6 API */ @@ -1358,6 +1874,15 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { #endif }; +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_md5_lookup, + .calc_md5_hash = tcp_v4_calc_md5_hash, + .md5_add = tcp_v6_md5_add_func, + .md5_parse = tcp_v6_parse_md5_keys, +#endif +}; + /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. */ @@ -1397,6 +1922,10 @@ static int tcp_v6_init_sock(struct sock *sk) sk->sk_write_space = sk_stream_write_space; sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_specific; +#endif + sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; @@ -1407,6 +1936,11 @@ static int tcp_v6_init_sock(struct sock *sk) static int tcp_v6_destroy_sock(struct sock *sk) { +#ifdef CONFIG_TCP_MD5SIG + /* Clean up the MD5 key list */ + if (tcp_sk(sk)->md5sig_info) + tcp_v6_clear_md5_list(sk); +#endif tcp_v4_destroy_sock(sk); return inet6_destroy_sock(sk); } -- cgit v1.2.3-70-g09d2 From 81878d27fdd297a33f3cfcf29483fe1abaf26dec Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 14 Nov 2006 19:45:27 -0800 Subject: [GENL]: Add genlmsg_reply() to simply unicast replies to requests A generic netlink user has no interest in knowing how to address the source of the original request. Signed-off-by: Thomas Graf Acked-by: Paul Moore Signed-off-by: David S. Miller --- include/net/genetlink.h | 10 ++++++++++ net/netlabel/netlabel_cipso_v4.c | 2 +- net/netlabel/netlabel_mgmt.c | 4 ++-- net/netlabel/netlabel_unlabeled.c | 2 +- net/netlink/genetlink.c | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 2010465fa7d4..797c18b5041f 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -149,6 +149,16 @@ static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid) return nlmsg_unicast(genl_sock, skb, pid); } +/** + * genlmsg_reply - reply to a request + * @skb: netlink message to be sent back + * @info: receiver information + */ +static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info) +{ + return genlmsg_unicast(skb, info->snd_pid); +} + /** * gennlmsg_data - head of message payload * @gnlh: genetlink messsage header diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index f1788bd290f8..52628878524c 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -568,7 +568,7 @@ list_start: genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto list_failure; diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index c529622ff0b7..784693735e0d 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -390,7 +390,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto listdef_failure; return 0; @@ -512,7 +512,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto version_failure; return 0; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 219dccade4e1..57dd07b51be6 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -160,7 +160,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto list_failure; return 0; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 70d60c818897..0249a56a9aad 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -529,7 +529,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) goto errout; } - err = genlmsg_unicast(msg, info->snd_pid); + err = genlmsg_reply(msg, info); errout: return err; } -- cgit v1.2.3-70-g09d2 From 17c157c889f4b07258af6bfec9e4e9dcf3c00178 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 14 Nov 2006 19:46:02 -0800 Subject: [GENL]: Add genlmsg_put_reply() to simplify building reply headers By modyfing genlmsg_put() to take a genl_family and by adding genlmsg_put_reply() the process of constructing the netlink and generic netlink headers is simplified. Signed-off-by: Thomas Graf Acked-by: Paul Moore Signed-off-by: David S. Miller --- include/net/genetlink.h | 31 ++++++++++++++++++++++++------- kernel/taskstats.c | 8 ++------ net/netlabel/netlabel_cipso_v4.c | 17 +++++------------ net/netlabel/netlabel_mgmt.c | 34 ++++++++++------------------------ net/netlabel/netlabel_unlabeled.c | 8 ++------ net/netlabel/netlabel_user.h | 31 ------------------------------- net/netlink/genetlink.c | 17 ++++++++--------- 7 files changed, 51 insertions(+), 95 deletions(-) (limited to 'net') diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 797c18b5041f..7fd131c9a8cc 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -79,33 +79,50 @@ extern struct sock *genl_sock; * @skb: socket buffer holding the message * @pid: netlink pid the message is addressed to * @seq: sequence number (usually the one of the sender) - * @type: netlink message type - * @hdrlen: length of the user specific header + * @family: generic netlink family * @flags netlink message flags * @cmd: generic netlink command - * @version: version * * Returns pointer to user specific header */ static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, - int type, int hdrlen, int flags, - u8 cmd, u8 version) + struct genl_family *family, int flags, u8 cmd) { struct nlmsghdr *nlh; struct genlmsghdr *hdr; - nlh = nlmsg_put(skb, pid, seq, type, GENL_HDRLEN + hdrlen, flags); + nlh = nlmsg_put(skb, pid, seq, family->id, GENL_HDRLEN + + family->hdrsize, flags); if (nlh == NULL) return NULL; hdr = nlmsg_data(nlh); hdr->cmd = cmd; - hdr->version = version; + hdr->version = family->version; hdr->reserved = 0; return (char *) hdr + GENL_HDRLEN; } +/** + * genlmsg_put_reply - Add generic netlink header to a reply message + * @skb: socket buffer holding the message + * @info: receiver info + * @family: generic netlink family + * @flags: netlink message flags + * @cmd: generic netlink command + * + * Returns pointer to user specific header + */ +static inline void *genlmsg_put_reply(struct sk_buff *skb, + struct genl_info *info, + struct genl_family *family, + int flags, u8 cmd) +{ + return genlmsg_put(skb, info->snd_pid, info->snd_seq, family, + flags, cmd); +} + /** * genlmsg_end - Finalize a generic netlink message * @skb: socket buffer the message is stored in diff --git a/kernel/taskstats.c b/kernel/taskstats.c index faa5239813ce..d3d28919d4b4 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -85,13 +85,9 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, int seq = get_cpu_var(taskstats_seqnum)++; put_cpu_var(taskstats_seqnum); - reply = genlmsg_put(skb, 0, seq, - family.id, 0, 0, - cmd, family.version); + reply = genlmsg_put(skb, 0, seq, &family, 0, cmd); } else - reply = genlmsg_put(skb, info->snd_pid, info->snd_seq, - family.id, 0, 0, - cmd, family.version); + reply = genlmsg_put_reply(skb, info, &family, 0, cmd); if (reply == NULL) { nlmsg_free(skb); return -EINVAL; diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 52628878524c..fe9851fac85d 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -457,12 +457,8 @@ list_start: ret_val = -ENOMEM; goto list_failure; } - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_cipsov4_gnl_family.id, - 0, - NLBL_CIPSOV4_C_LIST); + data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family, + 0, NLBL_CIPSOV4_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; @@ -607,12 +603,9 @@ static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; void *data; - data = netlbl_netlink_hdr_put(cb_arg->skb, - NETLINK_CB(cb_arg->nl_cb->skb).pid, - cb_arg->seq, - netlbl_cipsov4_gnl_family.id, - NLM_F_MULTI, - NLBL_CIPSOV4_C_LISTALL); + data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, + cb_arg->seq, &netlbl_cipsov4_gnl_family, + NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL); if (data == NULL) goto listall_cb_failure; diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 784693735e0d..e8c80f33f3d7 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -188,12 +188,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) struct netlbl_domhsh_walk_arg *cb_arg = arg; void *data; - data = netlbl_netlink_hdr_put(cb_arg->skb, - NETLINK_CB(cb_arg->nl_cb->skb).pid, - cb_arg->seq, - netlbl_mgmt_gnl_family.id, - NLM_F_MULTI, - NLBL_MGMT_C_LISTALL); + data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, + cb_arg->seq, &netlbl_mgmt_gnl_family, + NLM_F_MULTI, NLBL_MGMT_C_LISTALL); if (data == NULL) goto listall_cb_failure; @@ -359,12 +356,8 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_mgmt_gnl_family.id, - 0, - NLBL_MGMT_C_LISTDEF); + data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, + 0, NLBL_MGMT_C_LISTDEF); if (data == NULL) goto listdef_failure; @@ -422,12 +415,9 @@ static int netlbl_mgmt_protocols_cb(struct sk_buff *skb, int ret_val = -ENOMEM; void *data; - data = netlbl_netlink_hdr_put(skb, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - netlbl_mgmt_gnl_family.id, - NLM_F_MULTI, - NLBL_MGMT_C_PROTOCOLS); + data = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, + &netlbl_mgmt_gnl_family, NLM_F_MULTI, + NLBL_MGMT_C_PROTOCOLS); if (data == NULL) goto protocols_cb_failure; @@ -495,12 +485,8 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_mgmt_gnl_family.id, - 0, - NLBL_MGMT_C_VERSION); + data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, + 0, NLBL_MGMT_C_VERSION); if (data == NULL) goto version_failure; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 57dd07b51be6..a1d4ae51db04 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -141,12 +141,8 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) goto list_failure; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_unlabel_gnl_family.id, - 0, - NLBL_UNLABEL_C_LIST); + data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, + 0, NLBL_UNLABEL_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h index 47967ef32964..6d7f4ab46c2b 100644 --- a/net/netlabel/netlabel_user.h +++ b/net/netlabel/netlabel_user.h @@ -41,37 +41,6 @@ /* NetLabel NETLINK helper functions */ -/** - * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff - * @skb: the packet - * @pid: the PID of the receipient - * @seq: the sequence number - * @type: the generic NETLINK message family type - * @cmd: command - * - * Description: - * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr - * struct to the packet. Returns a pointer to the start of the payload buffer - * on success or NULL on failure. - * - */ -static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, - u32 pid, - u32 seq, - int type, - int flags, - u8 cmd) -{ - return genlmsg_put(skb, - pid, - seq, - type, - 0, - flags, - cmd, - NETLBL_PROTO_VERSION); -} - /** * netlbl_netlink_auditinfo - Fetch the audit information from a NETLINK msg * @skb: the packet diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0249a56a9aad..8903ef93db5b 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -384,6 +384,13 @@ static void genl_rcv(struct sock *sk, int len) * Controller **************************************************************************/ +static struct genl_family genl_ctrl = { + .id = GENL_ID_CTRL, + .name = "nlctrl", + .version = 0x1, + .maxattr = CTRL_ATTR_MAX, +}; + static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, u32 flags, struct sk_buff *skb, u8 cmd) { @@ -392,8 +399,7 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, void *hdr; int idx = 1; - hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd, - family->version); + hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); if (hdr == NULL) return -1; @@ -562,13 +568,6 @@ static struct genl_ops genl_ctrl_ops = { .policy = ctrl_policy, }; -static struct genl_family genl_ctrl = { - .id = GENL_ID_CTRL, - .name = "nlctrl", - .version = 0x1, - .maxattr = CTRL_ATTR_MAX, -}; - static int __init genl_init(void) { int i, err; -- cgit v1.2.3-70-g09d2 From a928630a2ffeaf6aa9a6b78456935b6ab1be3066 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Nov 2006 19:53:22 -0800 Subject: [TCP]: Fix some warning when MD5 is disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just some mis-placed ifdefs: net/ipv4/tcp_minisocks.c: In function ‘tcp_twsk_destructor’: net/ipv4/tcp_minisocks.c:364: warning: unused variable ‘twsk’ net/ipv6/tcp_ipv6.c:1846: warning: ‘tcp_sock_ipv6_specific’ defined but not used net/ipv6/tcp_ipv6.c:1877: warning: ‘tcp_sock_ipv6_mapped_specific’ defined but not used Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 2 +- net/ipv6/tcp_ipv6.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index ac55d8892cf1..4a0ee901a888 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -361,8 +361,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) void tcp_twsk_destructor(struct sock *sk) { - struct tcp_timewait_sock *twsk = tcp_twsk(sk); #ifdef CONFIG_TCP_MD5SIG + struct tcp_timewait_sock *twsk = tcp_twsk(sk); if (twsk->tw_md5_keylen) tcp_put_md5sig_pool(); #endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 663d1d238014..edef7eef8341 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -81,8 +81,10 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); static struct inet_connection_sock_af_ops ipv6_mapped; static struct inet_connection_sock_af_ops ipv6_specific; +#ifdef CONFIG_TCP_MD5SIG static struct tcp_sock_af_ops tcp_sock_ipv6_specific; static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; +#endif static int tcp_v6_get_port(struct sock *sk, unsigned short snum) { @@ -1843,14 +1845,14 @@ static struct inet_connection_sock_af_ops ipv6_specific = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { .md5_lookup = tcp_v6_md5_lookup, .calc_md5_hash = tcp_v6_calc_md5_hash, .md5_add = tcp_v6_md5_add_func, .md5_parse = tcp_v6_parse_md5_keys, -#endif }; +#endif /* * TCP over IPv4 via INET6 API @@ -1874,14 +1876,14 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, .md5_add = tcp_v6_md5_add_func, .md5_parse = tcp_v6_parse_md5_keys, -#endif }; +#endif /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. -- cgit v1.2.3-70-g09d2 From 04561c1fe7b067a8250e6caaf168256783580c4c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 14 Nov 2006 19:53:58 -0800 Subject: [IPv6] iflink: Convert IPv6's RTM_GETLINK to use the new netlink api By replacing the current method of exporting the device configuration which included allocating a temporary buffer, copying ipv6_devconf into it and copying that buffer into the message with a method that uses nla_reserve() allowing to copy the device configuration directly into the skb data buffer, a GFP_ATOMIC allocation could be removed. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 79 +++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 42 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 967ea320a9ca..46cd941d296f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3360,6 +3360,8 @@ errout: static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, __s32 *array, int bytes) { + BUG_ON(bytes < (DEVCONF_MAX * 4)); + memset(array, 0, bytes); array[DEVCONF_FORWARDING] = cnf->forwarding; array[DEVCONF_HOPLIMIT] = cnf->hop_limit; @@ -3409,66 +3411,59 @@ static inline size_t inet6_if_nlmsg_size(void) static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, u32 pid, u32 seq, int event, unsigned int flags) { - struct net_device *dev = idev->dev; - __s32 *array = NULL; - struct ifinfomsg *r; - struct nlmsghdr *nlh; - unsigned char *b = skb->tail; - struct rtattr *subattr; - __u32 mtu = dev->mtu; - struct ifla_cacheinfo ci; + struct net_device *dev = idev->dev; + struct nlattr *conf; + struct ifinfomsg *hdr; + struct nlmsghdr *nlh; + void *protoinfo; + struct ifla_cacheinfo ci; - nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); - r = NLMSG_DATA(nlh); - r->ifi_family = AF_INET6; - r->__ifi_pad = 0; - r->ifi_type = dev->type; - r->ifi_index = dev->ifindex; - r->ifi_flags = dev_get_flags(dev); - r->ifi_change = 0; + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); + if (nlh == NULL) + return -ENOBUFS; + + hdr = nlmsg_data(nlh); + hdr->ifi_family = AF_INET6; + hdr->__ifi_pad = 0; + hdr->ifi_type = dev->type; + hdr->ifi_index = dev->ifindex; + hdr->ifi_flags = dev_get_flags(dev); + hdr->ifi_change = 0; - RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); + NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); if (dev->addr_len) - RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); + NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); + NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); if (dev->ifindex != dev->iflink) - RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); - - subattr = (struct rtattr*)skb->tail; + NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); - RTA_PUT(skb, IFLA_PROTINFO, 0, NULL); + protoinfo = nla_nest_start(skb, IFLA_PROTINFO); + if (protoinfo == NULL) + goto nla_put_failure; - /* return the device flags */ - RTA_PUT(skb, IFLA_INET6_FLAGS, sizeof(__u32), &idev->if_flags); + NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags); - /* return interface cacheinfo */ ci.max_reasm_len = IPV6_MAXPLEN; ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100 + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); ci.reachable_time = idev->nd_parms->reachable_time; ci.retrans_time = idev->nd_parms->retrans_time; - RTA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); - - /* return the device sysctl params */ - if ((array = kmalloc(DEVCONF_MAX * sizeof(*array), GFP_ATOMIC)) == NULL) - goto rtattr_failure; - ipv6_store_devconf(&idev->cnf, array, DEVCONF_MAX * sizeof(*array)); - RTA_PUT(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(*array), array); + NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); + + conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); + if (conf == NULL) + goto nla_put_failure; + ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf)); /* XXX - Statistics/MC not implemented */ - subattr->rta_len = skb->tail - (u8*)subattr; - nlh->nlmsg_len = skb->tail - b; - kfree(array); - return skb->len; + nla_nest_end(skb, protoinfo); + return nlmsg_end(skb, nlh); -nlmsg_failure: -rtattr_failure: - kfree(array); - skb_trim(skb, b - skb->data); - return -1; +nla_put_failure: + return nlmsg_cancel(skb, nlh); } static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) -- cgit v1.2.3-70-g09d2 From 6051e2f4fb68fc8e5343db58fa680ece376f405c Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 14 Nov 2006 19:54:19 -0800 Subject: [IPv6] prefix: Convert RTM_NEWPREFIX notifications to use the new netlink api RTM_GETPREFIX is completely unused and is thus removed. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 2 -- net/core/rtnetlink.c | 1 - net/ipv6/addrconf.c | 30 ++++++++++++++---------------- security/selinux/nlmsgtab.c | 1 - 4 files changed, 14 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3a18addaed4c..33b3d0ab3a91 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -81,8 +81,6 @@ enum { RTM_NEWPREFIX = 52, #define RTM_NEWPREFIX RTM_NEWPREFIX - RTM_GETPREFIX = 54, -#define RTM_GETPREFIX RTM_GETPREFIX RTM_GETMULTICAST = 58, #define RTM_GETMULTICAST RTM_GETMULTICAST diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 50d6cb40c6e3..0cb4d9e53a07 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -108,7 +108,6 @@ static const int rtm_min[RTM_NR_FAMILIES] = [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), [RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)), - [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 46cd941d296f..052f99eaf2ac 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3518,16 +3518,18 @@ static inline size_t inet6_prefix_nlmsg_size(void) } static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, - struct prefix_info *pinfo, u32 pid, u32 seq, - int event, unsigned int flags) + struct prefix_info *pinfo, u32 pid, u32 seq, + int event, unsigned int flags) { - struct prefixmsg *pmsg; - struct nlmsghdr *nlh; - unsigned char *b = skb->tail; + struct prefixmsg *pmsg; + struct nlmsghdr *nlh; struct prefix_cacheinfo ci; - nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*pmsg), flags); - pmsg = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); + if (nlh == NULL) + return -ENOBUFS; + + pmsg = nlmsg_data(nlh); pmsg->prefix_family = AF_INET6; pmsg->prefix_pad1 = 0; pmsg->prefix_pad2 = 0; @@ -3535,26 +3537,22 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, pmsg->prefix_len = pinfo->prefix_len; pmsg->prefix_type = pinfo->type; pmsg->prefix_pad3 = 0; - pmsg->prefix_flags = 0; if (pinfo->onlink) pmsg->prefix_flags |= IF_PREFIX_ONLINK; if (pinfo->autoconf) pmsg->prefix_flags |= IF_PREFIX_AUTOCONF; - RTA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix); + NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix); ci.preferred_time = ntohl(pinfo->prefered); ci.valid_time = ntohl(pinfo->valid); - RTA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci); + NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci); - nlh->nlmsg_len = skb->tail - b; - return skb->len; + return nlmsg_end(skb, nlh); -nlmsg_failure: -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; +nla_put_failure: + return nlmsg_cancel(skb, nlh); } static void inet6_prefix_notify(int event, struct inet6_dev *idev, diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index b8f4d25cf335..ccfe8755735e 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -60,7 +60,6 @@ static struct nlmsg_perm nlmsg_route_perms[] = { RTM_DELACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_GETACTION, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, - { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ }, -- cgit v1.2.3-70-g09d2 From ba4e58eca8aa9473b44fdfd312f26c4a2e7798b3 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 11:10:57 -0800 Subject: [NET]: Supporting UDP-Lite (RFC 3828) in Linux This is a revision of the previously submitted patch, which alters the way files are organized and compiled in the following manner: * UDP and UDP-Lite now use separate object files * source file dependencies resolved via header files net/ipv{4,6}/udp_impl.h * order of inclusion files in udp.c/udplite.c adapted accordingly [NET/IPv4]: Support for the UDP-Lite protocol (RFC 3828) This patch adds support for UDP-Lite to the IPv4 stack, provided as an extension to the existing UDPv4 code: * generic routines are all located in net/ipv4/udp.c * UDP-Lite specific routines are in net/ipv4/udplite.c * MIB/statistics support in /proc/net/snmp and /proc/net/udplite * shared API with extensions for partial checksum coverage [NET/IPv6]: Extension for UDP-Lite over IPv6 It extends the existing UDPv6 code base with support for UDP-Lite in the same manner as per UDPv4. In particular, * UDPv6 generic and shared code is in net/ipv6/udp.c * UDP-Litev6 specific extensions are in net/ipv6/udplite.c * MIB/statistics support in /proc/net/snmp6 and /proc/net/udplite6 * support for IPV6_ADDRFORM * aligned the coding style of protocol initialisation with af_inet6.c * made the error handling in udpv6_queue_rcv_skb consistent; to return `-1' on error on all error cases * consolidation of shared code [NET]: UDP-Lite Documentation and basic XFRM/Netfilter support The UDP-Lite patch further provides * API documentation for UDP-Lite * basic xfrm support * basic netfilter support for IPv4 and IPv6 (LOG target) Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- Documentation/networking/udplite.txt | 281 +++++++++++++++++++ include/linux/in.h | 1 + include/linux/socket.h | 1 + include/linux/udp.h | 12 + include/net/ipv6.h | 12 +- include/net/transp_v6.h | 2 + include/net/udp.h | 91 +++++- include/net/udplite.h | 149 ++++++++++ include/net/xfrm.h | 2 + net/ipv4/Makefile | 3 +- net/ipv4/af_inet.c | 8 +- net/ipv4/netfilter/ipt_LOG.c | 11 +- net/ipv4/proc.c | 13 + net/ipv4/udp.c | 518 ++++++++++++++++++++--------------- net/ipv4/udp_impl.h | 38 +++ net/ipv4/udplite.c | 119 ++++++++ net/ipv4/xfrm4_policy.c | 1 + net/ipv6/Makefile | 4 +- net/ipv6/af_inet6.c | 21 +- net/ipv6/ipv6_sockglue.c | 11 +- net/ipv6/netfilter/ip6t_LOG.c | 10 +- net/ipv6/proc.c | 11 + net/ipv6/udp.c | 361 +++++++++++++----------- net/ipv6/udp_impl.h | 34 +++ net/ipv6/udplite.c | 105 +++++++ net/ipv6/xfrm6_policy.c | 1 + net/netfilter/xt_multiport.c | 5 +- net/netfilter/xt_tcpudp.c | 20 +- 28 files changed, 1442 insertions(+), 403 deletions(-) create mode 100644 Documentation/networking/udplite.txt create mode 100644 include/net/udplite.h create mode 100644 net/ipv4/udp_impl.h create mode 100644 net/ipv4/udplite.c create mode 100644 net/ipv6/udp_impl.h create mode 100644 net/ipv6/udplite.c (limited to 'net') diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt new file mode 100644 index 000000000000..dd6f46b83dab --- /dev/null +++ b/Documentation/networking/udplite.txt @@ -0,0 +1,281 @@ + =========================================================================== + The UDP-Lite protocol (RFC 3828) + =========================================================================== + + + UDP-Lite is a Standards-Track IETF transport protocol whose characteristic + is a variable-length checksum. This has advantages for transport of multimedia + (video, VoIP) over wireless networks, as partly damaged packets can still be + fed into the codec instead of being discarded due to a failed checksum test. + + This file briefly describes the existing kernel support and the socket API. + For in-depth information, you can consult: + + o The UDP-Lite Homepage: http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/ + Fom here you can also download some example application source code. + + o The UDP-Lite HOWTO on + http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/UDP-Lite-HOWTO.txt + + o The Wireshark UDP-Lite WiKi (with capture files): + http://wiki.wireshark.org/Lightweight_User_Datagram_Protocol + + o The Protocol Spec, RFC 3828, http://www.ietf.org/rfc/rfc3828.txt + + + I) APPLICATIONS + + Several applications have been ported successfully to UDP-Lite. Ethereal + (now called wireshark) has UDP-Litev4/v6 support by default. The tarball on + + http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/udplite_linux.tar.gz + + has source code for several v4/v6 client-server and network testing examples. + + Porting applications to UDP-Lite is straightforward: only socket level and + IPPROTO need to be changed; senders additionally set the checksum coverage + length (default = header length = 8). Details are in the next section. + + + II) PROGRAMMING API + + UDP-Lite provides a connectionless, unreliable datagram service and hence + uses the same socket type as UDP. In fact, porting from UDP to UDP-Lite is + very easy: simply add `IPPROTO_UDPLITE' as the last argument of the socket(2) + call so that the statement looks like: + + s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE); + + or, respectively, + + s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE); + + With just the above change you are able to run UDP-Lite services or connect + to UDP-Lite servers. The kernel will assume that you are not interested in + using partial checksum coverage and so emulate UDP mode (full coverage). + + To make use of the partial checksum coverage facilities requires setting a + single socket option, which takes an integer specifying the coverage length: + + * Sender checksum coverage: UDPLITE_SEND_CSCOV + + For example, + + int val = 20; + setsockopt(s, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int)); + + sets the checksum coverage length to 20 bytes (12b data + 8b header). + Of each packet only the first 20 bytes (plus the pseudo-header) will be + checksummed. This is useful for RTP applications which have a 12-byte + base header. + + + * Receiver checksum coverage: UDPLITE_RECV_CSCOV + + This option is the receiver-side analogue. It is truly optional, i.e. not + required to enable traffic with partial checksum coverage. Its function is + that of a traffic filter: when enabled, it instructs the kernel to drop + all packets which have a coverage _less_ than this value. For example, if + RTP and UDP headers are to be protected, a receiver can enforce that only + packets with a minimum coverage of 20 are admitted: + + int min = 20; + setsockopt(s, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &min, sizeof(int)); + + The calls to getsockopt(2) are analogous. Being an extension and not a stand- + alone protocol, all socket options known from UDP can be used in exactly the + same manner as before, e.g. UDP_CORK or UDP_ENCAP. + + A detailed discussion of UDP-Lite checksum coverage options is in section IV. + + + III) HEADER FILES + + The socket API requires support through header files in /usr/include: + + * /usr/include/netinet/in.h + to define IPPROTO_UDPLITE + + * /usr/include/netinet/udplite.h + for UDP-Lite header fields and protocol constants + + For testing purposes, the following can serve as a `mini' header file: + + #define IPPROTO_UDPLITE 136 + #define SOL_UDPLITE 136 + #define UDPLITE_SEND_CSCOV 10 + #define UDPLITE_RECV_CSCOV 11 + + Ready-made header files for various distros are in the UDP-Lite tarball. + + + IV) KERNEL BEHAVIOUR WITH REGARD TO THE VARIOUS SOCKET OPTIONS + + To enable debugging messages, the log level need to be set to 8, as most + messages use the KERN_DEBUG level (7). + + 1) Sender Socket Options + + If the sender specifies a value of 0 as coverage length, the module + assumes full coverage, transmits a packet with coverage length of 0 + and according checksum. If the sender specifies a coverage < 8 and + different from 0, the kernel assumes 8 as default value. Finally, + if the specified coverage length exceeds the packet length, the packet + length is used instead as coverage length. + + 2) Receiver Socket Options + + The receiver specifies the minimum value of the coverage length it + is willing to accept. A value of 0 here indicates that the receiver + always wants the whole of the packet covered. In this case, all + partially covered packets are dropped and an error is logged. + + It is not possible to specify illegal values (<0 and <8); in these + cases the default of 8 is assumed. + + All packets arriving with a coverage value less than the specified + threshold are discarded, these events are also logged. + + 3) Disabling the Checksum Computation + + On both sender and receiver, checksumming will always be performed + and can not be disabled using SO_NO_CHECK. Thus + + setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... ); + + will always will be ignored, while the value of + + getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...); + + is meaningless (as in TCP). Packets with a zero checksum field are + illegal (cf. RFC 3828, sec. 3.1) will be silently discarded. + + 4) Fragmentation + + The checksum computation respects both buffersize and MTU. The size + of UDP-Lite packets is determined by the size of the send buffer. The + minimum size of the send buffer is 2048 (defined as SOCK_MIN_SNDBUF + in include/net/sock.h), the default value is configurable as + net.core.wmem_default or via setting the SO_SNDBUF socket(7) + option. The maximum upper bound for the send buffer is determined + by net.core.wmem_max. + + Given a payload size larger than the send buffer size, UDP-Lite will + split the payload into several individual packets, filling up the + send buffer size in each case. + + The precise value also depends on the interface MTU. The interface MTU, + in turn, may trigger IP fragmentation. In this case, the generated + UDP-Lite packet is split into several IP packets, of which only the + first one contains the L4 header. + + The send buffer size has implications on the checksum coverage length. + Consider the following example: + + Payload: 1536 bytes Send Buffer: 1024 bytes + MTU: 1500 bytes Coverage Length: 856 bytes + + UDP-Lite will ship the 1536 bytes in two separate packets: + + Packet 1: 1024 payload + 8 byte header + 20 byte IP header = 1052 bytes + Packet 2: 512 payload + 8 byte header + 20 byte IP header = 540 bytes + + The coverage packet covers the UDP-Lite header and 848 bytes of the + payload in the first packet, the second packet is fully covered. Note + that for the second packet, the coverage length exceeds the packet + length. The kernel always re-adjusts the coverage length to the packet + length in such cases. + + As an example of what happens when one UDP-Lite packet is split into + several tiny fragments, consider the following example. + + Payload: 1024 bytes Send buffer size: 1024 bytes + MTU: 300 bytes Coverage length: 575 bytes + + +-+-----------+--------------+--------------+--------------+ + |8| 272 | 280 | 280 | 280 | + +-+-----------+--------------+--------------+--------------+ + 280 560 840 1032 + ^ + *****checksum coverage************* + + The UDP-Lite module generates one 1032 byte packet (1024 + 8 byte + header). According to the interface MTU, these are split into 4 IP + packets (280 byte IP payload + 20 byte IP header). The kernel module + sums the contents of the entire first two packets, plus 15 bytes of + the last packet before releasing the fragments to the IP module. + + To see the analogous case for IPv6 fragmentation, consider a link + MTU of 1280 bytes and a write buffer of 3356 bytes. If the checksum + coverage is less than 1232 bytes (MTU minus IPv6/fragment header + lengths), only the first fragment needs to be considered. When using + larger checksum coverage lengths, each eligible fragment needs to be + checksummed. Suppose we have a checksum coverage of 3062. The buffer + of 3356 bytes will be split into the following fragments: + + Fragment 1: 1280 bytes carrying 1232 bytes of UDP-Lite data + Fragment 2: 1280 bytes carrying 1232 bytes of UDP-Lite data + Fragment 3: 948 bytes carrying 900 bytes of UDP-Lite data + + The first two fragments have to be checksummed in full, of the last + fragment only 598 (= 3062 - 2*1232) bytes are checksummed. + + While it is important that such cases are dealt with correctly, they + are (annoyingly) rare: UDP-Lite is designed for optimising multimedia + performance over wireless (or generally noisy) links and thus smaller + coverage lenghts are likely to be expected. + + + V) UDP-LITE RUNTIME STATISTICS AND THEIR MEANING + + Exceptional and error conditions are logged to syslog at the KERN_DEBUG + level. Live statistics about UDP-Lite are available in /proc/net/snmp + and can (with newer versions of netstat) be viewed using + + netstat -svu + + This displays UDP-Lite statistics variables, whose meaning is as follows. + + InDatagrams: Total number of received datagrams. + + NoPorts: Number of packets received to an unknown port. + These cases are counted separately (not as InErrors). + + InErrors: Number of erroneous UDP-Lite packets. Errors include: + * internal socket queue receive errors + * packet too short (less than 8 bytes or stated + coverage length exceeds received length) + * xfrm4_policy_check() returned with error + * application has specified larger min. coverage + length than that of incoming packet + * checksum coverage violated + * bad checksum + + OutDatagrams: Total number of sent datagrams. + + These statistics derive from the UDP MIB (RFC 2013). + + + VI) IPTABLES + + There is packet match support for UDP-Lite as well as support for the LOG target. + If you copy and paste the following line into /etc/protcols, + + udplite 136 UDP-Lite # UDP-Lite [RFC 3828] + + then + iptables -A INPUT -p udplite -j LOG + + will produce logging output to syslog. Dropping and rejecting packets also works. + + + VII) MAINTAINER ADDRESS + + The UDP-Lite patch was developed at + University of Aberdeen + Electronics Research Group + Department of Engineering + Fraser Noble Building + Aberdeen AB24 3UE; UK + The current maintainer is Gerrit Renker, . Initial + code was developed by William Stanislaus, . diff --git a/include/linux/in.h b/include/linux/in.h index 2619859f6e1b..1912e7c0bc26 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -45,6 +45,7 @@ enum { IPPROTO_COMP = 108, /* Compression Header protocol */ IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ + IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ IPPROTO_RAW = 255, /* Raw IP packets */ IPPROTO_MAX diff --git a/include/linux/socket.h b/include/linux/socket.h index 361409094649..592b66679823 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -264,6 +264,7 @@ struct ucred { #define SOL_IPV6 41 #define SOL_ICMPV6 58 #define SOL_SCTP 132 +#define SOL_UDPLITE 136 /* UDP-Lite (RFC 3828) */ #define SOL_RAW 255 #define SOL_IPX 256 #define SOL_AX25 257 diff --git a/include/linux/udp.h b/include/linux/udp.h index 014b41d1e308..564f3b050105 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -38,6 +38,7 @@ struct udphdr { #include #include +#define UDP_HTABLE_SIZE 128 struct udp_sock { /* inet_sock has to be the first member */ @@ -50,12 +51,23 @@ struct udp_sock { * when the socket is uncorked. */ __u16 len; /* total length of pending frames */ + /* + * Fields specific to UDP-Lite. + */ + __u16 pcslen; + __u16 pcrlen; +/* indicator bits used by pcflag: */ +#define UDPLITE_BIT 0x1 /* set by udplite proto init function */ +#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */ +#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */ + __u8 pcflag; /* marks socket as UDP-Lite if > 0 */ }; static inline struct udp_sock *udp_sk(const struct sock *sk) { return (struct udp_sock *)sk; } +#define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag) #endif diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 3c266ad99a02..9390649bbfec 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -158,9 +158,13 @@ DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \ }) DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); -#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field) -#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field) -#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field) +DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6); +#define UDP6_INC_STATS_BH(field, is_udplite) do { \ + if (is_udplite) SNMP_INC_STATS_BH(udplite_stats_in6, field); \ + else SNMP_INC_STATS_BH(udp_stats_in6, field); } while(0) +#define UDP6_INC_STATS_USER(field, is_udplite) do { \ + if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \ + else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0) int snmp6_register_dev(struct inet6_dev *idev); int snmp6_unregister_dev(struct inet6_dev *idev); @@ -604,6 +608,8 @@ extern int tcp6_proc_init(void); extern void tcp6_proc_exit(void); extern int udp6_proc_init(void); extern void udp6_proc_exit(void); +extern int udplite6_proc_init(void); +extern void udplite6_proc_exit(void); extern int ipv6_misc_proc_init(void); extern void ipv6_misc_proc_exit(void); diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 61f724c1036f..409da3a9a455 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; extern struct proto udpv6_prot; +extern struct proto udplitev6_prot; extern struct proto tcpv6_prot; struct flowi; @@ -24,6 +25,7 @@ extern void ipv6_destopt_init(void); /* transport protocols */ extern void rawv6_init(void); extern void udpv6_init(void); +extern void udplitev6_init(void); extern void tcpv6_init(void); extern int udpv6_connect(struct sock *sk, diff --git a/include/net/udp.h b/include/net/udp.h index db0c05f67546..4f0626735ed3 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -26,9 +26,28 @@ #include #include #include +#include +#include #include -#define UDP_HTABLE_SIZE 128 +/** + * struct udp_skb_cb - UDP(-Lite) private variables + * + * @header: private variables used by IPv4/IPv6 + * @cscov: checksum coverage length (UDP-Lite only) + * @partial_cov: if set indicates partial csum coverage + */ +struct udp_skb_cb { + union { + struct inet_skb_parm h4; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + struct inet6_skb_parm h6; +#endif + } header; + __u16 cscov; + __u8 partial_cov; +}; +#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb)) extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; extern rwlock_t udp_hash_lock; @@ -47,6 +66,62 @@ extern struct proto udp_prot; struct sk_buff; +/* + * Generic checksumming routines for UDP(-Lite) v4 and v6 + */ +static inline u16 __udp_lib_checksum_complete(struct sk_buff *skb) +{ + if (! UDP_SKB_CB(skb)->partial_cov) + return __skb_checksum_complete(skb); + return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov, + skb->csum)); +} + +static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb) +{ + return skb->ip_summed != CHECKSUM_UNNECESSARY && + __udp_lib_checksum_complete(skb); +} + +/** + * udp_csum_outgoing - compute UDPv4/v6 checksum over fragments + * @sk: socket we are writing to + * @skb: sk_buff containing the filled-in UDP header + * (checksum field must be zeroed out) + */ +static inline u32 udp_csum_outgoing(struct sock *sk, struct sk_buff *skb) +{ + u32 csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0); + + skb_queue_walk(&sk->sk_write_queue, skb) { + csum = csum_add(csum, skb->csum); + } + return csum; +} + +/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */ +static inline void udp_lib_hash(struct sock *sk) +{ + BUG(); +} + +static inline void udp_lib_unhash(struct sock *sk) +{ + write_lock_bh(&udp_hash_lock); + if (sk_del_node_init(sk)) { + inet_sk(sk)->num = 0; + sock_prot_dec_use(sk->sk_prot); + } + write_unlock_bh(&udp_hash_lock); +} + +static inline void udp_lib_close(struct sock *sk, long timeout) +{ + sk_common_release(sk); +} + + +/* net/ipv4/udp.c */ extern int udp_get_port(struct sock *sk, unsigned short snum, int (*saddr_cmp)(const struct sock *, const struct sock *)); extern void udp_err(struct sk_buff *, u32); @@ -61,21 +136,29 @@ extern unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); -#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field) -#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field) -#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field) +/* + * SNMP statistics for UDP and UDP-Lite + */ +#define UDP_INC_STATS_USER(field, is_udplite) do { \ + if (is_udplite) SNMP_INC_STATS_USER(udplite_statistics, field); \ + else SNMP_INC_STATS_USER(udp_statistics, field); } while(0) +#define UDP_INC_STATS_BH(field, is_udplite) do { \ + if (is_udplite) SNMP_INC_STATS_BH(udplite_statistics, field); \ + else SNMP_INC_STATS_BH(udp_statistics, field); } while(0) /* /proc */ struct udp_seq_afinfo { struct module *owner; char *name; sa_family_t family; + struct hlist_head *hashtable; int (*seq_show) (struct seq_file *m, void *v); struct file_operations *seq_fops; }; struct udp_iter_state { sa_family_t family; + struct hlist_head *hashtable; int bucket; struct seq_operations seq_ops; }; diff --git a/include/net/udplite.h b/include/net/udplite.h new file mode 100644 index 000000000000..1473b3e49044 --- /dev/null +++ b/include/net/udplite.h @@ -0,0 +1,149 @@ +/* + * Definitions for the UDP-Lite (RFC 3828) code. + */ +#ifndef _UDPLITE_H +#define _UDPLITE_H + +/* UDP-Lite socket options */ +#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */ +#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */ + +extern struct proto udplite_prot; +extern struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; + +/* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */ +DECLARE_SNMP_STAT(struct udp_mib, udplite_statistics); + +/* + * Checksum computation is all in software, hence simpler getfrag. + */ +static __inline__ int udplite_getfrag(void *from, char *to, int offset, + int len, int odd, struct sk_buff *skb) +{ + return memcpy_fromiovecend(to, (struct iovec *) from, offset, len); +} + +/* Designate sk as UDP-Lite socket */ +static inline int udplite_sk_init(struct sock *sk) +{ + udp_sk(sk)->pcflag = UDPLITE_BIT; + return 0; +} + +/* + * Checksumming routines + */ +static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh) +{ + u16 cscov; + + /* In UDPv4 a zero checksum means that the transmitter generated no + * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets + * with a zero checksum field are illegal. */ + if (uh->check == 0) { + LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: zeroed checksum field\n"); + return 1; + } + + UDP_SKB_CB(skb)->partial_cov = 0; + cscov = ntohs(uh->len); + + if (cscov == 0) /* Indicates that full coverage is required. */ + cscov = skb->len; + else if (cscov < 8 || cscov > skb->len) { + /* + * Coverage length violates RFC 3828: log and discard silently. + */ + LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: bad csum coverage %d/%d\n", + cscov, skb->len); + return 1; + + } else if (cscov < skb->len) + UDP_SKB_CB(skb)->partial_cov = 1; + + UDP_SKB_CB(skb)->cscov = cscov; + + /* + * There is no known NIC manufacturer supporting UDP-Lite yet, + * hence ip_summed is always (re-)set to CHECKSUM_NONE. + */ + skb->ip_summed = CHECKSUM_NONE; + + return 0; +} + +static __inline__ int udplite4_csum_init(struct sk_buff *skb, struct udphdr *uh) +{ + int rc = udplite_checksum_init(skb, uh); + + if (!rc) + skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, + skb->nh.iph->daddr, + skb->len, IPPROTO_UDPLITE, 0); + return rc; +} + +static __inline__ int udplite6_csum_init(struct sk_buff *skb, struct udphdr *uh) +{ + int rc = udplite_checksum_init(skb, uh); + + if (!rc) + skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, + skb->len, IPPROTO_UDPLITE, 0); + return rc; +} + +static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh) +{ + int cscov = up->len; + + /* + * Sender has set `partial coverage' option on UDP-Lite socket + */ + if (up->pcflag & UDPLITE_SEND_CC) { + if (up->pcslen < up->len) { + /* up->pcslen == 0 means that full coverage is required, + * partial coverage only if 0 < up->pcslen < up->len */ + if (0 < up->pcslen) { + cscov = up->pcslen; + } + uh->len = htons(up->pcslen); + } + /* + * NOTE: Causes for the error case `up->pcslen > up->len': + * (i) Application error (will not be penalized). + * (ii) Payload too big for send buffer: data is split + * into several packets, each with its own header. + * In this case (e.g. last segment), coverage may + * exceed packet length. + * Since packets with coverage length > packet length are + * illegal, we fall back to the defaults here. + */ + } + return cscov; +} + +static inline u32 udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) +{ + u32 csum = 0; + int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh); + + skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */ + + skb_queue_walk(&sk->sk_write_queue, skb) { + off = skb->h.raw - skb->data; + len = skb->len - off; + + csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum); + + if ((cscov -= len) <= 0) + break; + } + return csum; +} + +extern void udplite4_register(void); +extern int udplite_get_port(struct sock *sk, unsigned short snum, + int (*scmp)(const struct sock *, const struct sock *)); +#endif /* _UDPLITE_H */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 81c91e8a328f..3878a88ff618 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -468,6 +468,7 @@ __be16 xfrm_flowi_sport(struct flowi *fl) switch(fl->proto) { case IPPROTO_TCP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_SCTP: port = fl->fl_ip_sport; break; @@ -493,6 +494,7 @@ __be16 xfrm_flowi_dport(struct flowi *fl) switch(fl->proto) { case IPPROTO_TCP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_SCTP: port = fl->fl_ip_dport; break; diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 15645c51520c..7a068626feea 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -8,7 +8,8 @@ obj-y := route.o inetpeer.o protocol.o \ inet_timewait_sock.o inet_connection_sock.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ tcp_minisocks.o tcp_cong.o \ - datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ + datagram.o raw.o udp.o udplite.o \ + arp.o icmp.o devinet.o af_inet.o igmp.o \ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 4a81d54a7569..8db39f7e3bf0 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -104,6 +104,7 @@ #include #include #include +#include #include #include #include @@ -1223,10 +1224,13 @@ static int __init init_ipv4_mibs(void) tcp_statistics[1] = alloc_percpu(struct tcp_mib); udp_statistics[0] = alloc_percpu(struct udp_mib); udp_statistics[1] = alloc_percpu(struct udp_mib); + udplite_statistics[0] = alloc_percpu(struct udp_mib); + udplite_statistics[1] = alloc_percpu(struct udp_mib); if (! (net_statistics[0] && net_statistics[1] && ip_statistics[0] && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1] - && udp_statistics[0] && udp_statistics[1])) + && udp_statistics[0] && udp_statistics[1] + && udplite_statistics[0] && udplite_statistics[1] ) ) return -ENOMEM; (void) tcp_mib_init(); @@ -1313,6 +1317,8 @@ static int __init inet_init(void) /* Setup TCP slab cache for open requests. */ tcp_init(); + /* Add UDP-Lite (RFC 3828) */ + udplite4_register(); /* * Set the ICMP layer up diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 7dc820df8bc5..46eee64a11f6 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -171,11 +171,15 @@ static void dump_packet(const struct nf_loginfo *info, } break; } - case IPPROTO_UDP: { + case IPPROTO_UDP: + case IPPROTO_UDPLITE: { struct udphdr _udph, *uh; - /* Max length: 10 "PROTO=UDP " */ - printk("PROTO=UDP "); + if (ih->protocol == IPPROTO_UDP) + /* Max length: 10 "PROTO=UDP " */ + printk("PROTO=UDP " ); + else /* Max length: 14 "PROTO=UDPLITE " */ + printk("PROTO=UDPLITE "); if (ntohs(ih->frag_off) & IP_OFFSET) break; @@ -341,6 +345,7 @@ static void dump_packet(const struct nf_loginfo *info, /* IP: 40+46+6+11+127 = 230 */ /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ /* UDP: 10+max(25,20) = 35 */ + /* UDPLITE: 14+max(25,20) = 39 */ /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ /* ESP: 10+max(25)+15 = 50 */ /* AH: 9+max(25)+15 = 49 */ diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 9c6cbe3d9fb8..cd873da54cbe 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated), atomic_read(&tcp_memory_allocated)); seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); + seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues, atomic_read(&ip_frag_mem)); @@ -304,6 +306,17 @@ static int snmp_seq_show(struct seq_file *seq, void *v) fold_field((void **) udp_statistics, snmp4_udp_list[i].entry)); + /* the UDP and UDP-Lite MIBs are the same */ + seq_puts(seq, "\nUdpLite:"); + for (i = 0; snmp4_udp_list[i].name != NULL; i++) + seq_printf(seq, " %s", snmp4_udp_list[i].name); + + seq_puts(seq, "\nUdpLite:"); + for (i = 0; snmp4_udp_list[i].name != NULL; i++) + seq_printf(seq, " %lu", + fold_field((void **) udplite_statistics, + snmp4_udp_list[i].entry) ); + seq_putc(seq, '\n'); return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 9e1bd374875e..98ba75096175 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -92,22 +92,16 @@ #include #include #include -#include #include -#include -#include #include -#include #include #include #include -#include -#include #include #include -#include #include #include +#include "udp_impl.h" /* * Snmp MIB for the UDP layer @@ -120,26 +114,30 @@ DEFINE_RWLOCK(udp_hash_lock); static int udp_port_rover; -static inline int udp_lport_inuse(u16 num) +static inline int __udp_lib_lport_inuse(__be16 num, struct hlist_head udptable[]) { struct sock *sk; struct hlist_node *node; - sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) + sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) if (inet_sk(sk)->num == num) return 1; return 0; } /** - * udp_get_port - common port lookup for IPv4 and IPv6 + * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 * * @sk: socket struct in question * @snum: port number to look up + * @udptable: hash list table, must be of UDP_HTABLE_SIZE + * @port_rover: pointer to record of last unallocated port * @saddr_comp: AF-dependent comparison of bound local IP addresses */ -int udp_get_port(struct sock *sk, unsigned short snum, - int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2)) +int __udp_lib_get_port(struct sock *sk, unsigned short snum, + struct hlist_head udptable[], int *port_rover, + int (*saddr_comp)(const struct sock *sk1, + const struct sock *sk2 ) ) { struct hlist_node *node; struct hlist_head *head; @@ -150,15 +148,15 @@ int udp_get_port(struct sock *sk, unsigned short snum, if (snum == 0) { int best_size_so_far, best, result, i; - if (udp_port_rover > sysctl_local_port_range[1] || - udp_port_rover < sysctl_local_port_range[0]) - udp_port_rover = sysctl_local_port_range[0]; + if (*port_rover > sysctl_local_port_range[1] || + *port_rover < sysctl_local_port_range[0]) + *port_rover = sysctl_local_port_range[0]; best_size_so_far = 32767; - best = result = udp_port_rover; + best = result = *port_rover; for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { int size; - head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; + head = &udptable[result & (UDP_HTABLE_SIZE - 1)]; if (hlist_empty(head)) { if (result > sysctl_local_port_range[1]) result = sysctl_local_port_range[0] + @@ -179,15 +177,15 @@ int udp_get_port(struct sock *sk, unsigned short snum, result = sysctl_local_port_range[0] + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1)); - if (!udp_lport_inuse(result)) + if (! __udp_lib_lport_inuse(result, udptable)) break; } if (i >= (1 << 16) / UDP_HTABLE_SIZE) goto fail; gotit: - udp_port_rover = snum = result; + *port_rover = snum = result; } else { - head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; sk_for_each(sk2, node, head) if (inet_sk(sk2)->num == snum && @@ -195,12 +193,12 @@ gotit: (!sk2->sk_reuse || !sk->sk_reuse) && (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_cmp)(sk, sk2) ) + (*saddr_comp)(sk, sk2) ) goto fail; } inet_sk(sk)->num = snum; if (sk_unhashed(sk)) { - head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; sk_add_node(sk, head); sock_prot_inc_use(sk->sk_prot); } @@ -210,7 +208,13 @@ fail: return error; } -static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +__inline__ int udp_get_port(struct sock *sk, unsigned short snum, + int (*scmp)(const struct sock *, const struct sock *)) +{ + return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); +} + +inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) { struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); @@ -224,34 +228,20 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); } - -static void udp_v4_hash(struct sock *sk) -{ - BUG(); -} - -static void udp_v4_unhash(struct sock *sk) -{ - write_lock_bh(&udp_hash_lock); - if (sk_del_node_init(sk)) { - inet_sk(sk)->num = 0; - sock_prot_dec_use(sk->sk_prot); - } - write_unlock_bh(&udp_hash_lock); -} - /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ -static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, int dif) +static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, + int dif, struct hlist_head udptable[]) { struct sock *sk, *result = NULL; struct hlist_node *node; unsigned short hnum = ntohs(dport); int badness = -1; - sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { + read_lock(&udp_hash_lock); + sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { struct inet_sock *inet = inet_sk(sk); if (inet->num == hnum && !ipv6_only_sock(sk)) { @@ -285,20 +275,10 @@ static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport, } } } - return result; -} - -static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, int dif) -{ - struct sock *sk; - - read_lock(&udp_hash_lock); - sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif); - if (sk) - sock_hold(sk); + if (result) + sock_hold(result); read_unlock(&udp_hash_lock); - return sk; + return result; } static inline struct sock *udp_v4_mcast_next(struct sock *sk, @@ -340,7 +320,7 @@ found: * to find the appropriate port. */ -void udp_err(struct sk_buff *skb, u32 info) +void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) { struct inet_sock *inet; struct iphdr *iph = (struct iphdr*)skb->data; @@ -351,7 +331,8 @@ void udp_err(struct sk_buff *skb, u32 info) int harderr; int err; - sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex); + sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, + skb->dev->ifindex, udptable ); if (sk == NULL) { ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); return; /* No socket for error */ @@ -405,6 +386,11 @@ out: sock_put(sk); } +__inline__ void udp_err(struct sk_buff *skb, u32 info) +{ + return __udp4_lib_err(skb, info, udp_hash); +} + /* * Throw away all pending data and cancel the corking. Socket is locked. */ @@ -419,16 +405,56 @@ static void udp_flush_pending_frames(struct sock *sk) } } +/** + * udp4_hwcsum_outgoing - handle outgoing HW checksumming + * @sk: socket we are sending on + * @skb: sk_buff containing the filled-in UDP header + * (checksum field must be zeroed out) + */ +static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, + __be32 src, __be32 dst, int len ) +{ + unsigned int csum = 0, offset; + struct udphdr *uh = skb->h.uh; + + if (skb_queue_len(&sk->sk_write_queue) == 1) { + /* + * Only one fragment on the socket. + */ + skb->csum = offsetof(struct udphdr, check); + uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); + } else { + /* + * HW-checksum won't work as there are two or more + * fragments on the socket so that all csums of sk_buffs + * should be together + */ + offset = skb->h.raw - skb->data; + skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); + + skb->ip_summed = CHECKSUM_NONE; + + skb_queue_walk(&sk->sk_write_queue, skb) { + csum = csum_add(csum, skb->csum); + } + + uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum); + if (uh->check == 0) + uh->check = -1; + } +} + /* * Push out all pending data as one UDP datagram. Socket is locked. */ -static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) +int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) { struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; struct sk_buff *skb; struct udphdr *uh; int err = 0; + u32 csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) @@ -443,52 +469,28 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) uh->len = htons(up->len); uh->check = 0; - if (sk->sk_no_check == UDP_CSUM_NOXMIT) { + if (up->pcflag) /* UDP-Lite */ + csum = udplite_csum_outgoing(sk, skb); + + else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */ + skb->ip_summed = CHECKSUM_NONE; goto send; - } - if (skb_queue_len(&sk->sk_write_queue) == 1) { - /* - * Only one fragment on the socket. - */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - skb->csum = offsetof(struct udphdr, check); - uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, - up->len, IPPROTO_UDP, 0); - } else { - skb->csum = csum_partial((char *)uh, - sizeof(struct udphdr), skb->csum); - uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, - up->len, IPPROTO_UDP, skb->csum); - if (uh->check == 0) - uh->check = -1; - } - } else { - unsigned int csum = 0; - /* - * HW-checksum won't work as there are two or more - * fragments on the socket so that all csums of sk_buffs - * should be together. - */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - int offset = (unsigned char *)uh - skb->data; - skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ - skb->ip_summed = CHECKSUM_NONE; - } else { - skb->csum = csum_partial((char *)uh, - sizeof(struct udphdr), skb->csum); - } + udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len); + goto send; + + } else /* `normal' UDP */ + csum = udp_csum_outgoing(sk, skb); + + /* add protocol-dependent pseudo-header */ + uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len, + sk->sk_protocol, csum ); + if (uh->check == 0) + uh->check = -1; - skb_queue_walk(&sk->sk_write_queue, skb) { - csum = csum_add(csum, skb->csum); - } - uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, - up->len, IPPROTO_UDP, csum); - if (uh->check == 0) - uh->check = -1; - } send: err = ip_push_pending_frames(sk); out: @@ -497,12 +499,6 @@ out: return err; } - -static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base) -{ - return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base)); -} - int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { @@ -516,8 +512,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, __be32 daddr, faddr, saddr; __be16 dport; u8 tos; - int err; + int err, is_udplite = up->pcflag; int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; + int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); if (len > 0xFFFF) return -EMSGSIZE; @@ -622,7 +619,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, { .daddr = faddr, .saddr = saddr, .tos = tos } }, - .proto = IPPROTO_UDP, + .proto = sk->sk_protocol, .uli_u = { .ports = { .sport = inet->sport, .dport = dport } } }; @@ -668,8 +665,9 @@ back_from_confirm: do_append_data: up->len += ulen; - err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, - sizeof(struct udphdr), &ipc, rt, + getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; + err = ip_append_data(sk, getfrag, msg->msg_iov, ulen, + sizeof(struct udphdr), &ipc, rt, corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); if (err) udp_flush_pending_frames(sk); @@ -684,7 +682,7 @@ out: if (free) kfree(ipc.opt); if (!err) { - UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); + UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite); return len; } /* @@ -695,7 +693,7 @@ out: * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); + UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite); } return err; @@ -707,8 +705,8 @@ do_confirm: goto out; } -static int udp_sendpage(struct sock *sk, struct page *page, int offset, - size_t size, int flags) +int udp_sendpage(struct sock *sk, struct page *page, int offset, + size_t size, int flags) { struct udp_sock *up = udp_sk(sk); int ret; @@ -795,29 +793,18 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) return(0); } -static __inline__ int __udp_checksum_complete(struct sk_buff *skb) -{ - return __skb_checksum_complete(skb); -} - -static __inline__ int udp_checksum_complete(struct sk_buff *skb) -{ - return skb->ip_summed != CHECKSUM_UNNECESSARY && - __udp_checksum_complete(skb); -} - /* * This should be easy, if there is something there we * return it, otherwise we block. */ -static int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; struct sk_buff *skb; - int copied, err; + int copied, err, copy_only, is_udplite = IS_UDPLITE(sk); /* * Check any passed addresses @@ -839,15 +826,25 @@ try_again: msg->msg_flags |= MSG_TRUNC; } - if (skb->ip_summed==CHECKSUM_UNNECESSARY) { - err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, - copied); - } else if (msg->msg_flags&MSG_TRUNC) { - if (__udp_checksum_complete(skb)) + /* + * Decide whether to checksum and/or copy data. + * + * UDP: checksum may have been computed in HW, + * (re-)compute it if message is truncated. + * UDP-Lite: always needs to checksum, no HW support. + */ + copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY); + + if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) { + if (__udp_lib_checksum_complete(skb)) goto csum_copy_err; - err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, - copied); - } else { + copy_only = 1; + } + + if (copy_only) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied ); + else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); if (err == -EINVAL) @@ -880,7 +877,7 @@ out: return err; csum_copy_err: - UDP_INC_STATS_BH(UDP_MIB_INERRORS); + UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); skb_kill_datagram(sk, skb, flags); @@ -912,11 +909,6 @@ int udp_disconnect(struct sock *sk, int flags) return 0; } -static void udp_close(struct sock *sk, long timeout) -{ - sk_common_release(sk); -} - /* return: * 1 if the the UDP system should process it * 0 if we should drop this packet @@ -1022,7 +1014,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) * Note that in the success and error cases, the skb is assumed to * have either been requeued or freed. */ -static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) +int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { struct udp_sock *up = udp_sk(sk); int rc; @@ -1030,10 +1022,8 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) /* * Charge it to the socket, dropping if the queue is full. */ - if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) { - kfree_skb(skb); - return -1; - } + if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) + goto drop; nf_reset(skb); if (up->encap_type) { @@ -1057,31 +1047,68 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) if (ret < 0) { /* process the ESP packet */ ret = xfrm4_rcv_encap(skb, up->encap_type); - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); + UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); return -ret; } /* FALLTHROUGH -- it's a UDP Packet */ } - if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { - if (__udp_checksum_complete(skb)) { - UDP_INC_STATS_BH(UDP_MIB_INERRORS); - kfree_skb(skb); - return -1; + /* + * UDP-Lite specific tests, ignored on UDP sockets + */ + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + + /* + * MIB statistics other than incrementing the error count are + * disabled for the following two types of errors: these depend + * on the application settings, not on the functioning of the + * protocol stack as such. + * + * RFC 3828 here recommends (sec 3.3): "There should also be a + * way ... to ... at least let the receiving application block + * delivery of packets with coverage values less than a value + * provided by the application." + */ + if (up->pcrlen == 0) { /* full coverage was set */ + LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage " + "%d while full coverage %d requested\n", + UDP_SKB_CB(skb)->cscov, skb->len); + goto drop; } + /* The next case involves violating the min. coverage requested + * by the receiver. This is subtle: if receiver wants x and x is + * greater than the buffersize/MTU then receiver will complain + * that it wants x while sender emits packets of smaller size y. + * Therefore the above ...()->partial_cov statement is essential. + */ + if (UDP_SKB_CB(skb)->cscov < up->pcrlen) { + LIMIT_NETDEBUG(KERN_WARNING + "UDPLITE: coverage %d too small, need min %d\n", + UDP_SKB_CB(skb)->cscov, up->pcrlen); + goto drop; + } + } + + if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { + if (__udp_lib_checksum_complete(skb)) + goto drop; skb->ip_summed = CHECKSUM_UNNECESSARY; } if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { /* Note that an ENOMEM error is charged twice */ if (rc == -ENOMEM) - UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); - UDP_INC_STATS_BH(UDP_MIB_INERRORS); - kfree_skb(skb); - return -1; + UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag); + goto drop; } - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); + + UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); return 0; + +drop: + UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag); + kfree_skb(skb); + return -1; } /* @@ -1090,14 +1117,16 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) * Note: called only from the BH handler context, * so we don't need to lock the hashes. */ -static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh, - __be32 saddr, __be32 daddr) +static int __udp4_lib_mcast_deliver(struct sk_buff *skb, + struct udphdr *uh, + __be32 saddr, __be32 daddr, + struct hlist_head udptable[]) { struct sock *sk; int dif; read_lock(&udp_hash_lock); - sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); + sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); dif = skb->dev->ifindex; sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); if (sk) { @@ -1131,65 +1160,75 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh, * Otherwise, csum completion requires chacksumming packet body, * including udp header and folding it to skb->csum. */ -static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, __be32 saddr, __be32 daddr) +static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh) { if (uh->check == 0) { skb->ip_summed = CHECKSUM_UNNECESSARY; } else if (skb->ip_summed == CHECKSUM_COMPLETE) { - if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) + if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, + skb->len, IPPROTO_UDP, skb->csum )) skb->ip_summed = CHECKSUM_UNNECESSARY; } if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); + skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, + skb->nh.iph->daddr, + skb->len, IPPROTO_UDP, 0); /* Probably, we should checksum udp header (it should be in cache * in any case) and data in tiny packets (< rx copybreak). */ + + /* UDP = UDP-Lite with a non-partial checksum coverage */ + UDP_SKB_CB(skb)->partial_cov = 0; } /* * All we need to do is get the socket, and then do a checksum. */ -int udp_rcv(struct sk_buff *skb) +int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], + int is_udplite) { struct sock *sk; - struct udphdr *uh; + struct udphdr *uh = skb->h.uh; unsigned short ulen; struct rtable *rt = (struct rtable*)skb->dst; __be32 saddr = skb->nh.iph->saddr; __be32 daddr = skb->nh.iph->daddr; - int len = skb->len; /* - * Validate the packet and the UDP length. + * Validate the packet. */ if (!pskb_may_pull(skb, sizeof(struct udphdr))) - goto no_header; - - uh = skb->h.uh; + goto drop; /* No space for header. */ ulen = ntohs(uh->len); - - if (ulen > len || ulen < sizeof(*uh)) + if (ulen > skb->len) goto short_packet; - if (pskb_trim_rcsum(skb, ulen)) - goto short_packet; + if(! is_udplite ) { /* UDP validates ulen. */ + + if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen)) + goto short_packet; - udp_checksum_init(skb, uh, ulen, saddr, daddr); + udp4_csum_init(skb, uh); + + } else { /* UDP-Lite validates cscov. */ + if (udplite4_csum_init(skb, uh)) + goto csum_error; + } if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) - return udp_v4_mcast_deliver(skb, uh, saddr, daddr); + return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); - sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex); + sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, + skb->dev->ifindex, udptable ); if (sk != NULL) { int ret = udp_queue_rcv_skb(sk, skb); sock_put(sk); /* a return value > 0 means to resubmit the input, but - * it it wants the return to be -protocol, or 0 + * it wants the return to be -protocol, or 0 */ if (ret > 0) return -ret; @@ -1201,10 +1240,10 @@ int udp_rcv(struct sk_buff *skb) nf_reset(skb); /* No socket. Drop packet silently, if checksum is wrong */ - if (udp_checksum_complete(skb)) + if (udp_lib_checksum_complete(skb)) goto csum_error; - UDP_INC_STATS_BH(UDP_MIB_NOPORTS); + UDP_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* @@ -1215,36 +1254,40 @@ int udp_rcv(struct sk_buff *skb) return(0); short_packet: - LIMIT_NETDEBUG(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", + LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", + is_udplite? "-Lite" : "", NIPQUAD(saddr), ntohs(uh->source), ulen, - len, + skb->len, NIPQUAD(daddr), ntohs(uh->dest)); -no_header: - UDP_INC_STATS_BH(UDP_MIB_INERRORS); - kfree_skb(skb); - return(0); + goto drop; csum_error: /* * RFC1122: OK. Discards the bad packet silently (as far as * the network is concerned, anyway) as per 4.1.3.4 (MUST). */ - LIMIT_NETDEBUG(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", + LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", + is_udplite? "-Lite" : "", NIPQUAD(saddr), ntohs(uh->source), NIPQUAD(daddr), ntohs(uh->dest), ulen); drop: - UDP_INC_STATS_BH(UDP_MIB_INERRORS); + UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); kfree_skb(skb); return(0); } -static int udp_destroy_sock(struct sock *sk) +__inline__ int udp_rcv(struct sk_buff *skb) +{ + return __udp4_lib_rcv(skb, udp_hash, 0); +} + +int udp_destroy_sock(struct sock *sk) { lock_sock(sk); udp_flush_pending_frames(sk); @@ -1293,6 +1336,32 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname, } break; + /* + * UDP-Lite's partial checksum coverage (RFC 3828). + */ + /* The sender sets actual checksum coverage length via this option. + * The case coverage > packet length is handled by send module. */ + case UDPLITE_SEND_CSCOV: + if (!up->pcflag) /* Disable the option on UDP sockets */ + return -ENOPROTOOPT; + if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ + val = 8; + up->pcslen = val; + up->pcflag |= UDPLITE_SEND_CC; + break; + + /* The receiver specifies a minimum checksum coverage value. To make + * sense, this should be set to at least 8 (as done below). If zero is + * used, this again means full checksum coverage. */ + case UDPLITE_RECV_CSCOV: + if (!up->pcflag) /* Disable the option on UDP sockets */ + return -ENOPROTOOPT; + if (val != 0 && val < 8) /* Avoid silly minimal values. */ + val = 8; + up->pcrlen = val; + up->pcflag |= UDPLITE_RECV_CC; + break; + default: err = -ENOPROTOOPT; break; @@ -1301,21 +1370,21 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname, return err; } -static int udp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +int udp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { - if (level != SOL_UDP) - return ip_setsockopt(sk, level, optname, optval, optlen); - return do_udp_setsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udp_setsockopt(sk, level, optname, optval, optlen); + return ip_setsockopt(sk, level, optname, optval, optlen); } #ifdef CONFIG_COMPAT -static int compat_udp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +int compat_udp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { - if (level != SOL_UDP) - return compat_ip_setsockopt(sk, level, optname, optval, optlen); - return do_udp_setsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udp_setsockopt(sk, level, optname, optval, optlen); + return compat_ip_setsockopt(sk, level, optname, optval, optlen); } #endif @@ -1342,6 +1411,16 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname, val = up->encap_type; break; + /* The following two cannot be changed on UDP sockets, the return is + * always 0 (which corresponds to the full checksum coverage of UDP). */ + case UDPLITE_SEND_CSCOV: + val = up->pcslen; + break; + + case UDPLITE_RECV_CSCOV: + val = up->pcrlen; + break; + default: return -ENOPROTOOPT; }; @@ -1353,21 +1432,21 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname, return 0; } -static int udp_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +int udp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { - if (level != SOL_UDP) - return ip_getsockopt(sk, level, optname, optval, optlen); - return do_udp_getsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udp_getsockopt(sk, level, optname, optval, optlen); + return ip_getsockopt(sk, level, optname, optval, optlen); } #ifdef CONFIG_COMPAT -static int compat_udp_getsockopt(struct sock *sk, int level, int optname, +int compat_udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { - if (level != SOL_UDP) - return compat_ip_getsockopt(sk, level, optname, optval, optlen); - return do_udp_getsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udp_getsockopt(sk, level, optname, optval, optlen); + return compat_ip_getsockopt(sk, level, optname, optval, optlen); } #endif /** @@ -1387,7 +1466,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) { unsigned int mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; - + int is_lite = IS_UDPLITE(sk); + /* Check for false positives due to checksum errors */ if ( (mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && @@ -1397,8 +1477,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) spin_lock_bh(&rcvq->lock); while ((skb = skb_peek(rcvq)) != NULL) { - if (udp_checksum_complete(skb)) { - UDP_INC_STATS_BH(UDP_MIB_INERRORS); + if (udp_lib_checksum_complete(skb)) { + UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite); __skb_unlink(skb, rcvq); kfree_skb(skb); } else { @@ -1420,7 +1500,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) struct proto udp_prot = { .name = "UDP", .owner = THIS_MODULE, - .close = udp_close, + .close = udp_lib_close, .connect = ip4_datagram_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, @@ -1431,8 +1511,8 @@ struct proto udp_prot = { .recvmsg = udp_recvmsg, .sendpage = udp_sendpage, .backlog_rcv = udp_queue_rcv_skb, - .hash = udp_v4_hash, - .unhash = udp_v4_unhash, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, .get_port = udp_v4_get_port, .obj_size = sizeof(struct udp_sock), #ifdef CONFIG_COMPAT @@ -1451,7 +1531,7 @@ static struct sock *udp_get_first(struct seq_file *seq) for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { struct hlist_node *node; - sk_for_each(sk, node, &udp_hash[state->bucket]) { + sk_for_each(sk, node, state->hashtable + state->bucket) { if (sk->sk_family == state->family) goto found; } @@ -1472,7 +1552,7 @@ try_again: } while (sk && sk->sk_family != state->family); if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { - sk = sk_head(&udp_hash[state->bucket]); + sk = sk_head(state->hashtable + state->bucket); goto try_again; } return sk; @@ -1522,6 +1602,7 @@ static int udp_seq_open(struct inode *inode, struct file *file) if (!s) goto out; s->family = afinfo->family; + s->hashtable = afinfo->hashtable; s->seq_ops.start = udp_seq_start; s->seq_ops.next = udp_seq_next; s->seq_ops.show = afinfo->seq_show; @@ -1588,7 +1669,7 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket) atomic_read(&sp->sk_refcnt), sp); } -static int udp4_seq_show(struct seq_file *seq, void *v) +int udp4_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) seq_printf(seq, "%-127s\n", @@ -1611,6 +1692,7 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { .owner = THIS_MODULE, .name = "udp", .family = AF_INET, + .hashtable = udp_hash, .seq_show = udp4_seq_show, .seq_fops = &udp4_seq_fops, }; diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h new file mode 100644 index 000000000000..f6f4277ba6dc --- /dev/null +++ b/net/ipv4/udp_impl.h @@ -0,0 +1,38 @@ +#ifndef _UDP4_IMPL_H +#define _UDP4_IMPL_H +#include +#include +#include +#include + +extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); +extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); + +extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, + struct hlist_head udptable[], int *port_rover, + int (*)(const struct sock*,const struct sock*)); +extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *); + + +extern int udp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen); +extern int udp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); + +#ifdef CONFIG_COMPAT +extern int compat_udp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen); +extern int compat_udp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +#endif +extern int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len); +extern int udp_sendpage(struct sock *sk, struct page *page, int offset, + size_t size, int flags); +extern int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); +extern int udp_destroy_sock(struct sock *sk); + +#ifdef CONFIG_PROC_FS +extern int udp4_seq_show(struct seq_file *seq, void *v); +#endif +#endif /* _UDP4_IMPL_H */ diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c new file mode 100644 index 000000000000..561de6d8c734 --- /dev/null +++ b/net/ipv4/udplite.c @@ -0,0 +1,119 @@ +/* + * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828). + * + * Version: $Id: udplite.c,v 1.25 2006/10/19 07:22:36 gerrit Exp $ + * + * Authors: Gerrit Renker + * + * Changes: + * Fixes: + * 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 "udp_impl.h" +DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly; + +struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; +static int udplite_port_rover; + +__inline__ int udplite_get_port(struct sock *sk, unsigned short p, + int (*c)(const struct sock *, const struct sock *)) +{ + return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); +} + +static __inline__ int udplite_v4_get_port(struct sock *sk, unsigned short snum) +{ + return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); +} + +__inline__ int udplite_rcv(struct sk_buff *skb) +{ + return __udp4_lib_rcv(skb, udplite_hash, 1); +} + +__inline__ void udplite_err(struct sk_buff *skb, u32 info) +{ + return __udp4_lib_err(skb, info, udplite_hash); +} + +static struct net_protocol udplite_protocol = { + .handler = udplite_rcv, + .err_handler = udplite_err, + .no_policy = 1, +}; + +struct proto udplite_prot = { + .name = "UDP-Lite", + .owner = THIS_MODULE, + .close = udp_lib_close, + .connect = ip4_datagram_connect, + .disconnect = udp_disconnect, + .ioctl = udp_ioctl, + .init = udplite_sk_init, + .destroy = udp_destroy_sock, + .setsockopt = udp_setsockopt, + .getsockopt = udp_getsockopt, + .sendmsg = udp_sendmsg, + .recvmsg = udp_recvmsg, + .sendpage = udp_sendpage, + .backlog_rcv = udp_queue_rcv_skb, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, + .get_port = udplite_v4_get_port, + .obj_size = sizeof(struct udp_sock), +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_udp_setsockopt, + .compat_getsockopt = compat_udp_getsockopt, +#endif +}; + +static struct inet_protosw udplite4_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_UDPLITE, + .prot = &udplite_prot, + .ops = &inet_dgram_ops, + .capability = -1, + .no_check = 0, /* must checksum (RFC 3828) */ + .flags = INET_PROTOSW_PERMANENT, +}; + +#ifdef CONFIG_PROC_FS +static struct file_operations udplite4_seq_fops; +static struct udp_seq_afinfo udplite4_seq_afinfo = { + .owner = THIS_MODULE, + .name = "udplite", + .family = AF_INET, + .hashtable = udplite_hash, + .seq_show = udp4_seq_show, + .seq_fops = &udplite4_seq_fops, +}; +#endif + +void __init udplite4_register(void) +{ + if (proto_register(&udplite_prot, 1)) + goto out_register_err; + + if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0) + goto out_unregister_proto; + + inet_register_protosw(&udplite4_protosw); + +#ifdef CONFIG_PROC_FS + if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */ + printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__); +#endif + return; + +out_unregister_proto: + proto_unregister(&udplite_prot); +out_register_err: + printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__); +} + +EXPORT_SYMBOL(udplite_hash); +EXPORT_SYMBOL(udplite_prot); +EXPORT_SYMBOL(udplite_get_port); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index da766234607b..d4107bb701b5 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -199,6 +199,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) { switch (iph->protocol) { case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index addcc011bc01..8bacda109b7f 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -5,8 +5,8 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ - route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ - protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ + raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 92bfccf62cb7..1eb1c7f261d4 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -737,8 +738,13 @@ static int __init init_ipv6_mibs(void) if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), __alignof__(struct udp_mib)) < 0) goto err_udp_mib; + if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), + __alignof__(struct udp_mib)) < 0) + goto err_udplite_mib; return 0; +err_udplite_mib: + snmp6_mib_free((void **)udp_stats_in6); err_udp_mib: snmp6_mib_free((void **)icmpv6_statistics); err_icmp_mib: @@ -753,6 +759,7 @@ static void cleanup_ipv6_mibs(void) snmp6_mib_free((void **)ipv6_statistics); snmp6_mib_free((void **)icmpv6_statistics); snmp6_mib_free((void **)udp_stats_in6); + snmp6_mib_free((void **)udplite_stats_in6); } static int __init inet6_init(void) @@ -780,10 +787,14 @@ static int __init inet6_init(void) if (err) goto out_unregister_tcp_proto; - err = proto_register(&rawv6_prot, 1); + err = proto_register(&udplitev6_prot, 1); if (err) goto out_unregister_udp_proto; + err = proto_register(&rawv6_prot, 1); + if (err) + goto out_unregister_udplite_proto; + /* Register the socket-side information for inet6_create. */ for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) @@ -837,6 +848,8 @@ static int __init inet6_init(void) goto proc_tcp6_fail; if (udp6_proc_init()) goto proc_udp6_fail; + if (udplite6_proc_init()) + goto proc_udplite6_fail; if (ipv6_misc_proc_init()) goto proc_misc6_fail; @@ -862,6 +875,7 @@ static int __init inet6_init(void) /* Init v6 transport protocols. */ udpv6_init(); + udplitev6_init(); tcpv6_init(); ipv6_packet_init(); @@ -879,6 +893,8 @@ proc_if6_fail: proc_anycast6_fail: ipv6_misc_proc_exit(); proc_misc6_fail: + udplite6_proc_exit(); +proc_udplite6_fail: udp6_proc_exit(); proc_udp6_fail: tcp6_proc_exit(); @@ -902,6 +918,8 @@ out_unregister_sock: sock_unregister(PF_INET6); out_unregister_raw_proto: proto_unregister(&rawv6_prot); +out_unregister_udplite_proto: + proto_unregister(&udplitev6_prot); out_unregister_udp_proto: proto_unregister(&udpv6_prot); out_unregister_tcp_proto: @@ -919,6 +937,7 @@ static void __exit inet6_exit(void) ac6_proc_exit(); ipv6_misc_proc_exit(); udp6_proc_exit(); + udplite6_proc_exit(); tcp6_proc_exit(); raw6_proc_exit(); #endif diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index de6b91981b30..1eafcfc95e81 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -239,6 +240,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, struct sk_buff *pktopt; if (sk->sk_protocol != IPPROTO_UDP && + sk->sk_protocol != IPPROTO_UDPLITE && sk->sk_protocol != IPPROTO_TCP) break; @@ -276,11 +278,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, sk->sk_family = PF_INET; tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); } else { + struct proto *prot = &udp_prot; + + if (sk->sk_protocol == IPPROTO_UDPLITE) + prot = &udplite_prot; local_bh_disable(); sock_prot_dec_use(sk->sk_prot); - sock_prot_inc_use(&udp_prot); + sock_prot_inc_use(prot); local_bh_enable(); - sk->sk_prot = &udp_prot; + sk->sk_prot = prot; sk->sk_socket->ops = &inet_dgram_ops; sk->sk_family = PF_INET; } @@ -813,6 +819,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, switch (optname) { case IPV6_ADDRFORM: if (sk->sk_protocol != IPPROTO_UDP && + sk->sk_protocol != IPPROTO_UDPLITE && sk->sk_protocol != IPPROTO_TCP) return -EINVAL; if (sk->sk_state != TCP_ESTABLISHED) diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 0cf537d30185..3cb6bb79cc05 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -270,11 +270,15 @@ static void dump_packet(const struct nf_loginfo *info, } break; } - case IPPROTO_UDP: { + case IPPROTO_UDP: + case IPPROTO_UDPLITE: { struct udphdr _udph, *uh; - /* Max length: 10 "PROTO=UDP " */ - printk("PROTO=UDP "); + if (currenthdr == IPPROTO_UDP) + /* Max length: 10 "PROTO=UDP " */ + printk("PROTO=UDP " ); + else /* Max length: 14 "PROTO=UDPLITE " */ + printk("PROTO=UDPLITE "); if (fragment) break; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 4158d386b0aa..35249d8487bb 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -49,6 +49,8 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) fold_prot_inuse(&tcpv6_prot)); seq_printf(seq, "UDP6: inuse %d\n", fold_prot_inuse(&udpv6_prot)); + seq_printf(seq, "UDPLITE6: inuse %d\n", + fold_prot_inuse(&udplitev6_prot)); seq_printf(seq, "RAW6: inuse %d\n", fold_prot_inuse(&rawv6_prot)); seq_printf(seq, "FRAG6: inuse %d memory %d\n", @@ -133,6 +135,14 @@ static struct snmp_mib snmp6_udp6_list[] = { SNMP_MIB_SENTINEL }; +static struct snmp_mib snmp6_udplite6_list[] = { + SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS), + SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), + SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), + SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), + SNMP_MIB_SENTINEL +}; + static unsigned long fold_field(void *mib[], int offt) { @@ -167,6 +177,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); + snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list); } return 0; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 886300d13a59..5a64027bf2fc 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -38,26 +38,18 @@ #include #include -#include -#include - -#include #include #include #include #include -#include -#include -#include #include -#include #include - #include #include #include #include +#include "udp_impl.h" DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; @@ -66,23 +58,9 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); } -static void udp_v6_hash(struct sock *sk) -{ - BUG(); -} - -static void udp_v6_unhash(struct sock *sk) -{ - write_lock_bh(&udp_hash_lock); - if (sk_del_node_init(sk)) { - inet_sk(sk)->num = 0; - sock_prot_dec_use(sk->sk_prot); - } - write_unlock_bh(&udp_hash_lock); -} - -static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, - struct in6_addr *daddr, u16 dport, int dif) +static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, + struct in6_addr *daddr, __be16 dport, + int dif, struct hlist_head udptable[]) { struct sock *sk, *result = NULL; struct hlist_node *node; @@ -90,7 +68,7 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, int badness = -1; read_lock(&udp_hash_lock); - sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { + sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { struct inet_sock *inet = inet_sk(sk); if (inet->num == hnum && sk->sk_family == PF_INET6) { @@ -131,21 +109,12 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, return result; } -/* - * - */ - -static void udpv6_close(struct sock *sk, long timeout) -{ - sk_common_release(sk); -} - /* * This should be easy, if there is something there we * return it, otherwise we block. */ -static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, +int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len) { @@ -153,7 +122,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; size_t copied; - int err; + int err, copy_only, is_udplite = IS_UDPLITE(sk); if (addr_len) *addr_len=sizeof(struct sockaddr_in6); @@ -172,15 +141,21 @@ try_again: msg->msg_flags |= MSG_TRUNC; } - if (skb->ip_summed==CHECKSUM_UNNECESSARY) { - err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, - copied); - } else if (msg->msg_flags&MSG_TRUNC) { - if (__skb_checksum_complete(skb)) + /* + * Decide whether to checksum and/or copy data. + */ + copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY); + + if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) { + if (__udp_lib_checksum_complete(skb)) goto csum_copy_err; - err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, - copied); - } else { + copy_only = 1; + } + + if (copy_only) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied ); + else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); if (err == -EINVAL) goto csum_copy_err; @@ -231,14 +206,15 @@ csum_copy_err: skb_kill_datagram(sk, skb, flags); if (flags & MSG_DONTWAIT) { - UDP6_INC_STATS_USER(UDP_MIB_INERRORS); + UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); return -EAGAIN; } goto try_again; } -static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) +void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info, + struct hlist_head udptable[] ) { struct ipv6_pinfo *np; struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; @@ -248,8 +224,8 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct sock *sk; int err; - sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb)); - + sk = __udp6_lib_lookup(daddr, uh->dest, + saddr, uh->source, inet6_iif(skb), udptable); if (sk == NULL) return; @@ -270,31 +246,55 @@ out: sock_put(sk); } -static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) +static __inline__ void udpv6_err(struct sk_buff *skb, + struct inet6_skb_parm *opt, int type, + int code, int offset, __u32 info ) +{ + return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash); +} + +int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { + struct udp_sock *up = udp_sk(sk); int rc; - if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { - kfree_skb(skb); - return -1; - } + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) + goto drop; - if (skb_checksum_complete(skb)) { - UDP6_INC_STATS_BH(UDP_MIB_INERRORS); - kfree_skb(skb); - return 0; + /* + * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). + */ + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + + if (up->pcrlen == 0) { /* full coverage was set */ + LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage" + " %d while full coverage %d requested\n", + UDP_SKB_CB(skb)->cscov, skb->len); + goto drop; + } + if (UDP_SKB_CB(skb)->cscov < up->pcrlen) { + LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: coverage %d " + "too small, need min %d\n", + UDP_SKB_CB(skb)->cscov, up->pcrlen); + goto drop; + } } + if (udp_lib_checksum_complete(skb)) + goto drop; + if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { /* Note that an ENOMEM error is charged twice */ if (rc == -ENOMEM) - UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); - UDP6_INC_STATS_BH(UDP_MIB_INERRORS); - kfree_skb(skb); - return 0; + UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag); + goto drop; } - UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS); + UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); return 0; +drop: + UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag); + kfree_skb(skb); + return -1; } static struct sock *udp_v6_mcast_next(struct sock *sk, @@ -338,15 +338,15 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, * Note: called only from the BH handler context, * so we don't need to lock the hashes. */ -static void udpv6_mcast_deliver(struct udphdr *uh, - struct in6_addr *saddr, struct in6_addr *daddr, - struct sk_buff *skb) +static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr, + struct in6_addr *daddr, struct hlist_head udptable[]) { struct sock *sk, *sk2; + const struct udphdr *uh = skb->h.uh; int dif; read_lock(&udp_hash_lock); - sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); + sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); dif = inet6_iif(skb); sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); if (!sk) { @@ -364,9 +364,34 @@ static void udpv6_mcast_deliver(struct udphdr *uh, udpv6_queue_rcv_skb(sk, skb); out: read_unlock(&udp_hash_lock); + return 0; } -static int udpv6_rcv(struct sk_buff **pskb) +static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) + +{ + if (uh->check == 0) { + /* RFC 2460 section 8.1 says that we SHOULD log + this error. Well, it is reasonable. + */ + LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); + return 1; + } + if (skb->ip_summed == CHECKSUM_COMPLETE && + !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, + skb->len, IPPROTO_UDP, skb->csum )) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (skb->ip_summed != CHECKSUM_UNNECESSARY) + skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, + skb->len, IPPROTO_UDP, 0); + + return (UDP_SKB_CB(skb)->partial_cov = 0); +} + +int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], + int is_udplite) { struct sk_buff *skb = *pskb; struct sock *sk; @@ -383,44 +408,39 @@ static int udpv6_rcv(struct sk_buff **pskb) uh = skb->h.uh; ulen = ntohs(uh->len); + if (ulen > skb->len) + goto short_packet; - /* Check for jumbo payload */ - if (ulen == 0) - ulen = skb->len; + if(! is_udplite ) { /* UDP validates ulen. */ - if (ulen > skb->len || ulen < sizeof(*uh)) - goto short_packet; + /* Check for jumbo payload */ + if (ulen == 0) + ulen = skb->len; - if (uh->check == 0) { - /* RFC 2460 section 8.1 says that we SHOULD log - this error. Well, it is reasonable. - */ - LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); - goto discard; - } + if (ulen < sizeof(*uh)) + goto short_packet; - if (ulen < skb->len) { - if (pskb_trim_rcsum(skb, ulen)) - goto discard; - saddr = &skb->nh.ipv6h->saddr; - daddr = &skb->nh.ipv6h->daddr; - uh = skb->h.uh; - } + if (ulen < skb->len) { + if (pskb_trim_rcsum(skb, ulen)) + goto short_packet; + saddr = &skb->nh.ipv6h->saddr; + daddr = &skb->nh.ipv6h->daddr; + uh = skb->h.uh; + } - if (skb->ip_summed == CHECKSUM_COMPLETE && - !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) - skb->ip_summed = CHECKSUM_UNNECESSARY; + if (udp6_csum_init(skb, uh)) + goto discard; - if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); + } else { /* UDP-Lite validates cscov. */ + if (udplite6_csum_init(skb, uh)) + goto discard; + } /* * Multicast receive code */ - if (ipv6_addr_is_multicast(daddr)) { - udpv6_mcast_deliver(uh, saddr, daddr, skb); - return 0; - } + if (ipv6_addr_is_multicast(daddr)) + return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable); /* Unicast */ @@ -428,15 +448,16 @@ static int udpv6_rcv(struct sk_buff **pskb) * check socket cache ... must talk to Alan about his plans * for sock caches... i'll skip this for now. */ - sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb)); + sk = __udp6_lib_lookup(saddr, uh->source, + daddr, uh->dest, inet6_iif(skb), udptable); if (sk == NULL) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) goto discard; - if (skb_checksum_complete(skb)) + if (udp_lib_checksum_complete(skb)) goto discard; - UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); + UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); @@ -451,14 +472,20 @@ static int udpv6_rcv(struct sk_buff **pskb) return(0); short_packet: - if (net_ratelimit()) - printk(KERN_DEBUG "UDP: short packet: %d/%u\n", ulen, skb->len); + LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", + is_udplite? "-Lite" : "", ulen, skb->len); discard: - UDP6_INC_STATS_BH(UDP_MIB_INERRORS); + UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); kfree_skb(skb); return(0); } + +static __inline__ int udpv6_rcv(struct sk_buff **pskb) +{ + return __udp6_lib_rcv(pskb, udp_hash, 0); +} + /* * Throw away all pending data and cancel the corking. Socket is locked. */ @@ -484,6 +511,7 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; int err = 0; + u32 csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) @@ -498,35 +526,17 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) uh->len = htons(up->len); uh->check = 0; - if (sk->sk_no_check == UDP_CSUM_NOXMIT) { - skb->ip_summed = CHECKSUM_NONE; - goto send; - } - - if (skb_queue_len(&sk->sk_write_queue) == 1) { - skb->csum = csum_partial((char *)uh, - sizeof(struct udphdr), skb->csum); - uh->check = csum_ipv6_magic(&fl->fl6_src, - &fl->fl6_dst, - up->len, fl->proto, skb->csum); - } else { - u32 tmp_csum = 0; - - skb_queue_walk(&sk->sk_write_queue, skb) { - tmp_csum = csum_add(tmp_csum, skb->csum); - } - tmp_csum = csum_partial((char *)uh, - sizeof(struct udphdr), tmp_csum); - tmp_csum = csum_ipv6_magic(&fl->fl6_src, - &fl->fl6_dst, - up->len, fl->proto, tmp_csum); - uh->check = tmp_csum; + if (up->pcflag) + csum = udplite_csum_outgoing(sk, skb); + else + csum = udp_csum_outgoing(sk, skb); - } + /* add protocol-dependent pseudo-header */ + uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, + up->len, fl->proto, csum ); if (uh->check == 0) uh->check = -1; -send: err = ip6_push_pending_frames(sk); out: up->len = 0; @@ -534,7 +544,7 @@ out: return err; } -static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, +int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { struct ipv6_txoptions opt_space; @@ -554,6 +564,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; int err; int connected = 0; + int is_udplite = up->pcflag; + int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); /* destination address check */ if (sin6) { @@ -694,7 +706,7 @@ do_udp_sendmsg: opt = fl6_merge_options(&opt_space, flowlabel, opt); opt = ipv6_fixup_options(&opt_space, opt); - fl.proto = IPPROTO_UDP; + fl.proto = sk->sk_protocol; ipv6_addr_copy(&fl.fl6_dst, daddr); if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) ipv6_addr_copy(&fl.fl6_src, &np->saddr); @@ -761,7 +773,8 @@ back_from_confirm: do_append_data: up->len += ulen; - err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, + getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; + err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, sizeof(struct udphdr), hlimit, tclass, opt, &fl, (struct rt6_info*)dst, corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); @@ -793,7 +806,7 @@ do_append_data: out: fl6_sock_release(flowlabel); if (!err) { - UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); + UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite); return len; } /* @@ -804,7 +817,7 @@ out: * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); + UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite); } return err; @@ -816,7 +829,7 @@ do_confirm: goto out; } -static int udpv6_destroy_sock(struct sock *sk) +int udpv6_destroy_sock(struct sock *sk) { lock_sock(sk); udp_v6_flush_pending_frames(sk); @@ -854,7 +867,6 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, release_sock(sk); } break; - case UDP_ENCAP: switch (val) { case 0: @@ -866,6 +878,24 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, } break; + case UDPLITE_SEND_CSCOV: + if (!up->pcflag) /* Disable the option on UDP sockets */ + return -ENOPROTOOPT; + if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ + val = 8; + up->pcslen = val; + up->pcflag |= UDPLITE_SEND_CC; + break; + + case UDPLITE_RECV_CSCOV: + if (!up->pcflag) /* Disable the option on UDP sockets */ + return -ENOPROTOOPT; + if (val != 0 && val < 8) /* Avoid silly minimal values. */ + val = 8; + up->pcrlen = val; + up->pcflag |= UDPLITE_RECV_CC; + break; + default: err = -ENOPROTOOPT; break; @@ -874,22 +904,21 @@ static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, return err; } -static int udpv6_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +int udpv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { - if (level != SOL_UDP) - return ipv6_setsockopt(sk, level, optname, optval, optlen); - return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + return ipv6_setsockopt(sk, level, optname, optval, optlen); } #ifdef CONFIG_COMPAT -static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { - if (level != SOL_UDP) - return compat_ipv6_setsockopt(sk, level, optname, - optval, optlen); - return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + return compat_ipv6_setsockopt(sk, level, optname, optval, optlen); } #endif @@ -916,6 +945,14 @@ static int do_udpv6_getsockopt(struct sock *sk, int level, int optname, val = up->encap_type; break; + case UDPLITE_SEND_CSCOV: + val = up->pcslen; + break; + + case UDPLITE_RECV_CSCOV: + val = up->pcrlen; + break; + default: return -ENOPROTOOPT; }; @@ -927,22 +964,21 @@ static int do_udpv6_getsockopt(struct sock *sk, int level, int optname, return 0; } -static int udpv6_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +int udpv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { - if (level != SOL_UDP) - return ipv6_getsockopt(sk, level, optname, optval, optlen); - return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + return ipv6_getsockopt(sk, level, optname, optval, optlen); } #ifdef CONFIG_COMPAT -static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { - if (level != SOL_UDP) - return compat_ipv6_getsockopt(sk, level, optname, - optval, optlen); - return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + if (level == SOL_UDP || level == SOL_UDPLITE) + return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + return compat_ipv6_getsockopt(sk, level, optname, optval, optlen); } #endif @@ -983,7 +1019,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket atomic_read(&sp->sk_refcnt), sp); } -static int udp6_seq_show(struct seq_file *seq, void *v) +int udp6_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) seq_printf(seq, @@ -1002,6 +1038,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { .owner = THIS_MODULE, .name = "udp6", .family = AF_INET6, + .hashtable = udp_hash, .seq_show = udp6_seq_show, .seq_fops = &udp6_seq_fops, }; @@ -1021,7 +1058,7 @@ void udp6_proc_exit(void) { struct proto udpv6_prot = { .name = "UDPv6", .owner = THIS_MODULE, - .close = udpv6_close, + .close = udp_lib_close, .connect = ip6_datagram_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, @@ -1031,8 +1068,8 @@ struct proto udpv6_prot = { .sendmsg = udpv6_sendmsg, .recvmsg = udpv6_recvmsg, .backlog_rcv = udpv6_queue_rcv_skb, - .hash = udp_v6_hash, - .unhash = udp_v6_unhash, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, .get_port = udp_v6_get_port, .obj_size = sizeof(struct udp6_sock), #ifdef CONFIG_COMPAT diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h new file mode 100644 index 000000000000..ec9878899128 --- /dev/null +++ b/net/ipv6/udp_impl.h @@ -0,0 +1,34 @@ +#ifndef _UDP6_IMPL_H +#define _UDP6_IMPL_H +#include +#include +#include +#include +#include + +extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); +extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, + int , int , int , __be32 , struct hlist_head []); + +extern int udpv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +extern int udpv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen); +#ifdef CONFIG_COMPAT +extern int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen); +extern int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +#endif +extern int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len); +extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len, + int noblock, int flags, int *addr_len); +extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); +extern int udpv6_destroy_sock(struct sock *sk); + +#ifdef CONFIG_PROC_FS +extern int udp6_seq_show(struct seq_file *seq, void *v); +#endif +#endif /* _UDP6_IMPL_H */ diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c new file mode 100644 index 000000000000..e0ec5e63004a --- /dev/null +++ b/net/ipv6/udplite.c @@ -0,0 +1,105 @@ +/* + * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6. + * See also net/ipv4/udplite.c + * + * Version: $Id: udplite.c,v 1.9 2006/10/19 08:28:10 gerrit Exp $ + * + * Authors: Gerrit Renker + * + * Changes: + * Fixes: + * 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 "udp_impl.h" + +DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; + +static __inline__ int udplitev6_rcv(struct sk_buff **pskb) +{ + return __udp6_lib_rcv(pskb, udplite_hash, 1); +} + +static __inline__ void udplitev6_err(struct sk_buff *skb, + struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) +{ + return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); +} + +static struct inet6_protocol udplitev6_protocol = { + .handler = udplitev6_rcv, + .err_handler = udplitev6_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +static __inline__ int udplite_v6_get_port(struct sock *sk, unsigned short snum) +{ + return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); +} + +struct proto udplitev6_prot = { + .name = "UDPLITEv6", + .owner = THIS_MODULE, + .close = udp_lib_close, + .connect = ip6_datagram_connect, + .disconnect = udp_disconnect, + .ioctl = udp_ioctl, + .init = udplite_sk_init, + .destroy = udpv6_destroy_sock, + .setsockopt = udpv6_setsockopt, + .getsockopt = udpv6_getsockopt, + .sendmsg = udpv6_sendmsg, + .recvmsg = udpv6_recvmsg, + .backlog_rcv = udpv6_queue_rcv_skb, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, + .get_port = udplite_v6_get_port, + .obj_size = sizeof(struct udp6_sock), +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_udpv6_setsockopt, + .compat_getsockopt = compat_udpv6_getsockopt, +#endif +}; + +static struct inet_protosw udplite6_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_UDPLITE, + .prot = &udplitev6_prot, + .ops = &inet6_dgram_ops, + .capability = -1, + .no_check = 0, + .flags = INET_PROTOSW_PERMANENT, +}; + +void __init udplitev6_init(void) +{ + if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0) + printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__); + + inet6_register_protosw(&udplite6_protosw); +} + +#ifdef CONFIG_PROC_FS +static struct file_operations udplite6_seq_fops; +static struct udp_seq_afinfo udplite6_seq_afinfo = { + .owner = THIS_MODULE, + .name = "udplite6", + .family = AF_INET6, + .hashtable = udplite_hash, + .seq_show = udp6_seq_show, + .seq_fops = &udplite6_seq_fops, +}; + +int __init udplite6_proc_init(void) +{ + return udp_proc_register(&udplite6_seq_afinfo); +} + +void udplite6_proc_exit(void) +{ + udp_proc_unregister(&udplite6_seq_afinfo); +} +#endif diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 2fba1f0739aa..8dffd4daae9c 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -274,6 +274,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) break; case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c index b4293058c6ff..1602086c7fd6 100644 --- a/net/netfilter/xt_multiport.c +++ b/net/netfilter/xt_multiport.c @@ -1,5 +1,5 @@ -/* Kernel module to match one of a list of TCP/UDP/SCTP/DCCP ports: ports are in - the same place so we can treat them as equal. */ +/* Kernel module to match one of a list of TCP/UDP(-Lite)/SCTP/DCCP ports: + ports are in the same place so we can treat them as equal. */ /* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team @@ -162,6 +162,7 @@ check(u_int16_t proto, { /* Must specify supported protocol, no unknown flags or bad count */ return (proto == IPPROTO_TCP || proto == IPPROTO_UDP + || proto == IPPROTO_UDPLITE || proto == IPPROTO_SCTP || proto == IPPROTO_DCCP) && !(ip_invflags & XT_INV_PROTO) && (match_flags == XT_MULTIPORT_SOURCE diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index e76a68e0bc66..46414b562a19 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c @@ -10,7 +10,7 @@ #include #include -MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); +MODULE_DESCRIPTION("x_tables match for TCP and UDP(-Lite), supports IPv4 and IPv6"); MODULE_LICENSE("GPL"); MODULE_ALIAS("xt_tcp"); MODULE_ALIAS("xt_udp"); @@ -234,6 +234,24 @@ static struct xt_match xt_tcpudp_match[] = { .proto = IPPROTO_UDP, .me = THIS_MODULE, }, + { + .name = "udplite", + .family = AF_INET, + .checkentry = udp_checkentry, + .match = udp_match, + .matchsize = sizeof(struct xt_udp), + .proto = IPPROTO_UDPLITE, + .me = THIS_MODULE, + }, + { + .name = "udplite", + .family = AF_INET6, + .checkentry = udp_checkentry, + .match = udp_match, + .matchsize = sizeof(struct xt_udp), + .proto = IPPROTO_UDPLITE, + .me = THIS_MODULE, + }, }; static int __init xt_tcpudp_init(void) -- cgit v1.2.3-70-g09d2 From c68b907028d35b0ad5a98b5e5552f0ad56a9ba1d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Nov 2006 20:40:49 -0800 Subject: [NETPOLL]: Minor coding-style cleanups. Signed-off-by: David S. Miller --- net/core/netpoll.c | 99 ++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 51 deletions(-) (limited to 'net') diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 0d1de3c47a01..0746c81c57b0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -78,7 +78,7 @@ static void queue_process(void *p) } static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, u32 saddr, u32 daddr) + unsigned short ulen, u32 saddr, u32 daddr) { unsigned int psum; @@ -144,12 +144,11 @@ static void service_arp_queue(struct netpoll_info *npi) arp_reply(skb); skb = skb_dequeue(&npi->arp_tx); } - return; } void netpoll_poll(struct netpoll *np) { - if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller) + if (!np->dev || !netif_running(np->dev) || !np->dev->poll_controller) return; /* Process pending work on NIC */ @@ -194,7 +193,7 @@ static void zap_completion_queue(void) while (clist != NULL) { struct sk_buff *skb = clist; clist = clist->next; - if(skb->destructor) + if (skb->destructor) dev_kfree_skb_any(skb); /* put this one back */ else __kfree_skb(skb); @@ -217,7 +216,7 @@ repeat: if (!skb) skb = skb_dequeue(&skb_pool); - if(!skb) { + if (!skb) { if (++count < 10) { netpoll_poll(np); goto repeat; @@ -243,12 +242,11 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } /* don't get messages out of order, and no recursion */ - if ( skb_queue_len(&npinfo->txq) == 0 - && npinfo->poll_owner != smp_processor_id() - && netif_tx_trylock(dev)) { - + if (skb_queue_len(&npinfo->txq) == 0 && + npinfo->poll_owner != smp_processor_id() && + netif_tx_trylock(dev)) { /* try until next clock tick */ - for(tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { + for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { if (!netif_queue_stopped(dev)) status = dev->hard_start_xmit(skb, dev); @@ -384,8 +382,8 @@ static void arp_reply(struct sk_buff *skb) if (np->dev->hard_header && np->dev->hard_header(send_skb, skb->dev, ptype, - np->remote_mac, np->local_mac, - send_skb->len) < 0) { + np->remote_mac, np->local_mac, + send_skb->len) < 0) { kfree_skb(send_skb); return; } @@ -423,7 +421,6 @@ int __netpoll_rx(struct sk_buff *skb) struct netpoll_info *npi = skb->dev->npinfo; struct netpoll *np = npi->rx_np; - if (!np) goto out; if (skb->dev->type != ARPHRD_ETHER) @@ -496,47 +493,47 @@ int netpoll_parse_options(struct netpoll *np, char *opt) { char *cur=opt, *delim; - if(*cur != '@') { + if (*cur != '@') { if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; - *delim=0; - np->local_port=simple_strtol(cur, NULL, 10); - cur=delim; + *delim = 0; + np->local_port = simple_strtol(cur, NULL, 10); + cur = delim; } cur++; printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port); - if(*cur != '/') { + if (*cur != '/') { if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; - *delim=0; - np->local_ip=ntohl(in_aton(cur)); - cur=delim; + *delim = 0; + np->local_ip = ntohl(in_aton(cur)); + cur = delim; printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->local_ip)); } cur++; - if ( *cur != ',') { + if (*cur != ',') { /* parse out dev name */ if ((delim = strchr(cur, ',')) == NULL) goto parse_failed; - *delim=0; + *delim = 0; strlcpy(np->dev_name, cur, sizeof(np->dev_name)); - cur=delim; + cur = delim; } cur++; printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name); - if ( *cur != '@' ) { + if (*cur != '@') { /* dst port */ if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; - *delim=0; - np->remote_port=simple_strtol(cur, NULL, 10); - cur=delim; + *delim = 0; + np->remote_port = simple_strtol(cur, NULL, 10); + cur = delim; } cur++; printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port); @@ -544,42 +541,41 @@ int netpoll_parse_options(struct netpoll *np, char *opt) /* dst ip */ if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; - *delim=0; - np->remote_ip=ntohl(in_aton(cur)); - cur=delim+1; + *delim = 0; + np->remote_ip = ntohl(in_aton(cur)); + cur = delim + 1; printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n", - np->name, HIPQUAD(np->remote_ip)); + np->name, HIPQUAD(np->remote_ip)); - if( *cur != 0 ) - { + if (*cur != 0) { /* MAC address */ if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; - *delim=0; - np->remote_mac[0]=simple_strtol(cur, NULL, 16); - cur=delim+1; + *delim = 0; + np->remote_mac[0] = simple_strtol(cur, NULL, 16); + cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; - *delim=0; - np->remote_mac[1]=simple_strtol(cur, NULL, 16); - cur=delim+1; + *delim = 0; + np->remote_mac[1] = simple_strtol(cur, NULL, 16); + cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; - *delim=0; - np->remote_mac[2]=simple_strtol(cur, NULL, 16); - cur=delim+1; + *delim = 0; + np->remote_mac[2] = simple_strtol(cur, NULL, 16); + cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; - *delim=0; - np->remote_mac[3]=simple_strtol(cur, NULL, 16); - cur=delim+1; + *delim = 0; + np->remote_mac[3] = simple_strtol(cur, NULL, 16); + cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; - *delim=0; - np->remote_mac[4]=simple_strtol(cur, NULL, 16); - cur=delim+1; - np->remote_mac[5]=simple_strtol(cur, NULL, 16); + *delim = 0; + np->remote_mac[4] = simple_strtol(cur, NULL, 16); + cur = delim + 1; + np->remote_mac[5] = simple_strtol(cur, NULL, 16); } printk(KERN_INFO "%s: remote ethernet address " @@ -735,7 +731,8 @@ int netpoll_setup(struct netpoll *np) return err; } -static int __init netpoll_init(void) { +static int __init netpoll_init(void) +{ skb_queue_head_init(&skb_pool); return 0; } -- cgit v1.2.3-70-g09d2 From 448c31aa34b5ee947d322e8747c4cf801fc4c104 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:47:46 -0800 Subject: [IRDA]: Trivial annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/irda/irlap_frame.h | 16 ++++++++-------- net/irda/iriap.c | 8 ++++---- net/irda/irlan/irlan_common.c | 2 +- net/irda/irttp.c | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h index 9dd54a5002b2..641f88e848bd 100644 --- a/include/net/irda/irlap_frame.h +++ b/include/net/irda/irlap_frame.h @@ -91,8 +91,8 @@ struct xid_frame { __u8 caddr; /* Connection address */ __u8 control; __u8 ident; /* Should always be XID_FORMAT */ - __u32 saddr; /* Source device address */ - __u32 daddr; /* Destination device address */ + __le32 saddr; /* Source device address */ + __le32 daddr; /* Destination device address */ __u8 flags; /* Discovery flags */ __u8 slotnr; __u8 version; @@ -101,15 +101,15 @@ struct xid_frame { struct test_frame { __u8 caddr; /* Connection address */ __u8 control; - __u32 saddr; /* Source device address */ - __u32 daddr; /* Destination device address */ + __le32 saddr; /* Source device address */ + __le32 daddr; /* Destination device address */ } IRDA_PACK; struct ua_frame { __u8 caddr; __u8 control; - __u32 saddr; /* Source device address */ - __u32 daddr; /* Dest device address */ + __le32 saddr; /* Source device address */ + __le32 daddr; /* Dest device address */ } IRDA_PACK; struct dm_frame { @@ -135,8 +135,8 @@ struct i_frame { struct snrm_frame { __u8 caddr; __u8 control; - __u32 saddr; - __u32 daddr; + __le32 saddr; + __le32 daddr; __u8 ncaddr; } IRDA_PACK; diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 415cf4eec23b..ab86d70393ea 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -451,12 +451,12 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, n = 2; /* Get length, MSB first */ - len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2; + len = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2; IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len); /* Get object ID, MSB first */ - obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2; + obj_id = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2; type = fp[n++]; IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type); @@ -506,7 +506,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, value = irias_new_string_value(fp+n); break; case IAS_OCT_SEQ: - value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); + value_len = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2; /* Will truncate to IAS_MAX_OCTET_STRING bytes */ @@ -544,7 +544,7 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self, { struct sk_buff *tx_skb; int n; - __u32 tmp_be32; + __be32 tmp_be32; __be16 tmp_be16; __u8 *fp; diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 9b962f247714..2bb04ac09329 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -995,7 +995,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, { __u8 *frame; __u8 param_len; - __u16 tmp_le; /* Temporary value in little endian format */ + __le16 tmp_le; /* Temporary value in little endian format */ int n=0; if (skb == NULL) { diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 3c2e70b77df1..9c446a72ff1f 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -1147,7 +1147,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, frame[3] = 0x02; /* Value length */ put_unaligned(cpu_to_be16((__u16) max_sdu_size), - (__u16 *)(frame+4)); + (__be16 *)(frame+4)); } else { /* Insert plain TTP header */ frame = skb_push(tx_skb, TTP_HEADER); @@ -1394,7 +1394,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, frame[3] = 0x02; /* Value length */ put_unaligned(cpu_to_be16((__u16) max_sdu_size), - (__u16 *)(frame+4)); + (__be16 *)(frame+4)); } else { /* Insert TTP header */ frame = skb_push(tx_skb, TTP_HEADER); -- cgit v1.2.3-70-g09d2 From 252e33467a3b016f20dd8df12269cef3b167f21e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:48:11 -0800 Subject: [NET] net/core: Annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- net/core/filter.c | 6 ++--- net/core/netpoll.c | 2 +- net/core/pktgen.c | 68 +++++++++++++++++++++++++----------------------------- 4 files changed, 38 insertions(+), 42 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 5bf13b132dd7..a7be106d0fdb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1215,7 +1215,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) { struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); struct packet_type *ptype; - int type = skb->protocol; + __be16 type = skb->protocol; int err; BUG_ON(skb_shinfo(skb)->frag_list); @@ -1766,7 +1766,7 @@ int netif_receive_skb(struct sk_buff *skb) struct packet_type *ptype, *pt_prev; struct net_device *orig_dev; int ret = NET_RX_DROP; - unsigned short type; + __be16 type; /* if we've gotten here through NAPI, check netpoll */ if (skb->dev->poll && netpoll_rx(skb)) diff --git a/net/core/filter.c b/net/core/filter.c index 6732782a5a40..0df843b667f4 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -178,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { - A = ntohl(get_unaligned((u32 *)ptr)); + A = ntohl(get_unaligned((__be32 *)ptr)); continue; } break; @@ -187,7 +187,7 @@ load_w: load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { - A = ntohs(get_unaligned((u16 *)ptr)); + A = ntohs(get_unaligned((__be16 *)ptr)); continue; } break; @@ -261,7 +261,7 @@ load_b: */ switch (k-SKF_AD_OFF) { case SKF_AD_PROTOCOL: - A = htons(skb->protocol); + A = ntohs(skb->protocol); continue; case SKF_AD_PKTTYPE: A = skb->pkt_type; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 0746c81c57b0..523141ee920c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -330,7 +330,7 @@ static void arp_reply(struct sk_buff *skb) struct arphdr *arp; unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; - u32 sip, tip; + __be32 sip, tip; struct sk_buff *send_skb; struct netpoll *np = NULL; diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 733d86d0a4fb..1897a3a385d8 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -207,7 +207,7 @@ static struct proc_dir_entry *pg_proc_dir = NULL; #define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4) struct flow_state { - __u32 cur_daddr; + __be32 cur_daddr; int count; }; @@ -282,10 +282,10 @@ struct pktgen_dev { /* If we're doing ranges, random or incremental, then this * defines the min/max for those ranges. */ - __u32 saddr_min; /* inclusive, source IP address */ - __u32 saddr_max; /* exclusive, source IP address */ - __u32 daddr_min; /* inclusive, dest IP address */ - __u32 daddr_max; /* exclusive, dest IP address */ + __be32 saddr_min; /* inclusive, source IP address */ + __be32 saddr_max; /* exclusive, source IP address */ + __be32 daddr_min; /* inclusive, dest IP address */ + __be32 daddr_max; /* exclusive, dest IP address */ __u16 udp_src_min; /* inclusive, source UDP port */ __u16 udp_src_max; /* exclusive, source UDP port */ @@ -317,8 +317,8 @@ struct pktgen_dev { __u32 cur_dst_mac_offset; __u32 cur_src_mac_offset; - __u32 cur_saddr; - __u32 cur_daddr; + __be32 cur_saddr; + __be32 cur_daddr; __u16 cur_udp_dst; __u16 cur_udp_src; __u32 cur_pkt_size; @@ -350,10 +350,10 @@ struct pktgen_dev { }; struct pktgen_hdr { - __u32 pgh_magic; - __u32 seq_num; - __u32 tv_sec; - __u32 tv_usec; + __be32 pgh_magic; + __be32 seq_num; + __be32 tv_sec; + __be32 tv_usec; }; struct pktgen_thread { @@ -2160,7 +2160,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) for(i = 0; i < pkt_dev->nr_labels; i++) if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM) pkt_dev->labels[i] = MPLS_STACK_BOTTOM | - (pktgen_random() & + ((__force __be32)pktgen_random() & htonl(0x000fffff)); } @@ -2220,29 +2220,25 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) { pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; } else { - - if ((imn = ntohl(pkt_dev->daddr_min)) < (imx = - ntohl(pkt_dev-> - daddr_max))) - { + imn = ntohl(pkt_dev->daddr_min); + imx = ntohl(pkt_dev->daddr_max); + if (imn < imx) { __u32 t; + __be32 s; if (pkt_dev->flags & F_IPDST_RND) { - t = ((pktgen_random() % (imx - imn)) + - imn); - t = htonl(t); + t = pktgen_random() % (imx - imn) + imn; + s = htonl(t); - while (LOOPBACK(t) || MULTICAST(t) - || BADCLASS(t) || ZERONET(t) - || LOCAL_MCAST(t)) { - t = ((pktgen_random() % - (imx - imn)) + imn); - t = htonl(t); + while (LOOPBACK(s) || MULTICAST(s) + || BADCLASS(s) || ZERONET(s) + || LOCAL_MCAST(s)) { + t = (pktgen_random() % + (imx - imn)) + imn; + s = htonl(t); } - pkt_dev->cur_daddr = t; - } - - else { + pkt_dev->cur_daddr = s; + } else { t = ntohl(pkt_dev->cur_daddr); t++; if (t > imx) { @@ -2270,7 +2266,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) for (i = 0; i < 4; i++) { pkt_dev->cur_in6_daddr.s6_addr32[i] = - ((pktgen_random() | + (((__force __be32)pktgen_random() | pkt_dev->min_in6_daddr.s6_addr32[i]) & pkt_dev->max_in6_daddr.s6_addr32[i]); } @@ -2377,7 +2373,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); memcpy(eth, pkt_dev->hh, 12); - *(u16 *) & eth[12] = protocol; + *(__be16 *) & eth[12] = protocol; /* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - @@ -2497,7 +2493,7 @@ static unsigned int scan_ip6(const char *s, char ip[16]) char suffix[16]; unsigned int prefixlen = 0; unsigned int suffixlen = 0; - __u32 tmp; + __be32 tmp; for (i = 0; i < 16; i++) ip[i] = 0; @@ -2713,7 +2709,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); memcpy(eth, pkt_dev->hh, 12); - *(u16 *) & eth[12] = protocol; + *(__be16 *) & eth[12] = protocol; /* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - @@ -2732,11 +2728,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, udph->len = htons(datalen + sizeof(struct udphdr)); udph->check = 0; /* No checksum */ - *(u32 *) iph = __constant_htonl(0x60000000); /* Version + flow */ + *(__be32 *) iph = __constant_htonl(0x60000000); /* Version + flow */ if (pkt_dev->traffic_class) { /* Version + traffic class + flow (0) */ - *(u32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20)); + *(__be32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20)); } iph->hop_limit = 32; -- cgit v1.2.3-70-g09d2 From 714e85be3557222bc25f69c252326207c900a7db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:51:49 -0800 Subject: [IPV6]: Assorted trivial endianness annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/inetdevice.h | 14 ++++++++------ include/net/arp.h | 2 +- include/net/ip.h | 11 ++++++----- net/ipv4/af_inet.c | 6 +++--- net/ipv4/arp.c | 2 +- net/ipv4/cipso_ipv4.c | 8 ++++---- net/ipv4/devinet.c | 10 +++++----- net/ipv4/ip_output.c | 2 +- net/ipv4/ip_sockglue.c | 2 +- net/ipv4/raw.c | 4 ++-- net/ipv4/route.c | 4 ++-- net/ipv4/syncookies.c | 18 +++++++++--------- net/ipv4/tcp_ipv4.c | 10 +++++----- net/ipv4/tcp_minisocks.c | 2 +- net/ipv4/tcp_timer.c | 2 +- 15 files changed, 50 insertions(+), 47 deletions(-) (limited to 'net') diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 5a0ab04627bc..c0f7aec331c2 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -124,12 +124,13 @@ static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa) * Check if a mask is acceptable. */ -static __inline__ int bad_mask(u32 mask, u32 addr) +static __inline__ int bad_mask(__be32 mask, __be32 addr) { + __u32 hmask; if (addr & (mask = ~mask)) return 1; - mask = ntohl(mask); - if (mask & (mask+1)) + hmask = ntohl(mask); + if (hmask & (hmask+1)) return 1; return 0; } @@ -190,11 +191,12 @@ static __inline__ __be32 inet_make_mask(int logmask) return 0; } -static __inline__ int inet_mask_len(__u32 mask) +static __inline__ int inet_mask_len(__be32 mask) { - if (!(mask = ntohl(mask))) + __u32 hmask = ntohl(mask); + if (!hmask) return 0; - return 32 - ffz(~mask); + return 32 - ffz(~hmask); } diff --git a/include/net/arp.h b/include/net/arp.h index 6a3d9a7d302b..f02664568600 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -16,7 +16,7 @@ extern void arp_send(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th); extern int arp_bind_neighbour(struct dst_entry *dst); -extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir); +extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir); extern void arp_ifdown(struct net_device *dev); extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, diff --git a/include/net/ip.h b/include/net/ip.h index 949fa8683626..412e8114667d 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -123,7 +123,7 @@ extern int ip4_datagram_connect(struct sock *sk, * multicast packets. */ -static inline void ip_tr_mc_map(u32 addr, char *buf) +static inline void ip_tr_mc_map(__be32 addr, char *buf) { buf[0]=0xC0; buf[1]=0x00; @@ -238,9 +238,9 @@ static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst * Map a multicast IP onto multicast MAC for type ethernet. */ -static inline void ip_eth_mc_map(u32 addr, char *buf) +static inline void ip_eth_mc_map(__be32 naddr, char *buf) { - addr=ntohl(addr); + __u32 addr=ntohl(naddr); buf[0]=0x01; buf[1]=0x00; buf[2]=0x5e; @@ -256,13 +256,14 @@ static inline void ip_eth_mc_map(u32 addr, char *buf) * Leave P_Key as 0 to be filled in by driver. */ -static inline void ip_ib_mc_map(u32 addr, char *buf) +static inline void ip_ib_mc_map(__be32 naddr, char *buf) { + __u32 addr; buf[0] = 0; /* Reserved */ buf[1] = 0xff; /* Multicast QPN */ buf[2] = 0xff; buf[3] = 0xff; - addr = ntohl(addr); + addr = ntohl(naddr); buf[4] = 0xff; buf[5] = 0x12; /* link local scope */ buf[6] = 0x40; /* IPv4 signature */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8db39f7e3bf0..1144900d37f6 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -644,7 +644,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr, sin->sin_port = inet->dport; sin->sin_addr.s_addr = inet->daddr; } else { - __u32 addr = inet->rcv_saddr; + __be32 addr = inet->rcv_saddr; if (!addr) addr = inet->saddr; sin->sin_port = inet->sport; @@ -995,8 +995,8 @@ static int inet_sk_reselect_saddr(struct sock *sk) struct inet_sock *inet = inet_sk(sk); int err; struct rtable *rt; - __u32 old_saddr = inet->saddr; - __u32 new_saddr; + __be32 old_saddr = inet->saddr; + __be32 new_saddr; __be32 daddr = inet->daddr; if (inet->opt && inet->opt->srr) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index cfb5d3de9c84..3981e8be9ab8 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -203,7 +203,7 @@ struct neigh_table arp_tbl = { .gc_thresh3 = 1024, }; -int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir) +int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) { switch (dev->type) { case ARPHRD_ETHER: diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 6460233407c7..c3a61ebbadef 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -966,7 +966,7 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, buf[0] = IPOPT_CIPSO; buf[1] = CIPSO_V4_HDR_LEN + len; - *(u32 *)&buf[2] = htonl(doi_def->doi); + *(__be32 *)&buf[2] = htonl(doi_def->doi); return 0; } @@ -1140,7 +1140,7 @@ int cipso_v4_validate(unsigned char **option) } rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2]))); + doi_def = cipso_v4_doi_getdef(ntohl(*((__be32 *)&opt[2]))); if (doi_def == NULL) { err_offset = 2; goto validate_return_locked; @@ -1370,7 +1370,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) if (ret_val == 0) return ret_val; - doi = ntohl(*(u32 *)&cipso_ptr[2]); + doi = ntohl(*(__be32 *)&cipso_ptr[2]); rcu_read_lock(); doi_def = cipso_v4_doi_getdef(doi); if (doi_def == NULL) { @@ -1436,7 +1436,7 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) return 0; - doi = ntohl(*(u32 *)&cipso_ptr[2]); + doi = ntohl(*(__be32 *)&cipso_ptr[2]); rcu_read_lock(); doi_def = cipso_v4_doi_getdef(doi); if (doi_def == NULL) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index f38cbbae0ae3..a1b356c8aa59 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -577,20 +577,20 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg * Determine a default network mask, based on the IP address. */ -static __inline__ int inet_abc_len(u32 addr) +static __inline__ int inet_abc_len(__be32 addr) { int rc = -1; /* Something else, probably a multicast. */ if (ZERONET(addr)) rc = 0; else { - addr = ntohl(addr); + __u32 haddr = ntohl(addr); - if (IN_CLASSA(addr)) + if (IN_CLASSA(haddr)) rc = 8; - else if (IN_CLASSB(addr)) + else if (IN_CLASSB(haddr)) rc = 16; - else if (IN_CLASSC(addr)) + else if (IN_CLASSC(haddr)) rc = 24; } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index def32d8d3b06..90942a384a45 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -341,7 +341,7 @@ packet_routed: /* OK, we know where to send it, allocate and build IP header. */ iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); - *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); + *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); iph->tot_len = htons(skb->len); if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) iph->frag_off = htons(IP_DF); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 4b132953bcc2..57d4bae6f080 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -355,7 +355,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) sin = (struct sockaddr_in *)msg->msg_name; if (sin) { sin->sin_family = AF_INET; - sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset); + sin->sin_addr.s_addr = *(__be32*)(skb->nh.raw + serr->addr_offset); sin->sin_port = serr->port; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 5c31dead2bdc..a6c63bbd9ddb 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -854,8 +854,8 @@ static void raw_seq_stop(struct seq_file *seq, void *v) static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i) { struct inet_sock *inet = inet_sk(sp); - unsigned int dest = inet->daddr, - src = inet->rcv_saddr; + __be32 dest = inet->daddr, + src = inet->rcv_saddr; __u16 destp = 0, srcp = inet->num; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d7152b2b2c64..ee00b6506ab4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -566,8 +566,8 @@ static inline u32 rt_score(struct rtable *rt) static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { - return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | - (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | + return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | + (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) | (fl1->mark ^ fl2->mark) | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ *(u16 *)&fl2->nl_u.ip4_u.tos) | diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 661e0a4bca72..6b19530905af 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -35,23 +35,23 @@ module_init(init_syncookies); #define COOKIEBITS 24 /* Upper bits store count */ #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) -static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, +static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, u32 count, int c) { __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); - tmp[0] = saddr; - tmp[1] = daddr; - tmp[2] = (sport << 16) + dport; + tmp[0] = (__force u32)saddr; + tmp[1] = (__force u32)daddr; + tmp[2] = ((__force u32)sport << 16) + (__force u32)dport; tmp[3] = count; sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); return tmp[17]; } -static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, - __u16 dport, __u32 sseq, __u32 count, +static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport, + __be16 dport, __u32 sseq, __u32 count, __u32 data) { /* @@ -80,8 +80,8 @@ static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, * "maxdiff" if the current (passed-in) "count". The return value * is (__u32)-1 if this test fails. */ -static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, - __u16 sport, __u16 dport, __u32 sseq, +static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr, + __be16 sport, __be16 dport, __u32 sseq, __u32 count, __u32 maxdiff) { __u32 diff; @@ -220,7 +220,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, } ireq = inet_rsk(req); treq = tcp_rsk(req); - treq->rcv_isn = htonl(skb->h.th->seq) - 1; + treq->rcv_isn = ntohl(skb->h.th->seq) - 1; treq->snt_isn = cookie; req->mss = mss; ireq->rmt_port = skb->h.th->source; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 8c8e8112f98d..0ca8dead03b0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -542,7 +542,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) struct { struct tcphdr th; #ifdef CONFIG_TCP_MD5SIG - u32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)]; + __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)]; #endif } rep; struct ip_reply_arg arg; @@ -618,9 +618,9 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, struct tcphdr *th = skb->h.th; struct { struct tcphdr th; - u32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2) + __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2) #ifdef CONFIG_TCP_MD5SIG - + (TCPOLEN_MD5SIG_ALIGNED >> 2) + + (TCPOLEN_MD5SIG_ALIGNED >> 2) #endif ]; } rep; @@ -2333,8 +2333,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) struct tcp_sock *tp = tcp_sk(sp); const struct inet_connection_sock *icsk = inet_csk(sp); struct inet_sock *inet = inet_sk(sp); - unsigned int dest = inet->daddr; - unsigned int src = inet->rcv_saddr; + __be32 dest = inet->daddr; + __be32 src = inet->rcv_saddr; __u16 destp = ntohs(inet->dport); __u16 srcp = ntohs(inet->sport); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 4a0ee901a888..383cb38461c5 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -493,7 +493,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, struct request_sock **prev) { struct tcphdr *th = skb->h.th; - u32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); + __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); int paws_reject = 0; struct tcp_options_received tmp_opt; struct sock *child; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index fb09ade5897b..3355c276b611 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -297,7 +297,7 @@ static void tcp_retransmit_timer(struct sock *sk) if (net_ratelimit()) { struct inet_sock *inet = inet_sk(sk); printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n", - NIPQUAD(inet->daddr), htons(inet->dport), + NIPQUAD(inet->daddr), ntohs(inet->dport), inet->num, tp->snd_una, tp->snd_nxt); } #endif -- cgit v1.2.3-70-g09d2 From e69a4adc669fe210817ec50ae3f9a7a5ad62d4e8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:56:00 -0800 Subject: [IPV6]: Misc endianness annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/addrconf.h | 8 ++++---- include/net/ip6_route.h | 2 +- include/net/ipv6.h | 2 +- include/net/ndisc.h | 4 ++-- net/ipv6/addrconf.c | 2 +- net/ipv6/af_inet6.c | 4 ++-- net/ipv6/datagram.c | 6 +++--- net/ipv6/exthdrs.c | 2 +- net/ipv6/exthdrs_core.c | 2 +- net/ipv6/inet6_connection_sock.c | 8 ++++---- net/ipv6/ip6_fib.c | 8 ++++---- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/mip6.c | 4 ++-- net/ipv6/ndisc.c | 5 +++-- net/ipv6/netfilter/ip6_tables.c | 3 ++- net/ipv6/netfilter/ip6t_LOG.c | 4 ++-- net/ipv6/raw.c | 2 +- net/ipv6/reassembly.c | 26 +++++++++++++------------- net/ipv6/route.c | 2 +- net/ipv6/sit.c | 18 +++++++++--------- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/udp.c | 4 ++-- 22 files changed, 62 insertions(+), 60 deletions(-) (limited to 'net') diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 44f1b673f916..88df8fc814e4 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -35,9 +35,9 @@ struct prefix_info { #else #error "Please fix " #endif - __u32 valid; - __u32 prefered; - __u32 reserved2; + __be32 valid; + __be32 prefered; + __be32 reserved2; struct in6_addr prefix; }; @@ -183,7 +183,7 @@ static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr) * This will include the IEEE address token on links that support it. */ - word = addr->s6_addr32[2] ^ addr->s6_addr32[3]; + word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); word ^= (word >> 16); word ^= (word >> 8); diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index c14b70ed4c57..4e927ebd1cb3 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -20,7 +20,7 @@ struct route_info { route_pref:2, reserved_h:3; #endif - __u32 lifetime; + __be32 lifetime; __u8 prefix[0]; /* 0,8 or 16 */ }; diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 9390649bbfec..4ca9e93decc5 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -563,7 +563,7 @@ extern int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len); extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); -extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port, +extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, u32 info, u8 *payload); extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info); diff --git a/include/net/ndisc.h b/include/net/ndisc.h index d3915dabe6de..475b10c575b3 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -66,8 +66,8 @@ struct rs_msg { struct ra_msg { struct icmp6hdr icmph; - __u32 reachable_time; - __u32 retrans_timer; + __be32 reachable_time; + __be32 retrans_timer; }; struct nd_opt_hdr { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 052f99eaf2ac..b41c5d8b2789 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -232,7 +232,7 @@ static inline unsigned ipv6_addr_scope2type(unsigned scope) int __ipv6_addr_type(const struct in6_addr *addr) { - u32 st; + __be32 st; st = addr->s6_addr32[0]; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 1eb1c7f261d4..87c8f54872b7 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -222,7 +222,7 @@ lookup_protocol: * the user to assign a number at socket * creation time automatically shares. */ - inet->sport = ntohs(inet->num); + inet->sport = htons(inet->num); sk->sk_prot->hash(sk); } if (sk->sk_prot->init) { @@ -342,7 +342,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; - inet->sport = ntohs(inet->num); + inet->sport = htons(inet->num); inet->dport = 0; inet->daddr = 0; out: diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a67434af691f..5c94fea90e97 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -207,7 +207,7 @@ out: } void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, - u16 port, u32 info, u8 *payload) + __be16 port, u32 info, u8 *payload) { struct ipv6_pinfo *np = inet6_sk(sk); struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; @@ -324,7 +324,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) } else { ipv6_addr_set(&sin->sin6_addr, 0, 0, htonl(0xffff), - *(u32*)(skb->nh.raw + serr->addr_offset)); + *(__be32*)(skb->nh.raw + serr->addr_offset)); } } @@ -397,7 +397,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) } if (np->rxopt.bits.rxtclass) { - int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff; + int tclass = (ntohl(*(__be32 *)skb->nh.ipv6h) >> 20) & 0xff; put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 27829cc4ce88..0711f92d6a12 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -655,7 +655,7 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) goto drop; } - pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); + pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); if (pkt_len <= IPV6_MAXPLEN) { IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 315bc1fbec3f..21cbbbddaf4d 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -77,7 +77,7 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) if (hp == NULL) return -1; if (nexthdr == NEXTHDR_FRAGMENT) { - unsigned short _frag_off, *fp; + __be16 _frag_off, *fp; fp = skb_header_pointer(skb, start+offsetof(struct frag_hdr, frag_off), diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index c598962eaa40..c700302ad51a 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -55,16 +55,16 @@ EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, const u32 rnd, const u16 synq_hsize) { - u32 a = raddr->s6_addr32[0]; - u32 b = raddr->s6_addr32[1]; - u32 c = raddr->s6_addr32[2]; + u32 a = (__force u32)raddr->s6_addr32[0]; + u32 b = (__force u32)raddr->s6_addr32[1]; + u32 c = (__force u32)raddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += rnd; __jhash_mix(a, b, c); - a += raddr->s6_addr32[3]; + a += (__force u32)raddr->s6_addr32[3]; b += (__force u32)rport; __jhash_mix(a, b, c); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f98ca30d7c1f..bf526115e518 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -139,9 +139,9 @@ static __inline__ u32 fib6_new_sernum(void) * test bit */ -static __inline__ int addr_bit_set(void *token, int fn_bit) +static __inline__ __be32 addr_bit_set(void *token, int fn_bit) { - __u32 *addr = token; + __be32 *addr = token; return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; } @@ -434,7 +434,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, struct fib6_node *pn = NULL; struct rt6key *key; int bit; - int dir = 0; + __be32 dir = 0; __u32 sernum = fib6_new_sernum(); RT6_TRACE("fib6_add_1\n"); @@ -829,7 +829,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, struct lookup_args *args) { struct fib6_node *fn; - int dir; + __be32 dir; if (unlikely(args->offset == 0)) return NULL; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 80a11909159d..25bc5ed49104 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); #define HASH_SIZE 32 -#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ +#define HASH(addr) ((__force u32)((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ (HASH_SIZE - 1)) diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 7ccdc8fc5a31..be7dd7db65d7 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -262,10 +262,10 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct sel.proto = fl->proto; sel.dport = xfrm_flowi_dport(fl); if (sel.dport) - sel.dport_mask = ~((__u16)0); + sel.dport_mask = htons(~0); sel.sport = xfrm_flowi_sport(fl); if (sel.sport) - sel.sport_mask = ~((__u16)0); + sel.sport_mask = htons(~0); sel.ifindex = fl->oif; err = km_report(IPPROTO_DSTOPTS, &sel, diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 1342be8b4cdc..56ea92837307 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1267,10 +1267,11 @@ skip_defrtr: } if (ndopts.nd_opts_mtu) { + __be32 n; u32 mtu; - memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); - mtu = ntohl(mtu); + memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); + mtu = ntohl(n); if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) { ND_PRINTK2(KERN_WARNING diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 204e02162d49..f63fb86d7c7b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1481,7 +1481,8 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if (hp == NULL) return -EBADMSG; if (nexthdr == NEXTHDR_FRAGMENT) { - unsigned short _frag_off, *fp; + unsigned short _frag_off; + __be16 *fp; fp = skb_header_pointer(skb, start+offsetof(struct frag_hdr, frag_off), diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 3cb6bb79cc05..f4857cf97f05 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -69,9 +69,9 @@ static void dump_packet(const struct nf_loginfo *info, /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ntohs(ih->payload_len) + sizeof(struct ipv6hdr), - (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20, + (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, ih->hop_limit, - (ntohl(*(u_int32_t *)ih) & 0x000fffff)); + (ntohl(*(__be32 *)ih) & 0x000fffff)); fragment = 0; ptr = ip6hoff + sizeof(struct ipv6hdr); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 813fa1d96862..b03040a20814 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -220,7 +220,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; - __u32 v4addr = 0; + __be32 v4addr = 0; int addr_type; int err; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3af0d5a6ceeb..6f9a9046510f 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -77,7 +77,7 @@ struct frag_queue struct hlist_node list; struct list_head lru_list; /* lru list member */ - __u32 id; /* fragment id */ + __be32 id; /* fragment id */ struct in6_addr saddr; struct in6_addr daddr; @@ -125,28 +125,28 @@ static __inline__ void fq_unlink(struct frag_queue *fq) * callers should be careful not to use the hash value outside the ipfrag_lock * as doing so could race with ipfrag_hash_rnd being recalculated. */ -static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, +static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, struct in6_addr *daddr) { u32 a, b, c; - a = saddr->s6_addr32[0]; - b = saddr->s6_addr32[1]; - c = saddr->s6_addr32[2]; + a = (__force u32)saddr->s6_addr32[0]; + b = (__force u32)saddr->s6_addr32[1]; + c = (__force u32)saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += ip6_frag_hash_rnd; __jhash_mix(a, b, c); - a += saddr->s6_addr32[3]; - b += daddr->s6_addr32[0]; - c += daddr->s6_addr32[1]; + a += (__force u32)saddr->s6_addr32[3]; + b += (__force u32)daddr->s6_addr32[0]; + c += (__force u32)daddr->s6_addr32[1]; __jhash_mix(a, b, c); - a += daddr->s6_addr32[2]; - b += daddr->s6_addr32[3]; - c += id; + a += (__force u32)daddr->s6_addr32[2]; + b += (__force u32)daddr->s6_addr32[3]; + c += (__force u32)id; __jhash_mix(a, b, c); return c & (IP6Q_HASHSZ - 1); @@ -370,7 +370,7 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) static struct frag_queue * -ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst, +ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst, struct inet6_dev *idev) { struct frag_queue *fq; @@ -396,7 +396,7 @@ oom: } static __inline__ struct frag_queue * -fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst, +fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, struct inet6_dev *idev) { struct frag_queue *fq; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a6472cb9054c..0bf17a3cf085 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -440,7 +440,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, if (pref == ICMPV6_ROUTER_PREF_INVALID) pref = ICMPV6_ROUTER_PREF_MEDIUM; - lifetime = htonl(rinfo->lifetime); + lifetime = ntohl(rinfo->lifetime); if (lifetime == 0xffffffff) { /* infinity */ } else if (lifetime > 0x7fffffff/HZ) { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index be699f85b2c7..85ff3dc45148 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -60,7 +60,7 @@ */ #define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) +#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); @@ -76,7 +76,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne static DEFINE_RWLOCK(ipip6_lock); -static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) +static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -102,8 +102,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) { - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; + __be32 remote = t->parms.iph.daddr; + __be32 local = t->parms.iph.saddr; unsigned h = 0; int prio = 0; @@ -144,8 +144,8 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) { - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; + __be32 remote = parms->iph.daddr; + __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = 0; @@ -405,9 +405,9 @@ out: /* Returns the embedded IPv4 address if the IPv6 address comes from 6to4 (RFC 3056) addr space */ -static inline u32 try_6to4(struct in6_addr *v6dst) +static inline __be32 try_6to4(struct in6_addr *v6dst) { - u32 dst = 0; + __be32 dst = 0; if (v6dst->s6_addr16[0] == htons(0x2002)) { /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ @@ -432,7 +432,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ - u32 dst = tiph->daddr; + __be32 dst = tiph->daddr; int mtu; struct in6_addr *addr6; int addr_type; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index edef7eef8341..53f270995d8a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1084,7 +1084,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, struct sk_buff *buff; struct flowi fl; int tot_len = sizeof(struct tcphdr); - u32 *topt; + __be32 *topt; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *key; struct tcp_md5sig_key tw_key; @@ -1128,7 +1128,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, t1->ack = 1; t1->window = htons(win); - topt = (u32*)(t1 + 1); + topt = (__be32 *)(t1 + 1); if (ts) { *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5a64027bf2fc..e6e1f85f1bbd 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -298,8 +298,8 @@ drop: } static struct sock *udp_v6_mcast_next(struct sock *sk, - u16 loc_port, struct in6_addr *loc_addr, - u16 rmt_port, struct in6_addr *rmt_addr, + __be16 loc_port, struct in6_addr *loc_addr, + __be16 rmt_port, struct in6_addr *rmt_addr, int dif) { struct hlist_node *node; -- cgit v1.2.3-70-g09d2 From 42d224aa170a4f7446cea6c972d9302d524545e5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:11:08 -0800 Subject: [NETFILTER]: More trivial annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4/ip_conntrack_tftp.h | 2 +- net/ipv4/netfilter/ip_conntrack_amanda.c | 2 +- net/ipv4/netfilter/ip_conntrack_helper_h323.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h b/include/linux/netfilter_ipv4/ip_conntrack_tftp.h index cde9729aa173..a404fc0abf0e 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tftp.h @@ -4,7 +4,7 @@ #define TFTP_PORT 69 struct tftphdr { - u_int16_t opcode; + __be16 opcode; }; #define TFTP_OPCODE_READ 1 diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index 6c7383a8e42b..7fca246615d5 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -180,7 +180,7 @@ static struct ip_conntrack_helper amanda_helper = { .help = help, .name = "amanda", - .tuple = { .src = { .u = { __constant_htons(10080) } }, + .tuple = { .src = { .u = { .udp = {.port = __constant_htons(10080) } } }, .dst = { .protonum = IPPROTO_UDP }, }, .mask = { .src = { .u = { 0xFFFF } }, diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 6cb9070cd0bc..a06b340ea414 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -1153,7 +1153,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_q931 = { .me = THIS_MODULE, .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ , .timeout = 240, - .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}}, + .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(Q931_PORT)}}}, .dst = {.protonum = IPPROTO_TCP}}, .mask = {.src = {.u = {0xFFFF}}, .dst = {.protonum = 0xFF}}, @@ -1746,7 +1746,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_ras = { .me = THIS_MODULE, .max_expected = 32, .timeout = 240, - .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}}, + .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(RAS_PORT)}}}, .dst = {.protonum = IPPROTO_UDP}}, .mask = {.src = {.u = {0xFFFE}}, .dst = {.protonum = 0xFF}}, -- cgit v1.2.3-70-g09d2 From 30d492da738a8d5f4ec884b3e1a13eef97714994 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:11:29 -0800 Subject: [ATM]: Annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/atmarp.h | 2 +- include/linux/atmbr2684.h | 4 ++-- include/linux/atmmpc.h | 16 ++++++++-------- include/net/atmclip.h | 2 +- net/atm/br2684.c | 2 +- net/atm/clip.c | 10 +++++----- net/atm/lec.c | 6 +++--- net/atm/lec.h | 6 +++--- net/atm/mpc.c | 26 +++++++++++++------------- net/atm/mpc.h | 6 +++--- net/atm/mpoa_caches.c | 14 +++++++------- net/atm/mpoa_caches.h | 16 ++++++++-------- net/atm/mpoa_proc.c | 6 +++--- 13 files changed, 58 insertions(+), 58 deletions(-) (limited to 'net') diff --git a/include/linux/atmarp.h b/include/linux/atmarp.h index 24f82338f59a..ee108f9e9cb7 100644 --- a/include/linux/atmarp.h +++ b/include/linux/atmarp.h @@ -37,7 +37,7 @@ enum atmarp_ctrl_type { struct atmarp_ctrl { enum atmarp_ctrl_type type; /* message type */ int itf_num;/* interface number (if present) */ - uint32_t ip; /* IP address (act_need only) */ + __be32 ip; /* IP address (act_need only) */ }; #endif diff --git a/include/linux/atmbr2684.h b/include/linux/atmbr2684.h index 7981b733f1ef..969fb6c9e1cc 100644 --- a/include/linux/atmbr2684.h +++ b/include/linux/atmbr2684.h @@ -86,8 +86,8 @@ struct atm_backend_br2684 { * efficient per-if in/out filters, this support will be removed */ struct br2684_filter { - __u32 prefix; /* network byte order */ - __u32 netmask; /* 0 = disable filter */ + __be32 prefix; /* network byte order */ + __be32 netmask; /* 0 = disable filter */ }; struct br2684_filter_set { diff --git a/include/linux/atmmpc.h b/include/linux/atmmpc.h index 5fbfa68136d3..ea1650425a12 100644 --- a/include/linux/atmmpc.h +++ b/include/linux/atmmpc.h @@ -13,7 +13,7 @@ struct atmmpc_ioc { int dev_num; - uint32_t ipaddr; /* the IP address of the shortcut */ + __be32 ipaddr; /* the IP address of the shortcut */ int type; /* ingress or egress */ }; @@ -21,8 +21,8 @@ typedef struct in_ctrl_info { uint8_t Last_NHRP_CIE_code; uint8_t Last_Q2931_cause_value; uint8_t eg_MPC_ATM_addr[ATM_ESA_LEN]; - uint32_t tag; - uint32_t in_dst_ip; /* IP address this ingress MPC sends packets to */ + __be32 tag; + __be32 in_dst_ip; /* IP address this ingress MPC sends packets to */ uint16_t holding_time; uint32_t request_id; } in_ctrl_info; @@ -30,10 +30,10 @@ typedef struct in_ctrl_info { typedef struct eg_ctrl_info { uint8_t DLL_header[256]; uint8_t DH_length; - uint32_t cache_id; - uint32_t tag; - uint32_t mps_ip; - uint32_t eg_dst_ip; /* IP address to which ingress MPC sends packets */ + __be32 cache_id; + __be32 tag; + __be32 mps_ip; + __be32 eg_dst_ip; /* IP address to which ingress MPC sends packets */ uint8_t in_MPC_data_ATM_addr[ATM_ESA_LEN]; uint16_t holding_time; } eg_ctrl_info; @@ -49,7 +49,7 @@ struct mpc_parameters { struct k_message { uint16_t type; - uint32_t ip_mask; + __be32 ip_mask; uint8_t MPS_ctrl[ATM_ESA_LEN]; union { in_ctrl_info in_info; diff --git a/include/net/atmclip.h b/include/net/atmclip.h index 90fcc98e676f..b5a51a7bb364 100644 --- a/include/net/atmclip.h +++ b/include/net/atmclip.h @@ -36,7 +36,7 @@ struct clip_vcc { struct atmarp_entry { - u32 ip; /* IP address */ + __be32 ip; /* IP address */ struct clip_vcc *vccs; /* active VCCs; NULL if resolution is pending */ unsigned long expires; /* entry expiration time */ diff --git a/net/atm/br2684.c b/net/atm/br2684.c index d00cca97eb33..b04162f10d85 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -372,7 +372,7 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg) /* Returns 1 if packet should be dropped */ static inline int -packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) +packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) { if (brvcc->filter.netmask == 0) return 0; /* no filter in place */ diff --git a/net/atm/clip.c b/net/atm/clip.c index 7af2c411da82..1c416934b7c1 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -54,7 +54,7 @@ static struct atm_vcc *atmarpd; static struct neigh_table clip_tbl; static struct timer_list idle_timer; -static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip) +static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip) { struct sock *sk; struct atmarp_ctrl *ctrl; @@ -220,7 +220,7 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) || memcmp(skb->data, llc_oui, sizeof (llc_oui))) skb->protocol = htons(ETH_P_IP); else { - skb->protocol = ((u16 *) skb->data)[3]; + skb->protocol = ((__be16 *) skb->data)[3]; skb_pull(skb, RFC1483LLC_LEN); if (skb->protocol == htons(ETH_P_ARP)) { PRIV(skb->dev)->stats.rx_packets++; @@ -430,7 +430,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) here = skb_push(skb, RFC1483LLC_LEN); memcpy(here, llc_oui, sizeof(llc_oui)); - ((u16 *) here)[3] = skb->protocol; + ((__be16 *) here)[3] = skb->protocol; } atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); ATM_SKB(skb)->atm_options = vcc->atm_options; @@ -509,7 +509,7 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) return 0; } -static int clip_setentry(struct atm_vcc *vcc, u32 ip) +static int clip_setentry(struct atm_vcc *vcc, __be32 ip) { struct neighbour *neigh; struct atmarp_entry *entry; @@ -752,7 +752,7 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) err = clip_mkip(vcc, arg); break; case ATMARP_SETENTRY: - err = clip_setentry(vcc, arg); + err = clip_setentry(vcc, (__force __be32)arg); break; case ATMARP_ENCAP: err = clip_encap(vcc, arg); diff --git a/net/atm/lec.c b/net/atm/lec.c index 66c57c1091a8..9f5f931743bd 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -204,9 +204,9 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) memset(rdesc, 0, ETH_ALEN); /* offset 4 comes from LAN destination field in LE control frames */ if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT)) - memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(uint16_t)); + memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(__be16)); else { - memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t)); + memcpy(&rdesc[4], &trh->rseg[1], sizeof(__be16)); rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0)); } @@ -775,7 +775,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) unsigned char *src, *dst; atm_return(vcc, skb->truesize); - if (*(uint16_t *) skb->data == htons(priv->lecid) || + if (*(__be16 *) skb->data == htons(priv->lecid) || !priv->lecd || !(dev->flags & IFF_UP)) { /* * Probably looping back, or if lecd is missing, diff --git a/net/atm/lec.h b/net/atm/lec.h index 877f50939696..24cc95f86741 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -14,14 +14,14 @@ #define LEC_HEADER_LEN 16 struct lecdatahdr_8023 { - unsigned short le_header; + __be16 le_header; unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; - unsigned short h_type; + __be16 h_type; }; struct lecdatahdr_8025 { - unsigned short le_header; + __be16 le_header; unsigned char ac_pad; unsigned char fc; unsigned char h_dest[ETH_ALEN]; diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 0d2b994af511..f15f5d847860 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -152,7 +152,7 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev) /* * Overwrites the old entry or makes a new one. */ -struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos) +struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos) { struct atm_mpoa_qos *entry; @@ -177,7 +177,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos) return entry; } -struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip) +struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip) { struct atm_mpoa_qos *qos; @@ -460,11 +460,11 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) in_cache_entry *entry; struct iphdr *iph; char *buff; - uint32_t ipaddr = 0; + __be32 ipaddr = 0; static struct { struct llc_snap_hdr hdr; - uint32_t tag; + __be32 tag; } tagged_llc_snap_hdr = { {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}}, 0 @@ -559,7 +559,7 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) struct mpoa_client *mpc; struct atmmpc_ioc ioc_data; in_cache_entry *in_entry; - uint32_t ipaddr; + __be32 ipaddr; bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc)); if (bytes_left != 0) { @@ -638,7 +638,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) struct sk_buff *new_skb; eg_cache_entry *eg; struct mpoa_client *mpc; - uint32_t tag; + __be32 tag; char *tmp; ddprintk("mpoa: (%s) mpc_push:\n", dev->name); @@ -683,7 +683,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) } tmp = skb->data + sizeof(struct llc_snap_hdr); - tag = *(uint32_t *)tmp; + tag = *(__be32 *)tmp; eg = mpc->eg_ops->get_by_tag(tag, mpc); if (eg == NULL) { @@ -1029,7 +1029,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; + __be32 dst_ip = msg->content.in_info.in_dst_ip; in_cache_entry *entry; entry = mpc->in_ops->get(dst_ip, mpc); @@ -1066,7 +1066,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) */ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; + __be32 dst_ip = msg->content.in_info.in_dst_ip; struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client); @@ -1102,7 +1102,7 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; + __be32 dst_ip = msg->content.in_info.in_dst_ip; in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc); dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip)); @@ -1148,8 +1148,8 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; - uint32_t mask = msg->ip_mask; + __be32 dst_ip = msg->content.in_info.in_dst_ip; + __be32 mask = msg->ip_mask; in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); if(entry == NULL){ @@ -1173,7 +1173,7 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t cache_id = msg->content.eg_info.cache_id; + __be32 cache_id = msg->content.eg_info.cache_id; eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc); if (entry == NULL) { diff --git a/net/atm/mpc.h b/net/atm/mpc.h index 3c7981a229e8..51f460d005c3 100644 --- a/net/atm/mpc.h +++ b/net/atm/mpc.h @@ -36,14 +36,14 @@ struct mpoa_client { struct atm_mpoa_qos { struct atm_mpoa_qos *next; - uint32_t ipaddr; + __be32 ipaddr; struct atm_qos qos; }; /* MPOA QoS operations */ -struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos); -struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip); +struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos); +struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip); int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos); /* Display QoS entries. This is for the procfs */ diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index fbf13cdcf46e..f3b99b38c91b 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -22,7 +22,7 @@ #define ddprintk(format,args...) #endif -static in_cache_entry *in_cache_get(uint32_t dst_ip, +static in_cache_entry *in_cache_get(__be32 dst_ip, struct mpoa_client *client) { in_cache_entry *entry; @@ -42,9 +42,9 @@ static in_cache_entry *in_cache_get(uint32_t dst_ip, return NULL; } -static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip, +static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip, struct mpoa_client *client, - uint32_t mask) + __be32 mask) { in_cache_entry *entry; @@ -84,7 +84,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc, return NULL; } -static in_cache_entry *in_cache_add_entry(uint32_t dst_ip, +static in_cache_entry *in_cache_add_entry(__be32 dst_ip, struct mpoa_client *client) { in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL); @@ -319,7 +319,7 @@ static void in_destroy_cache(struct mpoa_client *mpc) return; } -static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, struct mpoa_client *mpc) { eg_cache_entry *entry; @@ -339,7 +339,7 @@ static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_c } /* This can be called from any context since it saves CPU flags */ -static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc) { unsigned long flags; eg_cache_entry *entry; @@ -380,7 +380,7 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_clie return NULL; } -static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr, struct mpoa_client *mpc) { eg_cache_entry *entry; diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h index 6c9886a03d0b..84de977def2e 100644 --- a/net/atm/mpoa_caches.h +++ b/net/atm/mpoa_caches.h @@ -29,12 +29,12 @@ typedef struct in_cache_entry { } in_cache_entry; struct in_cache_ops{ - in_cache_entry *(*add_entry)(uint32_t dst_ip, + in_cache_entry *(*add_entry)(__be32 dst_ip, struct mpoa_client *client); - in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client); - in_cache_entry *(*get_with_mask)(uint32_t dst_ip, + in_cache_entry *(*get)(__be32 dst_ip, struct mpoa_client *client); + in_cache_entry *(*get_with_mask)(__be32 dst_ip, struct mpoa_client *client, - uint32_t mask); + __be32 mask); in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client); void (*put)(in_cache_entry *entry); @@ -56,17 +56,17 @@ typedef struct eg_cache_entry{ struct atm_vcc *shortcut; uint32_t packets_rcvd; uint16_t entry_state; - uint32_t latest_ip_addr; /* The src IP address of the last packet */ + __be32 latest_ip_addr; /* The src IP address of the last packet */ struct eg_ctrl_info ctrl_info; atomic_t use; } eg_cache_entry; struct eg_cache_ops{ eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client); - eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client); - eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client); + eg_cache_entry *(*get_by_cache_id)(__be32 cache_id, struct mpoa_client *client); + eg_cache_entry *(*get_by_tag)(__be32 cache_id, struct mpoa_client *client); eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client); - eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client); + eg_cache_entry *(*get_by_src_ip)(__be32 ipaddr, struct mpoa_client *client); void (*put)(eg_cache_entry *entry); void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client); void (*update)(eg_cache_entry *entry, uint16_t holding_time); diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index d37b8911b3ab..3844c85d602f 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -231,14 +231,14 @@ static int parse_qos(const char *buff) */ unsigned char ip[4]; int tx_pcr, tx_sdu, rx_pcr, rx_sdu; - uint32_t ipaddr; + __be32 ipaddr; struct atm_qos qos; memset(&qos, 0, sizeof(struct atm_qos)); if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu", ip, ip+1, ip+2, ip+3) == 4) { - ipaddr = *(uint32_t *)ip; + ipaddr = *(__be32 *)ip; return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); } @@ -250,7 +250,7 @@ static int parse_qos(const char *buff) ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8) return 0; - ipaddr = *(uint32_t *)ip; + ipaddr = *(__be32 *)ip; qos.txtp.traffic_class = ATM_CBR; qos.txtp.max_pcr = tx_pcr; qos.txtp.max_sdu = tx_sdu; -- cgit v1.2.3-70-g09d2 From 47c183fa5ea7feebc356da8ccbd9105a41f8e534 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:11:51 -0800 Subject: [BRIDGE]: Annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter_bridge.h | 2 +- include/linux/netfilter_bridge/ebt_802_3.h | 10 +++++----- include/linux/netfilter_bridge/ebt_among.h | 2 +- include/linux/netfilter_bridge/ebt_arp.h | 14 +++++++------- include/linux/netfilter_bridge/ebt_ip.h | 8 ++++---- include/linux/netfilter_bridge/ebt_vlan.h | 2 +- include/linux/netfilter_bridge/ebtables.h | 2 +- net/bridge/br_netfilter.c | 2 +- net/bridge/netfilter/ebt_802_3.c | 2 +- net/bridge/netfilter/ebt_among.c | 22 +++++++++++----------- net/bridge/netfilter/ebt_arp.c | 6 +++--- net/bridge/netfilter/ebt_ip.c | 4 ++-- net/bridge/netfilter/ebt_log.c | 6 +++--- net/bridge/netfilter/ebt_vlan.c | 2 +- 14 files changed, 42 insertions(+), 42 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 9a4dd11af86e..6c4613f8ad75 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -64,7 +64,7 @@ static inline int nf_bridge_pad(const struct sk_buff *skb) struct bridge_skb_cb { union { - __u32 ipv4; + __be32 ipv4; } daddr; }; diff --git a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h index b9f712c14a0a..07f044ff1a6b 100644 --- a/include/linux/netfilter_bridge/ebt_802_3.h +++ b/include/linux/netfilter_bridge/ebt_802_3.h @@ -28,21 +28,21 @@ struct hdr_ui { uint8_t ssap; uint8_t ctrl; uint8_t orig[3]; - uint16_t type; + __be16 type; }; struct hdr_ni { uint8_t dsap; uint8_t ssap; - uint16_t ctrl; + __be16 ctrl; uint8_t orig[3]; - uint16_t type; + __be16 type; }; struct ebt_802_3_hdr { uint8_t daddr[6]; uint8_t saddr[6]; - uint16_t len; + __be16 len; union { struct hdr_ui ui; struct hdr_ni ni; @@ -61,7 +61,7 @@ static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb) struct ebt_802_3_info { uint8_t sap; - uint16_t type; + __be16 type; uint8_t bitmask; uint8_t invflags; }; diff --git a/include/linux/netfilter_bridge/ebt_among.h b/include/linux/netfilter_bridge/ebt_among.h index 307c1fed8511..7654069233ca 100644 --- a/include/linux/netfilter_bridge/ebt_among.h +++ b/include/linux/netfilter_bridge/ebt_among.h @@ -32,7 +32,7 @@ struct ebt_mac_wormhash_tuple { uint32_t cmp[2]; - uint32_t ip; + __be32 ip; }; struct ebt_mac_wormhash diff --git a/include/linux/netfilter_bridge/ebt_arp.h b/include/linux/netfilter_bridge/ebt_arp.h index 537ec6b487a2..97e4dbde1f89 100644 --- a/include/linux/netfilter_bridge/ebt_arp.h +++ b/include/linux/netfilter_bridge/ebt_arp.h @@ -14,13 +14,13 @@ struct ebt_arp_info { - uint16_t htype; - uint16_t ptype; - uint16_t opcode; - uint32_t saddr; - uint32_t smsk; - uint32_t daddr; - uint32_t dmsk; + __be16 htype; + __be16 ptype; + __be16 opcode; + __be32 saddr; + __be32 smsk; + __be32 daddr; + __be32 dmsk; unsigned char smaddr[ETH_ALEN]; unsigned char smmsk[ETH_ALEN]; unsigned char dmaddr[ETH_ALEN]; diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h index 7247385cdcb1..d6847475bf2e 100644 --- a/include/linux/netfilter_bridge/ebt_ip.h +++ b/include/linux/netfilter_bridge/ebt_ip.h @@ -28,10 +28,10 @@ /* the same values are used for the invflags */ struct ebt_ip_info { - uint32_t saddr; - uint32_t daddr; - uint32_t smsk; - uint32_t dmsk; + __be32 saddr; + __be32 daddr; + __be32 smsk; + __be32 dmsk; uint8_t tos; uint8_t protocol; uint8_t bitmask; diff --git a/include/linux/netfilter_bridge/ebt_vlan.h b/include/linux/netfilter_bridge/ebt_vlan.h index cb1fcc41565f..1d98be4031e7 100644 --- a/include/linux/netfilter_bridge/ebt_vlan.h +++ b/include/linux/netfilter_bridge/ebt_vlan.h @@ -10,7 +10,7 @@ struct ebt_vlan_info { uint16_t id; /* VLAN ID {1-4095} */ uint8_t prio; /* VLAN User Priority {0-7} */ - uint16_t encap; /* VLAN Encapsulated frame code {0-65535} */ + __be16 encap; /* VLAN Encapsulated frame code {0-65535} */ uint8_t bitmask; /* Args bitmask bit 1=1 - ID arg, bit 2=1 User-Priority arg, bit 3=1 encap*/ uint8_t invflags; /* Inverse bitmask bit 1=1 - inversed ID arg, diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index b1a7cc90877b..e6ea70de24d5 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -141,7 +141,7 @@ struct ebt_entry { /* this needs to be the first field */ unsigned int bitmask; unsigned int invflags; - uint16_t ethproto; + __be16 ethproto; /* the physical in-dev */ char in[IFNAMSIZ]; /* the logical in-dev */ diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index ac181be13d83..2a5d31b1a196 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -381,7 +381,7 @@ static int check_hbh_len(struct sk_buff *skb) case IPV6_TLV_JUMBO: if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2) goto bad; - pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2)); + pkt_len = ntohl(*(__be32 *) (skb->nh.raw + off + 2)); if (pkt_len <= IPV6_MAXPLEN || skb->nh.ipv6h->payload_len) goto bad; diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c index d42f63f5e9f8..9abbc09ccdc3 100644 --- a/net/bridge/netfilter/ebt_802_3.c +++ b/net/bridge/netfilter/ebt_802_3.c @@ -17,7 +17,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device * { struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); - uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; + __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; if (info->bitmask & EBT_802_3_SAP) { if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index a614485828af..ce97c4285f9a 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c @@ -15,7 +15,7 @@ #include static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, - const char *mac, uint32_t ip) + const char *mac, __be32 ip) { /* You may be puzzled as to how this code works. * Some tricks were used, refer to @@ -70,7 +70,7 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash return 0; } -static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr) +static int get_ip_dst(const struct sk_buff *skb, __be32 *addr) { if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { struct iphdr _iph, *ih; @@ -81,16 +81,16 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr) *addr = ih->daddr; } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { struct arphdr _arph, *ah; - uint32_t buf, *bp; + __be32 buf, *bp; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL || - ah->ar_pln != sizeof(uint32_t) || + ah->ar_pln != sizeof(__be32) || ah->ar_hln != ETH_ALEN) return -1; bp = skb_header_pointer(skb, sizeof(struct arphdr) + - 2 * ETH_ALEN + sizeof(uint32_t), - sizeof(uint32_t), &buf); + 2 * ETH_ALEN + sizeof(__be32), + sizeof(__be32), &buf); if (bp == NULL) return -1; *addr = *bp; @@ -98,7 +98,7 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr) return 0; } -static int get_ip_src(const struct sk_buff *skb, uint32_t *addr) +static int get_ip_src(const struct sk_buff *skb, __be32 *addr) { if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { struct iphdr _iph, *ih; @@ -109,15 +109,15 @@ static int get_ip_src(const struct sk_buff *skb, uint32_t *addr) *addr = ih->saddr; } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { struct arphdr _arph, *ah; - uint32_t buf, *bp; + __be32 buf, *bp; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL || - ah->ar_pln != sizeof(uint32_t) || + ah->ar_pln != sizeof(__be32) || ah->ar_hln != ETH_ALEN) return -1; bp = skb_header_pointer(skb, sizeof(struct arphdr) + - ETH_ALEN, sizeof(uint32_t), &buf); + ETH_ALEN, sizeof(__be32), &buf); if (bp == NULL) return -1; *addr = *bp; @@ -133,7 +133,7 @@ static int ebt_filter_among(const struct sk_buff *skb, struct ebt_among_info *info = (struct ebt_among_info *) data; const char *dmac, *smac; const struct ebt_mac_wormhash *wh_dst, *wh_src; - uint32_t dip = 0, sip = 0; + __be32 dip = 0, sip = 0; wh_dst = ebt_among_wh_dst(info); wh_src = ebt_among_wh_src(info); diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index a6c81d9f73b8..9c599800a900 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c @@ -35,10 +35,10 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in return EBT_NOMATCH; if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { - uint32_t _addr, *ap; + __be32 _addr, *ap; /* IPv4 addresses are always 4 bytes */ - if (ah->ar_pln != sizeof(uint32_t)) + if (ah->ar_pln != sizeof(__be32)) return EBT_NOMATCH; if (info->bitmask & EBT_ARP_SRC_IP) { ap = skb_header_pointer(skb, sizeof(struct arphdr) + @@ -53,7 +53,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in if (info->bitmask & EBT_ARP_DST_IP) { ap = skb_header_pointer(skb, sizeof(struct arphdr) + - 2*ah->ar_hln+sizeof(uint32_t), + 2*ah->ar_hln+sizeof(__be32), sizeof(_addr), &_addr); if (ap == NULL) return EBT_NOMATCH; diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 65b665ce57b5..e4c642448e1b 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -20,8 +20,8 @@ #include struct tcpudphdr { - uint16_t src; - uint16_t dst; + __be16 src; + __be16 dst; }; static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 466ed3440b74..a184f879f253 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -38,8 +38,8 @@ static int ebt_log_check(const char *tablename, unsigned int hookmask, struct tcpudphdr { - uint16_t src; - uint16_t dst; + __be16 src; + __be16 dst; }; struct arppayload @@ -130,7 +130,7 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, * then log the ARP payload */ if (ah->ar_hrd == htons(1) && ah->ar_hln == ETH_ALEN && - ah->ar_pln == sizeof(uint32_t)) { + ah->ar_pln == sizeof(__be32)) { struct arppayload _arpp, *ap; ap = skb_header_pointer(skb, sizeof(_arph), diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index a2b452862b73..7ee377622964 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c @@ -55,7 +55,7 @@ ebt_filter_vlan(const struct sk_buff *skb, unsigned short id; /* VLAN ID, given from frame TCI */ unsigned char prio; /* user_priority, given from frame TCI */ /* VLAN encapsulated Type/Length field, given from orig frame */ - unsigned short encap; + __be16 encap; fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); if (fp == NULL) -- cgit v1.2.3-70-g09d2 From 75e7ce66ef044fa877a420f1b4febe416bbc09ad Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:13:28 -0800 Subject: [IPVS]: Annotate ..._app_hashkey(). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv4/ipvs/ip_vs_proto_tcp.c | 8 +++++--- net/ipv4/ipvs/ip_vs_proto_udp.c | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index 7de385267b33..b60a07910df7 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -490,16 +490,18 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction, static struct list_head tcp_apps[TCP_APP_TAB_SIZE]; static DEFINE_SPINLOCK(tcp_app_lock); -static inline __u16 tcp_app_hashkey(__u16 port) +static inline __u16 tcp_app_hashkey(__be16 port) { - return ((port >> TCP_APP_TAB_BITS) ^ port) & TCP_APP_TAB_MASK; + return (((__force u16)port >> TCP_APP_TAB_BITS) ^ (__force u16)port) + & TCP_APP_TAB_MASK; } static int tcp_register_app(struct ip_vs_app *inc) { struct ip_vs_app *i; - __u16 hash, port = inc->port; + __u16 hash; + __be16 port = inc->port; int ret = 0; hash = tcp_app_hashkey(port); diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 452cb9c384b3..261581e6a814 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -282,16 +282,18 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) static struct list_head udp_apps[UDP_APP_TAB_SIZE]; static DEFINE_SPINLOCK(udp_app_lock); -static inline __u16 udp_app_hashkey(__u16 port) +static inline __u16 udp_app_hashkey(__be16 port) { - return ((port >> UDP_APP_TAB_BITS) ^ port) & UDP_APP_TAB_MASK; + return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port) + & UDP_APP_TAB_MASK; } static int udp_register_app(struct ip_vs_app *inc) { struct ip_vs_app *i; - __u16 hash, port = inc->port; + __u16 hash; + __be16 port = inc->port; int ret = 0; hash = udp_app_hashkey(port); -- cgit v1.2.3-70-g09d2 From 3277c39f8d706afb6fefc02f49563a73bbd405b9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:13:53 -0800 Subject: [NET]: Kill direct includes of asm/checksum.h Signed-off-by: Al Viro Signed-off-by: David S. Miller --- arch/frv/lib/checksum.c | 1 - arch/sh/kernel/sh_ksyms.c | 1 - drivers/net/ioc3-eth.c | 1 - drivers/net/meth.c | 1 - drivers/net/myri_sbus.c | 1 - drivers/net/typhoon.c | 1 - fs/reiserfs/xattr.c | 2 +- net/802/hippi.c | 1 - net/bridge/br_netfilter.c | 1 - net/ethernet/eth.c | 1 - net/rxrpc/transport.c | 1 - 11 files changed, 1 insertion(+), 11 deletions(-) (limited to 'net') diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c index 20e7dfc474ef..2581a960d58f 100644 --- a/arch/frv/lib/checksum.c +++ b/arch/frv/lib/checksum.c @@ -32,7 +32,6 @@ of the assembly has to go. */ #include -#include #include static inline unsigned short from32to16(unsigned long x) diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 9daad70bc305..8a2fd19dc9eb 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -18,7 +18,6 @@ #include #include #include -#include extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index f56b00ee385e..f0d30cf67b5f 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -57,7 +57,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/meth.c b/drivers/net/meth.c index c1aa60b9a982..e1d97cdf649e 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -33,7 +33,6 @@ #include #include -#include #include #include diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 7747bfd99f91..ee26ef52289f 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -39,7 +39,6 @@ static char version[] = #include #include #include -#include #include "myri_sbus.h" #include "myri_code.h" diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 3bf9e630404f..8ddea1da7c05 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -127,7 +127,6 @@ static const int multicast_filter_limit = 32; #include #include #include -#include #include #include diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 7bdb0ed443e1..1e4d68590178 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/802/hippi.c b/net/802/hippi.c index 6d7fed3dd99a..579e2ddf5ebe 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -36,7 +36,6 @@ #include #include #include -#include #include /* diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 2a5d31b1a196..ac47ba2ba028 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -40,7 +40,6 @@ #include #include -#include #include "br_private.h" #ifdef CONFIG_SYSCTL #include diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 4bd78c8cfb26..2d31bf3f05c5 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -60,7 +60,6 @@ #include #include #include -#include __setup("ether=", netdev_boot_setup); diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c index 94b2e2fe6fdb..4268b38d92d2 100644 --- a/net/rxrpc/transport.c +++ b/net/rxrpc/transport.c @@ -31,7 +31,6 @@ #endif #include #include -#include #include "internal.h" struct errormsg { -- cgit v1.2.3-70-g09d2 From d3bc23e7ee9db8023dff5a86bb3b0069ed018789 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:24:49 -0800 Subject: [NET]: Annotate callers of csum_fold() in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/datagram.c | 8 ++++---- net/core/dev.c | 4 ++-- net/core/netpoll.c | 2 +- net/core/skbuff.c | 4 ++-- net/ipv4/icmp.c | 4 ++-- net/ipv4/igmp.c | 2 +- net/ipv4/ip_gre.c | 4 ++-- net/ipv4/ip_output.c | 2 +- net/ipv4/ipmr.c | 2 +- net/ipv4/ipvs/ip_vs_core.c | 2 +- net/ipv4/netfilter.c | 2 +- net/ipv4/tcp.c | 8 +++++--- net/sunrpc/socklib.c | 2 +- 13 files changed, 24 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/net/core/datagram.c b/net/core/datagram.c index f558c61aecc7..e5a05a046fef 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -413,9 +413,9 @@ fault: unsigned int __skb_checksum_complete(struct sk_buff *skb) { - unsigned int sum; + __sum16 sum; - sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); + sum = csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); if (likely(!sum)) { if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) netdev_rx_csum_fault(skb->dev); @@ -441,7 +441,7 @@ EXPORT_SYMBOL(__skb_checksum_complete); int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, struct iovec *iov) { - unsigned int csum; + __wsum csum; int chunk = skb->len - hlen; /* Skip filled elements. @@ -460,7 +460,7 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, chunk, &csum)) goto fault; - if ((unsigned short)csum_fold(csum)) + if (csum_fold(csum)) goto csum_error; if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) netdev_rx_csum_fault(skb->dev); diff --git a/net/core/dev.c b/net/core/dev.c index a7be106d0fdb..1a36b17f4b51 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(netif_device_attach); */ int skb_checksum_help(struct sk_buff *skb) { - unsigned int csum; + __wsum csum; int ret = 0, offset = skb->h.raw - skb->data; if (skb->ip_summed == CHECKSUM_COMPLETE) @@ -1193,7 +1193,7 @@ int skb_checksum_help(struct sk_buff *skb) BUG_ON(offset <= 0); BUG_ON(skb->csum + 2 > offset); - *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum); + *(__sum16*)(skb->h.raw + skb->csum) = csum_fold(csum); out_set_summed: skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 523141ee920c..edd3246873e8 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -88,7 +88,7 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); if (skb->ip_summed == CHECKSUM_COMPLETE && - !(u16)csum_fold(csum_add(psum, skb->csum))) + !csum_fold(csum_add(psum, skb->csum))) return 0; skb->csum = psum; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b3dea1ef9535..dfa02cc8d687 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1396,7 +1396,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) { - unsigned int csum; + __wsum csum; long csstart; if (skb->ip_summed == CHECKSUM_PARTIAL) @@ -1416,7 +1416,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) if (skb->ip_summed == CHECKSUM_PARTIAL) { long csstuff = csstart + skb->csum; - *((unsigned short *)(to + csstuff)) = csum_fold(csum); + *((__sum16 *)(to + csstuff)) = csum_fold(csum); } } diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index b39a37a47545..cb9da0842b77 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -356,7 +356,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, ip_flush_pending_frames(icmp_socket->sk); else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { struct icmphdr *icmph = skb->h.icmph; - unsigned int csum = 0; + __wsum csum = 0; struct sk_buff *skb1; skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) { @@ -931,7 +931,7 @@ int icmp_rcv(struct sk_buff *skb) switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (!(u16)csum_fold(skb->csum)) + if (!csum_fold(skb->csum)) break; /* fall through */ case CHECKSUM_NONE: diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6eee71647b7c..0017ccb01d6d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -932,7 +932,7 @@ int igmp_rcv(struct sk_buff *skb) switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (!(u16)csum_fold(skb->csum)) + if (!csum_fold(skb->csum)) break; /* fall through */ case CHECKSUM_NONE: diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 25221146debb..2bf54adee8c2 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -557,7 +557,7 @@ static int ipgre_rcv(struct sk_buff *skb) struct iphdr *iph; u8 *h; __be16 flags; - u16 csum = 0; + __sum16 csum = 0; __be32 key = 0; u32 seqno = 0; struct ip_tunnel *tunnel; @@ -580,7 +580,7 @@ static int ipgre_rcv(struct sk_buff *skb) if (flags&GRE_CSUM) { switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - csum = (u16)csum_fold(skb->csum); + csum = csum_fold(skb->csum); if (!csum) break; /* fall through */ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 90942a384a45..5f3e35c03637 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1384,7 +1384,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar &ipc, rt, MSG_DONTWAIT); if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { if (arg->csumoffset >= 0) - *((u16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum)); + *((__sum16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum)); skb->ip_summed = CHECKSUM_NONE; ip_push_pending_frames(sk); } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 97cfa97c8abb..efcf45ecc818 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1493,7 +1493,7 @@ static int pim_rcv(struct sk_buff * skb) if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) || (pim->flags&PIM_NULL_REGISTER) || (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && - (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0)))) + csum_fold(skb_checksum(skb, 0, skb->len, 0)))) goto drop; /* check if the inner packet is destined to mcast group */ diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 1445bb47fea4..fac2dffd6672 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -538,7 +538,7 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum, u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) { - return (u16) csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); + return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); } static inline struct sk_buff * diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index e49441ac3571..b797a37c01ce 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -172,7 +172,7 @@ unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, case CHECKSUM_COMPLETE: if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) break; - if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || + if ((protocol == 0 && !csum_fold(skb->csum)) || !csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - dataoff, protocol, skb->csum)) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index dadef867a3bb..168f9de906bc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2162,7 +2162,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) struct tcphdr *th; unsigned thlen; unsigned int seq; - unsigned int delta; + __be32 delta; unsigned int oldlen; unsigned int len; @@ -2215,7 +2215,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) do { th->fin = th->psh = 0; - th->check = ~csum_fold(th->check + delta); + th->check = ~csum_fold((__force __wsum)((__force u32)th->check + + (__force u32)delta)); if (skb->ip_summed != CHECKSUM_PARTIAL) th->check = csum_fold(csum_partial(skb->h.raw, thlen, skb->csum)); @@ -2229,7 +2230,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) } while (skb->next); delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); - th->check = ~csum_fold(th->check + delta); + th->check = ~csum_fold((__force __wsum)((__force u32)th->check + + (__force u32)delta)); if (skb->ip_summed != CHECKSUM_PARTIAL) th->check = csum_fold(csum_partial(skb->h.raw, thlen, skb->csum)); diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 6f17527b9e69..61a038fc30cf 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c @@ -166,7 +166,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) } if (desc.count) return -1; - if ((unsigned short)csum_fold(desc.csum)) + if (csum_fold(desc.csum)) return -1; if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) netdev_rx_csum_fault(skb->dev); -- cgit v1.2.3-70-g09d2 From d6f5493c1a42b1203e5b0cb0507afd00bb2927bf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:26:08 -0800 Subject: [NET]: Annotate callers of csum_tcpudp_nofold() in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/ip.h | 2 +- net/core/netpoll.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/include/net/ip.h b/include/net/ip.h index 412e8114667d..eafbcaf728fd 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -135,7 +135,7 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf) struct ip_reply_arg { struct kvec iov[1]; - u32 csum; + __wsum csum; int csumoffset; /* u16 offset of csum in iov[0].iov_base */ /* -1 if not needed */ }; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index edd3246873e8..26ee1791aa02 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -78,9 +78,9 @@ static void queue_process(void *p) } static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, u32 saddr, u32 daddr) + unsigned short ulen, __be32 saddr, __be32 daddr) { - unsigned int psum; + __wsum psum; if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY) return 0; -- cgit v1.2.3-70-g09d2 From 6b11687ef003ed595033da89643c8995676f929d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:28:24 -0800 Subject: [NET]: Annotate csum_tcpudp_magic() callers in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/tcp.h | 6 +++--- net/ipv4/udp.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/tcp.h b/include/net/tcp.h index 363960872de0..826aaecdb994 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -807,9 +807,9 @@ static inline void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq) /* * Calculate(/check) TCP checksum */ -static inline u16 tcp_v4_check(struct tcphdr *th, int len, - unsigned long saddr, unsigned long daddr, - unsigned long base) +static inline __sum16 tcp_v4_check(struct tcphdr *th, int len, + __be32 saddr, __be32 daddr, + __wsum base) { return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 98ba75096175..f9c4ed7207bb 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -414,8 +414,9 @@ static void udp_flush_pending_frames(struct sock *sk) static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, __be32 src, __be32 dst, int len ) { - unsigned int csum = 0, offset; + unsigned int offset; struct udphdr *uh = skb->h.uh; + __wsum csum = 0; if (skb_queue_len(&sk->sk_write_queue) == 1) { /* -- cgit v1.2.3-70-g09d2 From 2bda2853150e20ca2a44627d00b5f85af0b24a42 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:28:51 -0800 Subject: [NET]: Annotate csum_tcpudp_magic() callers in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 35985334daee..6bca71929de5 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -344,7 +344,7 @@ out: sock_put(sk); } -static inline u16 dccp_v4_csum_finish(struct sk_buff *skb, +static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb, __be32 src, __be32 dst) { return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum); -- cgit v1.2.3-70-g09d2 From 868c86bcb5bdea7ed8d45979b17bb919af9254db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:35:48 -0800 Subject: [NET]: annotate csum_ipv6_magic() callers in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/udp.h | 4 ++-- include/net/udplite.h | 4 ++-- net/dccp/ipv6.c | 2 +- net/ipv6/icmp.c | 14 +++++++------- net/ipv6/mcast.c | 4 ++-- net/ipv6/netfilter.c | 5 +++-- net/ipv6/raw.c | 11 +++++------ net/ipv6/tcp_ipv6.c | 8 ++++---- net/ipv6/udp.c | 9 +++++---- 9 files changed, 31 insertions(+), 30 deletions(-) (limited to 'net') diff --git a/include/net/udp.h b/include/net/udp.h index 4f0626735ed3..39e825a6909a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -89,9 +89,9 @@ static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb) * @skb: sk_buff containing the filled-in UDP header * (checksum field must be zeroed out) */ -static inline u32 udp_csum_outgoing(struct sock *sk, struct sk_buff *skb) +static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb) { - u32 csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0); + __wsum csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0); skb_queue_walk(&sk->sk_write_queue, skb) { csum = csum_add(csum, skb->csum); diff --git a/include/net/udplite.h b/include/net/udplite.h index 1473b3e49044..406eb755b34e 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -124,10 +124,10 @@ static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh) return cscov; } -static inline u32 udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) +static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) { - u32 csum = 0; int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh); + __wsum csum = 0; skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index e0a0607862ef..f28e406a4a1f 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -59,7 +59,7 @@ static void dccp_v6_hash(struct sock *sk) } /* add pseudo-header to DCCP checksum stored in skb->csum */ -static inline u16 dccp_v6_csum_finish(struct sk_buff *skb, +static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, struct in6_addr *saddr, struct in6_addr *daddr) { diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index bd51847acd57..4ab8acf37b54 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -234,7 +234,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct len, fl->proto, skb->csum); } else { - u32 tmp_csum = 0; + __wsum tmp_csum = 0; skb_queue_walk(&sk->sk_write_queue, skb) { tmp_csum = csum_add(tmp_csum, skb->csum); @@ -242,10 +242,10 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct tmp_csum = csum_partial((char *)icmp6h, sizeof(struct icmp6hdr), tmp_csum); - tmp_csum = csum_ipv6_magic(&fl->fl6_src, - &fl->fl6_dst, - len, fl->proto, tmp_csum); - icmp6h->icmp6_cksum = tmp_csum; + icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, + &fl->fl6_dst, + len, fl->proto, + tmp_csum); } ip6_push_pending_frames(sk); out: @@ -636,8 +636,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) break; /* fall through */ case CHECKSUM_NONE: - skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, - IPPROTO_ICMPV6, 0); + skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, + IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", NIP6(*saddr), NIP6(*daddr)); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index c006d02be8bc..a1c231a04ac2 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -91,7 +91,7 @@ struct mld2_grec { struct mld2_report { __u8 type; __u8 resv1; - __u16 csum; + __sum16 csum; __be16 resv2; __be16 ngrec; struct mld2_grec grec[0]; @@ -100,7 +100,7 @@ struct mld2_report { struct mld2_query { __u8 type; __u8 code; - __u16 csum; + __sum16 csum; __be16 mrc; __be16 resv1; struct in6_addr mca; diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 646a47456fd4..8d1b542806c1 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -100,12 +100,13 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, } /* fall through */ case CHECKSUM_NONE: - skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->csum = ~csum_unfold( + csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, protocol, csum_sub(0, skb_checksum(skb, 0, - dataoff, 0))); + dataoff, 0)))); csum = __skb_checksum_complete(skb); } return csum; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index b03040a20814..cee5db27e8b4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -370,9 +370,9 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) skb->ip_summed = CHECKSUM_UNNECESSARY; } if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len, inet->num, 0); + skb->len, inet->num, 0)); if (inet->hdrincl) { if (skb_checksum_complete(skb)) { @@ -479,8 +479,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, int offset; int len; int total_len; - u32 tmp_csum; - u16 csum; + __wsum tmp_csum; + __sum16 csum; if (!rp->checksum) goto send; @@ -532,14 +532,13 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, if (unlikely(csum)) tmp_csum = csum_sub(tmp_csum, csum); - tmp_csum = csum_ipv6_magic(&fl->fl6_src, + csum = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, total_len, fl->proto, tmp_csum); if (tmp_csum == 0 && fl->proto == IPPROTO_UDP) tmp_csum = -1; - csum = tmp_csum; if (skb_store_bits(skb, offset, &csum, 2)) BUG(); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 53f270995d8a..394bc54c5c21 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -105,10 +105,10 @@ static void tcp_v6_hash(struct sock *sk) } } -static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, +static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len, struct in6_addr *saddr, struct in6_addr *daddr, - unsigned long base) + __wsum base) { return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); } @@ -1537,8 +1537,8 @@ static int tcp_v6_checksum_init(struct sk_buff *skb) } } - skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, 0); + skb->csum = ~csum_unfold(tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, 0)); if (skb->len <= 76) { return __skb_checksum_complete(skb); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e6e1f85f1bbd..0d22008d522e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -383,9 +383,10 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) skb->ip_summed = CHECKSUM_UNNECESSARY; if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, - skb->len, IPPROTO_UDP, 0); + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, + ulen, IPPROTO_UDP, + 0)); return (UDP_SKB_CB(skb)->partial_cov = 0); } @@ -511,7 +512,7 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; int err = 0; - u32 csum = 0; + __wsum csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) -- cgit v1.2.3-70-g09d2 From 44bb93633f57a55979f3c2589b10fd6a2bfc7c08 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:36:14 -0800 Subject: [NET]: Annotate csum_partial() callers in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/socket.h | 2 +- include/linux/sunrpc/xdr.h | 2 +- net/core/iovec.c | 4 ++-- net/core/skbuff.c | 2 +- net/ipv4/ip_output.c | 8 ++++---- net/unix/af_unix.c | 3 ++- 6 files changed, 11 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/include/linux/socket.h b/include/linux/socket.h index 592b66679823..92cd38efad7f 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -293,7 +293,7 @@ extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, extern int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, - unsigned int len, int *csump); + unsigned int len, __wsum *csump); extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index ac69e5511606..9a527c364394 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -151,7 +151,7 @@ typedef struct { struct sk_buff *skb; unsigned int offset; size_t count; - unsigned int csum; + __wsum csum; } skb_reader_t; typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len); diff --git a/net/core/iovec.c b/net/core/iovec.c index 65e4b56fbc77..04b249c40b5b 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -158,9 +158,9 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, * call to this function will be unaligned also. */ int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov, - int offset, unsigned int len, int *csump) + int offset, unsigned int len, __wsum *csump) { - int csum = *csump; + __wsum csum = *csump; int partial_cnt = 0, err = 0; /* Skip over the finished iovecs */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index dfa02cc8d687..c0e3427057fc 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1265,7 +1265,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset, end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { - unsigned int csum2; + __wsum csum2; u8 *vaddr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 5f3e35c03637..f9194f7e39d3 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -682,7 +682,7 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk if (memcpy_fromiovecend(to, iov, offset, len) < 0) return -EFAULT; } else { - unsigned int csum = 0; + __wsum csum = 0; if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0) return -EFAULT; skb->csum = csum_block_add(skb->csum, csum, odd); @@ -690,11 +690,11 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk return 0; } -static inline unsigned int +static inline __wsum csum_page(struct page *page, int offset, int copy) { char *kaddr; - unsigned int csum; + __wsum csum; kaddr = kmap(page); csum = csum_partial(kaddr + offset, copy, 0); kunmap(page); @@ -1166,7 +1166,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, } if (skb->ip_summed == CHECKSUM_NONE) { - unsigned int csum; + __wsum csum; csum = csum_page(page, offset, len); skb->csum = csum_block_add(skb->csum, csum, skb->len); } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b43a27828df5..2f208c7f4d43 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -151,8 +151,9 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) * each socket state is protected by separate rwlock. */ -static inline unsigned unix_hash_fold(unsigned hash) +static inline unsigned unix_hash_fold(__wsum n) { + unsigned hash = (__force unsigned)n; hash ^= hash>>16; hash ^= hash>>8; return hash&(UNIX_HASH_SIZE-1); -- cgit v1.2.3-70-g09d2 From 5084205faf45384fff25c4cf77dd5c96279283ad Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:36:34 -0800 Subject: [NET]: Annotate callers of csum_partial_copy_...() and csum_and_copy...() in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/skbuff.h | 3 +-- include/net/sock.h | 2 +- net/core/datagram.c | 6 +++--- net/core/skbuff.c | 2 +- net/ipv4/ip_output.c | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e3ae544b3956..64fa7f4c702d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1199,8 +1199,7 @@ static inline int skb_add_data(struct sk_buff *skb, if (skb->ip_summed == CHECKSUM_NONE) { int err = 0; - unsigned int csum = csum_and_copy_from_user(from, - skb_put(skb, copy), + __wsum csum = csum_and_copy_from_user(from, skb_put(skb, copy), copy, 0, &err); if (!err) { skb->csum = csum_block_add(skb->csum, csum, off); diff --git a/include/net/sock.h b/include/net/sock.h index 35ffbdd35d3e..dc4b92b8abea 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1088,7 +1088,7 @@ static inline int skb_copy_to_page(struct sock *sk, char __user *from, { if (skb->ip_summed == CHECKSUM_NONE) { int err = 0; - unsigned int csum = csum_and_copy_from_user(from, + __wsum csum = csum_and_copy_from_user(from, page_address(page) + off, copy, 0, &err); if (err) diff --git a/net/core/datagram.c b/net/core/datagram.c index e5a05a046fef..0d9c9bac4006 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -321,7 +321,7 @@ fault: static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 __user *to, int len, - unsigned int *csump) + __wsum *csump) { int start = skb_headlen(skb); int pos = 0; @@ -350,7 +350,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { - unsigned int csum2; + __wsum csum2; int err = 0; u8 *vaddr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -386,7 +386,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, end = start + list->len; if ((copy = end - offset) > 0) { - unsigned int csum2 = 0; + __wsum csum2 = 0; if (copy > len) copy = len; if (skb_copy_and_csum_datagram(list, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c0e3427057fc..da6683f4b31d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1342,7 +1342,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { - unsigned int csum2; + __wsum csum2; u8 *vaddr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index f9194f7e39d3..1da3d32f8289 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1314,7 +1314,7 @@ void ip_flush_pending_frames(struct sock *sk) static int ip_reply_glue_bits(void *dptr, char *to, int offset, int len, int odd, struct sk_buff *skb) { - unsigned int csum; + __wsum csum; csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0); skb->csum = csum_block_add(skb->csum, csum, odd); -- cgit v1.2.3-70-g09d2 From 5f92a7388a29594d6c365b23a48d4bb8299a3ea7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:36:54 -0800 Subject: [NET]: Annotate callers of the reset of checksum.h stuff. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/skbuff.c | 2 +- net/ipv4/icmp.c | 2 +- net/ipv4/ip_gre.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/raw.c | 2 +- net/sunrpc/socklib.c | 5 +++-- 6 files changed, 8 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index da6683f4b31d..6e8c15b39eb8 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1294,7 +1294,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset, end = start + list->len; if ((copy = end - offset) > 0) { - unsigned int csum2; + __wsum csum2; if (copy > len) copy = len; csum2 = skb_checksum(list, offset - start, diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index cb9da0842b77..40cf0d0e1b83 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -332,7 +332,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) { struct icmp_bxm *icmp_param = (struct icmp_bxm *)from; - unsigned int csum; + __wsum csum; csum = skb_copy_and_csum_bits(icmp_param->skb, icmp_param->offset + offset, diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2bf54adee8c2..476cb6084c75 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -877,7 +877,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (tunnel->parms.o_flags&GRE_CSUM) { *ptr = 0; - *(__be16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); + *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); } } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4ab8acf37b54..3dcc4b7f41b4 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -262,7 +262,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st { struct icmpv6_msg *msg = (struct icmpv6_msg *) from; struct sk_buff *org_skb = msg->skb; - __u32 csum = 0; + __wsum csum = 0; csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset, to, len, csum); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index cee5db27e8b4..9b21d67ca48c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -530,7 +530,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, /* in case cksum was not initialized */ if (unlikely(csum)) - tmp_csum = csum_sub(tmp_csum, csum); + tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); csum = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 61a038fc30cf..2635c543ba06 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c @@ -45,7 +45,8 @@ static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len) */ static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len) { - unsigned int csum2, pos; + unsigned int pos; + __wsum csum2; if (len > desc->count) len = desc->count; @@ -160,7 +161,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0) return -1; if (desc.offset != skb->len) { - unsigned int csum2; + __wsum csum2; csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); desc.csum = csum_block_add(desc.csum, csum2, desc.offset); } -- cgit v1.2.3-70-g09d2 From 2bbbc86890ac4c911c5057f69af93853e52a42a8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:37:14 -0800 Subject: [NET]: Annotate skb_checksum() and callers. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- net/core/skbuff.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 64fa7f4c702d..784129fb61d4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1334,8 +1334,8 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); -extern unsigned int skb_checksum(const struct sk_buff *skb, int offset, - int len, unsigned int csum); +extern __wsum skb_checksum(const struct sk_buff *skb, int offset, + int len, __wsum csum); extern int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len); extern int skb_store_bits(const struct sk_buff *skb, int offset, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e8c15b39eb8..be9b541f536f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1240,8 +1240,8 @@ EXPORT_SYMBOL(skb_store_bits); /* Checksum skb data. */ -unsigned int skb_checksum(const struct sk_buff *skb, int offset, - int len, unsigned int csum) +__wsum skb_checksum(const struct sk_buff *skb, int offset, + int len, __wsum csum) { int start = skb_headlen(skb); int i, copy = start - offset; -- cgit v1.2.3-70-g09d2 From 81d77662763ae527ba3a9b9275467901aaab7dfd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:37:33 -0800 Subject: [NET]: Annotate skb_copy_and_csum_bits() and callers. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- net/core/skbuff.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 784129fb61d4..874ca029fbb9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1340,9 +1340,9 @@ extern int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len); extern int skb_store_bits(const struct sk_buff *skb, int offset, void *from, int len); -extern unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, +extern __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, - unsigned int csum); + __wsum csum); extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index be9b541f536f..07c25d601922 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1315,8 +1315,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, /* Both of above in one bottle. */ -unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, - u8 *to, int len, unsigned int csum) +__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, + u8 *to, int len, __wsum csum) { int start = skb_headlen(skb); int i, copy = start - offset; @@ -1368,7 +1368,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - unsigned int csum2; + __wsum csum2; int end; BUG_TRAP(start <= offset + len); -- cgit v1.2.3-70-g09d2 From b1550f221255f7dd06048d832bf0f3d166840e1c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:37:50 -0800 Subject: [NET]: Annotate ip_vs_checksum_complete() and callers. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/ip_vs.h | 2 +- net/ipv4/ipvs/ip_vs_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 903108e583f8..fedea8db156a 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -988,7 +988,7 @@ extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len); extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int dir); -extern u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); +extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); static inline u16 ip_vs_check_diff(u32 old, u32 new, u16 oldsum) { diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index fac2dffd6672..34257520a3a6 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -536,7 +536,7 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum, return NF_STOP; } -u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) +__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) { return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); } -- cgit v1.2.3-70-g09d2 From b51655b958dfb1176bfcf99466231fdbef8751ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:40:42 -0800 Subject: [NET]: Annotate __skb_checksum_complete() and friends. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter.h | 6 +++--- include/linux/netfilter_ipv4.h | 2 +- include/linux/netfilter_ipv6.h | 2 +- include/linux/skbuff.h | 2 +- include/net/tcp.h | 2 +- include/net/udp.h | 8 ++++---- net/core/datagram.c | 2 +- net/core/netpoll.c | 4 ++-- net/ipv4/netfilter.c | 4 ++-- net/ipv4/tcp_input.c | 4 ++-- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/netfilter.c | 4 ++-- net/ipv6/tcp_ipv6.c | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index b7e67d1d4382..707bb2e53c4e 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -290,7 +290,7 @@ extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, struct nf_afinfo { unsigned short family; - unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, + __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); void (*saveroute)(const struct sk_buff *skb, struct nf_info *info); @@ -305,12 +305,12 @@ static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) return rcu_dereference(nf_afinfo[family]); } -static inline unsigned int +static inline __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol, unsigned short family) { struct nf_afinfo *afinfo; - unsigned int csum = 0; + __sum16 csum = 0; rcu_read_lock(); afinfo = nf_get_afinfo(family); diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 5b63a231a76b..5821eb5a0a3e 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -79,7 +79,7 @@ enum nf_ip_hook_priorities { #ifdef __KERNEL__ extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type); extern int ip_xfrm_me_harder(struct sk_buff **pskb); -extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, +extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); #endif /*__KERNEL__*/ diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index d97e268cdfe5..ab81a6dc94ea 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -74,7 +74,7 @@ enum nf_ip6_hook_priorities { #ifdef CONFIG_NETFILTER extern int ip6_route_me_harder(struct sk_buff *skb); -extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, +extern __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); extern int ipv6_netfilter_init(void); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 874ca029fbb9..41753667541d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1398,7 +1398,7 @@ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval * extern void __net_timestamp(struct sk_buff *skb); -extern unsigned int __skb_checksum_complete(struct sk_buff *skb); +extern __sum16 __skb_checksum_complete(struct sk_buff *skb); /** * skb_checksum_complete - Calculate checksum of an entire packet diff --git a/include/net/tcp.h b/include/net/tcp.h index 826aaecdb994..aa7989c53791 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -814,7 +814,7 @@ static inline __sum16 tcp_v4_check(struct tcphdr *th, int len, return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base); } -static inline int __tcp_checksum_complete(struct sk_buff *skb) +static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb) { return __skb_checksum_complete(skb); } diff --git a/include/net/udp.h b/include/net/udp.h index 39e825a6909a..c5ccd9a3387b 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -69,15 +69,15 @@ struct sk_buff; /* * Generic checksumming routines for UDP(-Lite) v4 and v6 */ -static inline u16 __udp_lib_checksum_complete(struct sk_buff *skb) +static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) { if (! UDP_SKB_CB(skb)->partial_cov) return __skb_checksum_complete(skb); - return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov, - skb->csum)); + return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov, + skb->csum)); } -static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb) +static inline __sum16 udp_lib_checksum_complete(struct sk_buff *skb) { return skb->ip_summed != CHECKSUM_UNNECESSARY && __udp_lib_checksum_complete(skb); diff --git a/net/core/datagram.c b/net/core/datagram.c index 0d9c9bac4006..797fdd4352ce 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -411,7 +411,7 @@ fault: return -EFAULT; } -unsigned int __skb_checksum_complete(struct sk_buff *skb) +__sum16 __skb_checksum_complete(struct sk_buff *skb) { __sum16 sum; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 26ee1791aa02..8be3681d3d80 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -77,8 +77,8 @@ static void queue_process(void *p) } } -static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, __be32 saddr, __be32 daddr) +static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, + unsigned short ulen, __be32 saddr, __be32 daddr) { __wsum psum; diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b797a37c01ce..a68966059b50 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -162,11 +162,11 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, +__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { struct iphdr *iph = skb->nh.iph; - unsigned int csum = 0; + __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6ab3423674bb..9304034c0c47 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3790,9 +3790,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) return err; } -static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) +static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) { - int result; + __sum16 result; if (sock_owned_by_user(sk)) { local_bh_enable(); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0ca8dead03b0..dadf80272413 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1544,7 +1544,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -static int tcp_v4_checksum_init(struct sk_buff *skb) +static __sum16 tcp_v4_checksum_init(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_COMPLETE) { if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 8d1b542806c1..f6294e5bcb31 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -80,11 +80,11 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, +__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { struct ipv6hdr *ip6h = skb->nh.ipv6h; - unsigned int csum = 0; + __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 394bc54c5c21..147ce499f509 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1527,7 +1527,7 @@ out: return NULL; } -static int tcp_v6_checksum_init(struct sk_buff *skb) +static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_COMPLETE) { if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, -- cgit v1.2.3-70-g09d2 From f6ab028804bdc580fe0915494dbf31f5ea473ca7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 16 Nov 2006 02:36:50 -0800 Subject: [NET]: Make mangling a checksum (0 -> 0xffff on the wire) explicit. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/checksum.h | 1 + net/ipv4/ipvs/ip_vs_proto_udp.c | 6 +++--- net/ipv4/netfilter/ip_nat_helper.c | 2 +- net/ipv4/netfilter/ip_nat_proto_udp.c | 2 +- net/ipv4/udp.c | 4 ++-- net/ipv6/raw.c | 4 ++-- net/ipv6/udp.c | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/include/net/checksum.h b/include/net/checksum.h index 2b3c8dc6c11d..124246172a88 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -92,4 +92,5 @@ static inline __wsum csum_unfold(__sum16 n) return (__force __wsum)n; } +#define CSUM_MANGLED_0 ((__force __sum16)0xffff) #endif diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 261581e6a814..3647397e416d 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -125,7 +125,7 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, ip_vs_check_diff(oldport ^ htons(0xFFFF), newport, uhdr->check)); if (!uhdr->check) - uhdr->check = -1; + uhdr->check = CSUM_MANGLED_0; } static int @@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = -1; + udph->check = CSUM_MANGLED_0; IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", pp->name, udph->check, (char*)&(udph->check) - (char*)udph); @@ -228,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = -1; + udph->check = CSUM_MANGLED_0; (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; } return 1; diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c index 3bf858480558..3e7fd64c2162 100644 --- a/net/ipv4/netfilter/ip_nat_helper.c +++ b/net/ipv4/netfilter/ip_nat_helper.c @@ -264,7 +264,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, csum_partial((char *)udph, datalen, 0)); if (!udph->check) - udph->check = -1; + udph->check = CSUM_MANGLED_0; } else udph->check = nf_proto_csum_update(*pskb, htons(oldlen) ^ htons(0xFFFF), diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 4bbec7730d18..82f8a6ab07ec 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -121,7 +121,7 @@ udp_manip_pkt(struct sk_buff **pskb, *portptr ^ htons(0xFFFF), newport, hdr->check, 0); if (!hdr->check) - hdr->check = -1; + hdr->check = CSUM_MANGLED_0; } *portptr = newport; return 1; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f9c4ed7207bb..dc19ba1e73b5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -441,7 +441,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum); if (uh->check == 0) - uh->check = -1; + uh->check = CSUM_MANGLED_0; } } @@ -490,7 +490,7 @@ int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len, sk->sk_protocol, csum ); if (uh->check == 0) - uh->check = -1; + uh->check = CSUM_MANGLED_0; send: err = ip_push_pending_frames(sk); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 9b21d67ca48c..c2e629d6aea4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -536,8 +536,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, &fl->fl6_dst, total_len, fl->proto, tmp_csum); - if (tmp_csum == 0 && fl->proto == IPPROTO_UDP) - tmp_csum = -1; + if (csum == 0 && fl->proto == IPPROTO_UDP) + csum = CSUM_MANGLED_0; if (skb_store_bits(skb, offset, &csum, 2)) BUG(); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 0d22008d522e..bb45b9b7cbd9 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -536,7 +536,7 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, up->len, fl->proto, csum ); if (uh->check == 0) - uh->check = -1; + uh->check = CSUM_MANGLED_0; err = ip6_push_pending_frames(sk); out: -- cgit v1.2.3-70-g09d2 From f9214b2627fb8582af1986afc4aed5942086a535 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 16 Nov 2006 02:41:18 -0800 Subject: [NET]: ipvs checksum annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/ip_vs.h | 14 ++++++++++---- net/ipv4/ipvs/ip_vs_proto_tcp.c | 6 +++--- net/ipv4/ipvs/ip_vs_proto_udp.c | 6 +++--- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index fedea8db156a..672564e5a81d 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -990,12 +990,18 @@ extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); -static inline u16 ip_vs_check_diff(u32 old, u32 new, u16 oldsum) +static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum) { - u32 diff[2] = { old, new }; + __be32 diff[2] = { ~old, new }; - return csum_fold(csum_partial((char *) diff, sizeof(diff), - oldsum ^ 0xFFFF)); + return csum_partial((char *) diff, sizeof(diff), oldsum); +} + +static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum) +{ + __be16 diff[2] = { ~old, new }; + + return csum_partial((char *) diff, sizeof(diff), oldsum); } #endif /* __KERNEL__ */ diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index b60a07910df7..16a9ebee2fe6 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -116,9 +116,9 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip, __be16 oldport, __be16 newport) { tcph->check = - ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ htons(0xFFFF), - newport, tcph->check)); + csum_fold(ip_vs_check_diff4(oldip, newip, + ip_vs_check_diff2(oldport, newport, + ~csum_unfold(tcph->check)))); } diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 3647397e416d..03f0a414cfa4 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -121,9 +121,9 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, __be16 oldport, __be16 newport) { uhdr->check = - ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ htons(0xFFFF), - newport, uhdr->check)); + csum_fold(ip_vs_check_diff4(oldip, newip, + ip_vs_check_diff2(oldport, newport, + ~csum_unfold(uhdr->check)))); if (!uhdr->check) uhdr->check = CSUM_MANGLED_0; } -- cgit v1.2.3-70-g09d2 From 43bc0ca7eadc024e9e5b935fa5e0892df4fec9eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:43:23 -0800 Subject: [NET]: netfilter checksum annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter.h | 26 +++++++++++++++---- .../linux/netfilter_ipv4/ip_conntrack_proto_gre.h | 4 +-- net/ipv4/netfilter/ip_nat_core.c | 6 ++--- net/ipv4/netfilter/ip_nat_helper.c | 30 ++++++++-------------- net/ipv4/netfilter/ip_nat_proto_gre.c | 8 +++--- net/ipv4/netfilter/ip_nat_proto_icmp.c | 6 ++--- net/ipv4/netfilter/ip_nat_proto_tcp.c | 5 ++-- net/ipv4/netfilter/ip_nat_proto_udp.c | 7 ++--- net/ipv4/netfilter/ipt_ECN.c | 11 +++----- net/ipv4/netfilter/ipt_TCPMSS.c | 24 ++++++----------- net/ipv4/netfilter/ipt_TOS.c | 5 ++-- net/ipv4/netfilter/ipt_TTL.c | 5 ++-- net/netfilter/core.c | 27 ++++++++----------- 13 files changed, 70 insertions(+), 94 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 707bb2e53c4e..6ab5e2d6133e 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -282,11 +282,27 @@ extern void nf_invalidate_cache(int pf); Returns true or false. */ extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); -extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, - u_int32_t csum); -extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, - u_int32_t oldval, u_int32_t newval, - u_int16_t csum, int pseudohdr); +static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to) +{ + __be32 diff[] = { ~from, to }; + + *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(*sum))); +} + +static inline void nf_csum_replace2(__sum16 *sum, __be16 from, __be16 to) +{ + nf_csum_replace4(sum, (__force __be32)from, (__force __be32)to); +} + +extern void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, + __be32 from, __be32 to, int pseudohdr); + +static inline void nf_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb, + __be16 from, __be16 to, int pseudohdr) +{ + nf_proto_csum_replace4(sum, skb, (__force __be32)from, + (__force __be32)to, pseudohdr); +} struct nf_afinfo { unsigned short family; diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h index 1d853aa873eb..e371e0fc1672 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h @@ -102,11 +102,11 @@ static inline __be32 *gre_key(struct gre_hdr *greh) } /* get pointer ot gre csum, if present */ -static inline u_int16_t *gre_csum(struct gre_hdr *greh) +static inline __sum16 *gre_csum(struct gre_hdr *greh) { if (!greh->csum) return NULL; - return (u_int16_t *) (greh+sizeof(*greh)); + return (__sum16 *) (greh+sizeof(*greh)); } #endif /* __KERNEL__ */ diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 4b6260a97408..9d1a5175dcd4 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto, iph = (void *)(*pskb)->data + iphdroff; if (maniptype == IP_NAT_MANIP_SRC) { - iph->check = nf_csum_update(~iph->saddr, target->src.ip, - iph->check); + nf_csum_replace4(&iph->check, iph->saddr, target->src.ip); iph->saddr = target->src.ip; } else { - iph->check = nf_csum_update(~iph->daddr, target->dst.ip, - iph->check); + nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip); iph->daddr = target->dst.ip; } return 1; diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c index 3e7fd64c2162..ee80feb4b2a9 100644 --- a/net/ipv4/netfilter/ip_nat_helper.c +++ b/net/ipv4/netfilter/ip_nat_helper.c @@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, csum_partial((char *)tcph, datalen, 0)); } else - tcph->check = nf_proto_csum_update(*pskb, - htons(oldlen) ^ htons(0xFFFF), - htons(datalen), - tcph->check, 1); + nf_proto_csum_replace2(&tcph->check, *pskb, + htons(oldlen), htons(datalen), 1); if (rep_len != match_len) { set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); @@ -266,10 +264,8 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, if (!udph->check) udph->check = CSUM_MANGLED_0; } else - udph->check = nf_proto_csum_update(*pskb, - htons(oldlen) ^ htons(0xFFFF), - htons(datalen), - udph->check, 1); + nf_proto_csum_replace2(&udph->check, *pskb, + htons(oldlen), htons(datalen), 1); return 1; } EXPORT_SYMBOL(ip_nat_mangle_udp_packet); @@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb, ntohl(sack->start_seq), new_start_seq, ntohl(sack->end_seq), new_end_seq); - tcph->check = nf_proto_csum_update(skb, - ~sack->start_seq, - new_start_seq, - tcph->check, 0); - tcph->check = nf_proto_csum_update(skb, - ~sack->end_seq, - new_end_seq, - tcph->check, 0); + nf_proto_csum_replace4(&tcph->check, skb, + sack->start_seq, new_start_seq, 0); + nf_proto_csum_replace4(&tcph->check, skb, + sack->end_seq, new_end_seq, 0); sack->start_seq = new_start_seq; sack->end_seq = new_end_seq; sackoff += sizeof(*sack); @@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb, else newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); - tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq, - tcph->check, 0); - tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack, - tcph->check, 0); + 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), diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index bf91f9312b3c..95810202d849 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb, } if (greh->csum) { /* FIXME: Never tested this code... */ - *(gre_csum(greh)) = - nf_proto_csum_update(*pskb, - ~*(gre_key(greh)), - tuple->dst.u.gre.key, - *(gre_csum(greh)), 0); + nf_proto_csum_replace4(gre_csum(greh), *pskb, + *(gre_key(greh)), + tuple->dst.u.gre.key, 0); } *(gre_key(greh)) = tuple->dst.u.gre.key; break; diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c index 3f6efc13ac74..75266fe3e0fa 100644 --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c @@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb, return 0; hdr = (struct icmphdr *)((*pskb)->data + hdroff); - hdr->checksum = nf_proto_csum_update(*pskb, - hdr->un.echo.id ^ htons(0xFFFF), - tuple->src.u.icmp.id, - hdr->checksum, 0); + nf_proto_csum_replace2(&hdr->checksum, *pskb, + hdr->un.echo.id, tuple->src.u.icmp.id, 0); hdr->un.echo.id = tuple->src.u.icmp.id; return 1; } diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index 12deb13b93b1..b586d18b3fb3 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb, if (hdrsize < sizeof(*hdr)) return 1; - hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1); - hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport, - hdr->check, 0); + nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); + nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0); return 1; } diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 82f8a6ab07ec..5ced0877b32f 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -115,11 +115,8 @@ udp_manip_pkt(struct sk_buff **pskb, } if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { - hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, - hdr->check, 1); - hdr->check = nf_proto_csum_update(*pskb, - *portptr ^ htons(0xFFFF), newport, - hdr->check, 0); + nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); + nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0); if (!hdr->check) hdr->check = CSUM_MANGLED_0; } diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index 1aa4517fbcdb..b55d670a24df 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c @@ -28,17 +28,16 @@ static inline int set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) { struct iphdr *iph = (*pskb)->nh.iph; - u_int16_t oldtos; if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { + __u8 oldtos; if (!skb_make_writable(pskb, sizeof(struct iphdr))) return 0; iph = (*pskb)->nh.iph; oldtos = iph->tos; iph->tos &= ~IPT_ECN_IP_MASK; iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); - iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), - htons(iph->tos), iph->check); + nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); } return 1; } @@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) if (einfo->operation & IPT_ECN_OP_SET_CWR) tcph->cwr = einfo->proto.tcp.cwr; - tcph->check = nf_proto_csum_update((*pskb), - oldval ^ htons(0xFFFF), - ((__be16 *)tcph)[6], - tcph->check, 0); + nf_proto_csum_replace2(&tcph->check, *pskb, + oldval, ((__be16 *)tcph)[6], 0); return 1; } diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 108b6b76311f..93eb5c3c1884 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c @@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb, opt[i+2] = (newmss & 0xff00) >> 8; opt[i+3] = (newmss & 0x00ff); - tcph->check = nf_proto_csum_update(*pskb, - htons(oldmss)^htons(0xFFFF), - htons(newmss), - tcph->check, 0); + nf_proto_csum_replace2(&tcph->check, *pskb, + htons(oldmss), htons(newmss), 0); return IPT_CONTINUE; } } @@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb, opt = (u_int8_t *)tcph + sizeof(struct tcphdr); memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); - tcph->check = nf_proto_csum_update(*pskb, - htons(tcplen) ^ htons(0xFFFF), - htons(tcplen + TCPOLEN_MSS), - tcph->check, 1); + nf_proto_csum_replace2(&tcph->check, *pskb, + htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); opt[0] = TCPOPT_MSS; opt[1] = TCPOLEN_MSS; opt[2] = (newmss & 0xff00) >> 8; opt[3] = (newmss & 0x00ff); - tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt), - tcph->check, 0); + nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); oldval = ((__be16 *)tcph)[6]; tcph->doff += TCPOLEN_MSS/4; - tcph->check = nf_proto_csum_update(*pskb, - oldval ^ htons(0xFFFF), - ((__be16 *)tcph)[6], - tcph->check, 0); + nf_proto_csum_replace2(&tcph->check, *pskb, + oldval, ((__be16 *)tcph)[6], 0); newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); - iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF), - newtotlen, iph->check); + nf_csum_replace2(&iph->check, iph->tot_len, newtotlen); iph->tot_len = newtotlen; return IPT_CONTINUE; } diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 83b80b3a5d2f..18e74ac4d425 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c @@ -30,16 +30,15 @@ target(struct sk_buff **pskb, { const struct ipt_tos_target_info *tosinfo = targinfo; struct iphdr *iph = (*pskb)->nh.iph; - u_int16_t oldtos; if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { + __u8 oldtos; if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; iph = (*pskb)->nh.iph; oldtos = iph->tos; iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; - iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), - htons(iph->tos), iph->check); + nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); } return IPT_CONTINUE; } diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index ac9517d62af0..fffe5ca82e91 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c @@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb, } if (new_ttl != iph->ttl) { - iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF), - htons(new_ttl << 8), - iph->check); + nf_csum_replace2(&iph->check, htons(iph->ttl << 8), + htons(new_ttl << 8)); iph->ttl = new_ttl; } diff --git a/net/netfilter/core.c b/net/netfilter/core.c index d80b935b3a92..17f9e1cbc73b 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -222,28 +222,21 @@ copy_skb: } EXPORT_SYMBOL(skb_make_writable); -u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum) -{ - u_int32_t diff[] = { oldval, newval }; - - return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum)); -} -EXPORT_SYMBOL(nf_csum_update); - -u_int16_t nf_proto_csum_update(struct sk_buff *skb, - u_int32_t oldval, u_int32_t newval, - u_int16_t csum, int pseudohdr) +void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, + __be32 from, __be32 to, int pseudohdr) { + __be32 diff[] = { ~from, to }; if (skb->ip_summed != CHECKSUM_PARTIAL) { - csum = nf_csum_update(oldval, newval, csum); + *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), + ~csum_unfold(*sum))); if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) - skb->csum = nf_csum_update(oldval, newval, skb->csum); + skb->csum = ~csum_partial((char *)diff, sizeof(diff), + ~skb->csum); } else if (pseudohdr) - csum = ~nf_csum_update(oldval, newval, ~csum); - - return csum; + *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff), + csum_unfold(*sum))); } -EXPORT_SYMBOL(nf_proto_csum_update); +EXPORT_SYMBOL(nf_proto_csum_replace4); /* This does not belong here, but locally generated errors need it if connection tracking in use: without this, connection may not be in hash table, and hence -- cgit v1.2.3-70-g09d2 From 7d533f941856d7d192bfec28581e130dda9c6688 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:51:36 -0800 Subject: [NET]: More dccp endianness annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/dccp/ipv6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index f28e406a4a1f..6eda430ae929 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -76,8 +76,8 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value, dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); } -static inline __u32 secure_dccpv6_sequence_number(__u32 *saddr, __u32 *daddr, - __u16 sport, __u16 dport ) +static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport ) { return secure_tcpv6_sequence_number(saddr, daddr, sport, dport); } -- cgit v1.2.3-70-g09d2 From 7d9e9b3df491d5e1c3ed76c5cff7ace6094124c1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Nov 2006 22:09:20 -0800 Subject: [IPV6]: udp.c build fix Signed-off-by: David S. Miller --- net/ipv6/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index bb45b9b7cbd9..efa8950ddd30 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -385,7 +385,7 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) if (skb->ip_summed != CHECKSUM_UNNECESSARY) skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - ulen, IPPROTO_UDP, + skb->len, IPPROTO_UDP, 0)); return (UDP_SKB_CB(skb)->partial_cov = 0); -- cgit v1.2.3-70-g09d2 From 078250d68d883495f31d0e6ce8321292f2dc1cfa Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 15 Nov 2006 00:44:49 -0800 Subject: [NET/IPv4]: Make udp_push_pending_frames static udp_push_pending_frames is only referenced within net/ipv4/udp.c and hence can remain static. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/ipv4/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index dc19ba1e73b5..7eb76fbf1b4b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -448,7 +448,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, /* * Push out all pending data as one UDP datagram. Socket is locked. */ -int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) +static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) { struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; -- cgit v1.2.3-70-g09d2 From 3c6952624a8f600f9a0fbc1f5db5560a7ef9b13e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 15 Nov 2006 21:27:47 -0200 Subject: [DCCP]: Introduce DCCP_{BUG{_ON},CRIT} macros, use enum:8 for the ccid3 states This patch tackles the following problem: * the ccid3_hc_{t,r}x_sock define ccid3hc{t,r}x_state as `u8', but in reality there can only be a few, pre-defined enum names * this necessitates addiditional checking for unexpected values which would otherwise be caught by the compiler Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 45 ++++++++++++--------------------------------- net/dccp/ccids/ccid3.h | 19 +++++++++++++++++-- net/dccp/dccp.h | 8 ++++++++ 3 files changed, 37 insertions(+), 35 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index cec23ad286de..2fa0c6d1fbee 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -75,14 +75,6 @@ static struct dccp_tx_hist *ccid3_tx_hist; static struct dccp_rx_hist *ccid3_rx_hist; static struct dccp_li_hist *ccid3_li_hist; -/* TFRC sender states */ -enum ccid3_hc_tx_states { - TFRC_SSTATE_NO_SENT = 1, - TFRC_SSTATE_NO_FBACK, - TFRC_SSTATE_FBACK, - TFRC_SSTATE_TERM, -}; - #ifdef CCID3_DEBUG static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) { @@ -251,9 +243,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) hctx->ccid3hctx_x)); break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); goto out; } @@ -329,9 +320,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, rc = delay > 0 ? delay : 0; break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); rc = -EINVAL; break; } @@ -423,9 +413,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) } break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); break; } } @@ -568,9 +557,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hctx->ccid3hctx_idle = 1; break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); break; } } @@ -688,13 +676,6 @@ static void ccid3_hc_tx_exit(struct sock *sk) * RX Half Connection methods */ -/* TFRC receiver states */ -enum ccid3_hc_rx_states { - TFRC_RSTATE_NO_DATA = 1, - TFRC_RSTATE_DATA, - TFRC_RSTATE_TERM = 127, -}; - #ifdef CCID3_DEBUG static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) { @@ -744,9 +725,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) } break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hcrx->ccid3hcrx_state); return; } @@ -1088,9 +1068,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } return; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hcrx->ccid3hcrx_state); return; } diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 0a2cb7536d26..c122e757eb7f 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -73,6 +73,14 @@ struct ccid3_options_received { u32 ccid3or_receive_rate; }; +/* TFRC sender states */ +enum ccid3_hc_tx_states { + TFRC_SSTATE_NO_SENT = 1, + TFRC_SSTATE_NO_FBACK, + TFRC_SSTATE_FBACK, + TFRC_SSTATE_TERM, +}; + /** struct ccid3_hc_tx_sock - CCID3 sender half connection sock * * @ccid3hctx_state - Sender state @@ -103,7 +111,7 @@ struct ccid3_hc_tx_sock { #define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto #define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi u16 ccid3hctx_s; - u8 ccid3hctx_state; + enum ccid3_hc_tx_states ccid3hctx_state:8; u8 ccid3hctx_last_win_count; u8 ccid3hctx_idle; struct timeval ccid3hctx_t_last_win_count; @@ -115,6 +123,13 @@ struct ccid3_hc_tx_sock { struct ccid3_options_received ccid3hctx_options_received; }; +/* TFRC receiver states */ +enum ccid3_hc_rx_states { + TFRC_RSTATE_NO_DATA = 1, + TFRC_RSTATE_DATA, + TFRC_RSTATE_TERM = 127, +}; + struct ccid3_hc_rx_sock { struct tfrc_rx_info ccid3hcrx_tfrc; #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv @@ -122,8 +137,8 @@ struct ccid3_hc_rx_sock { #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p u64 ccid3hcrx_seqno_nonloss:48, ccid3hcrx_ccval_nonloss:4, - ccid3hcrx_state:8, ccid3hcrx_ccval_last_counter:4; + enum ccid3_hc_rx_states ccid3hcrx_state:8; u32 ccid3hcrx_bytes_recv; struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_ack; diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 363fa520056e..ecb4e7bd1a84 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -18,6 +18,14 @@ #include #include "ackvec.h" +#define DCCP_CRIT(fmt, a...) LIMIT_NETDEBUG(KERN_CRIT fmt " at %s:%d/%s()\n", \ + ##a, __FILE__, __LINE__, __FUNCTION__) +#define DCCP_BUG(fmt, a...) do { DCCP_CRIT(fmt, ##a); dump_stack(); } while (0) +#define DCCP_BUG_ON(cond) do { if (unlikely((cond) == 0)) \ + DCCP_BUG("BUG: condition \"%s\" fails",\ + __stringify((cond))); \ + } while (0) + #ifdef CONFIG_IP_DCCP_DEBUG extern int dccp_debug; -- cgit v1.2.3-70-g09d2 From e523a1550e877f8a8ff87a50269b7ee7bfb43464 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 16 Nov 2006 12:23:58 -0200 Subject: [DCCP]: One NET_INC_STATS() could be NET_INC_STATS_BH in dccp_v4_err() Spotted by Eric Dumazet in tcp_v4_rcv(). Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 6bca71929de5..a20eb71d45db 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -244,7 +244,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) seq = dccp_hdr_seq(skb); if (sk->sk_state != DCCP_LISTEN && !between48(seq, dp->dccps_swl, dp->dccps_swh)) { - NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS); + NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); goto out; } -- cgit v1.2.3-70-g09d2 From 58a5a7b9555ea231b557ebef5cabeaf8e951df0b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 16 Nov 2006 14:06:06 -0200 Subject: [NET]: Conditionally use bh_lock_sock_nested in sk_receive_skb Spotted by Ian McDonald, tentatively fixed by Gerrit Renker: http://www.mail-archive.com/dccp%40vger.kernel.org/msg00599.html Rewritten not to unroll sk_receive_skb, in the common case, i.e. no lock debugging, its optimized away. Signed-off-by: Arnaldo Carvalho de Melo --- drivers/net/pppoe.c | 2 +- include/net/sock.h | 3 ++- net/core/sock.c | 7 +++++-- net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 2 +- net/decnet/dn_nsp_in.c | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 0adee733b761..315d5c3fc66a 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -393,7 +393,7 @@ static int pppoe_rcv(struct sk_buff *skb, po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); if (po != NULL) - return sk_receive_skb(sk_pppox(po), skb); + return sk_receive_skb(sk_pppox(po), skb, 0); drop: kfree_skb(skb); out: diff --git a/include/net/sock.h b/include/net/sock.h index dc4b92b8abea..26fc0b16bc0c 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -954,7 +954,8 @@ static inline void sock_put(struct sock *sk) sk_free(sk); } -extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb); +extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb, + const int nested); /* Detach socket from process context. * Announce socket dead, detach it from wait queue and inode. diff --git a/net/core/sock.c b/net/core/sock.c index 32ff1c551d69..ab8fafadb4ba 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -270,7 +270,7 @@ out: } EXPORT_SYMBOL(sock_queue_rcv_skb); -int sk_receive_skb(struct sock *sk, struct sk_buff *skb) +int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) { int rc = NET_RX_SUCCESS; @@ -279,7 +279,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb) skb->dev = NULL; - bh_lock_sock(sk); + if (nested) + bh_lock_sock_nested(sk); + else + bh_lock_sock(sk); if (!sock_owned_by_user(sk)) { /* * trylock + unlock semantics: diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index a20eb71d45db..7114befe7d50 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -899,7 +899,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; nf_reset(skb); - return sk_receive_skb(sk, skb); + return sk_receive_skb(sk, skb, 1); no_dccp_socket: if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6eda430ae929..03bb8298250a 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -888,7 +888,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb) if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - return sk_receive_skb(sk, skb) ? -1 : 0; + return sk_receive_skb(sk, skb, 1) ? -1 : 0; no_dccp_socket: if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 7683d4f754d2..39a6cf7fb566 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -804,7 +804,7 @@ got_it: goto free_out; } - return sk_receive_skb(sk, skb); + return sk_receive_skb(sk, skb, 0); } return dn_nsp_no_socket(skb, reason); -- cgit v1.2.3-70-g09d2 From 32aac18dfa0963fde40cc074ba97ebbae8b755f2 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Thu, 16 Nov 2006 14:28:40 -0200 Subject: [DCCP] CCID2: Code optimizations These are code optimizations which are relevant when dealing with large windows. They are not coded the way I would like to, but they do the job for the short-term. This patch should be more neat. Commiter note: Changed the seqno comparisions to use {after,before}48 to handle wrapping. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.c | 22 ++++++++++++++++++++-- net/dccp/ccids/ccid2.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 162032baeac0..6533cb2f27bb 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -619,7 +619,17 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) } ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; - seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + if (after48(ackno, hctx->ccid2hctx_high_ack)) + hctx->ccid2hctx_high_ack = ackno; + + seqp = hctx->ccid2hctx_seqt; + while (before48(seqp->ccid2s_seq, ackno)) { + seqp = seqp->ccid2s_next; + if (seqp == hctx->ccid2hctx_seqh) { + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + break; + } + } /* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for * this single ack. I round up. @@ -697,7 +707,14 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* The state about what is acked should be correct now * Check for NUMDUPACK */ - seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + seqp = hctx->ccid2hctx_seqt; + while (before48(seqp->ccid2s_seq, hctx->ccid2hctx_high_ack)) { + seqp = seqp->ccid2s_next; + if (seqp == hctx->ccid2hctx_seqh) { + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + break; + } + } done = 0; while (1) { if (seqp->ccid2s_acked) { @@ -771,6 +788,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) hctx->ccid2hctx_lastrtt = 0; hctx->ccid2hctx_rpdupack = -1; hctx->ccid2hctx_last_cong = jiffies; + hctx->ccid2hctx_high_ack = 0; hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 5b2ef4acb300..a97a89927308 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -72,6 +72,7 @@ struct ccid2_hc_tx_sock { int ccid2hctx_rpdupack; int ccid2hctx_sendwait; unsigned long ccid2hctx_last_cong; + u64 ccid2hctx_high_ack; }; struct ccid2_hc_rx_sock { -- cgit v1.2.3-70-g09d2 From 7174259e6ced15bebee202983511d8fc950e929f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 10:57:30 -0200 Subject: [TCP_IPV4]: CodingStyle cleanups, no code change Mostly related to CONFIG_TCP_MD5SIG recent merge. Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/tcp_ipv4.c | 143 +++++++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 68 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dadf80272413..010dff442a11 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -93,16 +93,18 @@ static struct socket *tcp_socket; void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); #ifdef CONFIG_TCP_MD5SIG -static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr); +static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, + __be32 addr); static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, - __be32 saddr, __be32 daddr, struct tcphdr *th, - int protocol, int tcplen); + __be32 saddr, __be32 daddr, + struct tcphdr *th, int protocol, + int tcplen); #endif struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { - .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), - .lhash_users = ATOMIC_INIT(0), - .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), + .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), + .lhash_users = ATOMIC_INIT(0), + .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), }; static int tcp_v4_get_port(struct sock *sk, unsigned short snum) @@ -215,13 +217,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (tcp_death_row.sysctl_tw_recycle && !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { struct inet_peer *peer = rt_get_peer(rt); - - /* VJ's idea. We save last timestamp seen from - * the destination in peer table, when entering state TIME-WAIT - * and initialize rx_opt.ts_recent from it, when trying new connection. + /* + * VJ's idea. We save last timestamp seen from + * the destination in peer table, when entering state + * TIME-WAIT * and initialize rx_opt.ts_recent from it, + * when trying new connection. */ - - if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) { + if (peer != NULL && + peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) { tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; tp->rx_opt.ts_recent = peer->tcp_ts; } @@ -246,7 +249,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err) goto failure; - err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); + err = ip_route_newports(&rt, IPPROTO_TCP, + inet->sport, inet->dport, sk); if (err) goto failure; @@ -270,7 +274,10 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return 0; failure: - /* This unhashes the socket and releases the local port, if necessary. */ + /* + * This unhashes the socket and releases the local port, + * if necessary. + */ tcp_set_state(sk, TCP_CLOSE); ip_rt_put(rt); sk->sk_route_caps = 0; @@ -495,7 +502,8 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) struct tcphdr *th = skb->h.th; if (skb->ip_summed == CHECKSUM_PARTIAL) { - th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); + th->check = ~tcp_v4_check(th, len, + inet->saddr, inet->daddr, 0); skb->csum = offsetof(struct tcphdr, check); } else { th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, @@ -572,7 +580,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) skb->len - (th->doff << 2)); } - memset(&arg, 0, sizeof arg); + memset(&arg, 0, sizeof(arg)); arg.iov[0].iov_base = (unsigned char *)&rep; arg.iov[0].iov_len = sizeof(rep.th); @@ -595,9 +603,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.iov[0].iov_len); } #endif - arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, - skb->nh.iph->saddr, /*XXX*/ + skb->nh.iph->saddr, /* XXX */ sizeof(struct tcphdr), IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr, check) / 2; @@ -631,7 +638,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, #endif memset(&rep.th, 0, sizeof(struct tcphdr)); - memset(&arg, 0, sizeof arg); + memset(&arg, 0, sizeof(arg)); arg.iov[0].iov_base = (unsigned char *)&rep; arg.iov[0].iov_len = sizeof(rep.th); @@ -668,9 +675,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, tw_key.key = twsk->tw_md5_key; tw_key.keylen = twsk->tw_md5_keylen; key = &tw_key; - } else { + } else key = NULL; - } if (key) { int offset = (ts) ? 3 : 0; @@ -690,9 +696,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, arg.iov[0].iov_len); } #endif - arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, - skb->nh.iph->saddr, /*XXX*/ + skb->nh.iph->saddr, /* XXX */ arg.iov[0].iov_len, IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr, check) / 2; @@ -707,12 +712,14 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) struct tcp_timewait_sock *tcptw = tcp_twsk(sk); tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, - tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); + tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, + tcptw->tw_ts_recent); inet_twsk_put(tw); } -static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) +static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, + struct request_sock *req) { tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, @@ -809,7 +816,8 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, */ /* Find the Key structure for an address. */ -static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) +static struct tcp_md5sig_key * + tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) { struct tcp_sock *tp = tcp_sk(sk); int i; @@ -818,7 +826,8 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) return NULL; for (i = 0; i < tp->md5sig_info->entries4; i++) { if (tp->md5sig_info->keys4[i].addr == addr) - return (struct tcp_md5sig_key *)&tp->md5sig_info->keys4[i]; + return (struct tcp_md5sig_key *) + &tp->md5sig_info->keys4[i]; } return NULL; } @@ -915,13 +924,12 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) if (tp->md5sig_info->entries4 == 0) { kfree(tp->md5sig_info->keys4); tp->md5sig_info->keys4 = NULL; - } else { + } else if (tp->md5sig_info->entries4 != i) { /* Need to do some manipulation */ - if (tp->md5sig_info->entries4 != i) - memcpy(&tp->md5sig_info->keys4[i], - &tp->md5sig_info->keys4[i+1], - (tp->md5sig_info->entries4 - i) - * sizeof (struct tcp4_md5sig_key)); + memcpy(&tp->md5sig_info->keys4[i], + &tp->md5sig_info->keys4[i+1], + (tp->md5sig_info->entries4 - i) * + sizeof(struct tcp4_md5sig_key)); } tcp_free_md5sig_pool(); return 0; @@ -932,7 +940,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) EXPORT_SYMBOL(tcp_v4_md5_do_del); -static void tcp_v4_clear_md5_list (struct sock *sk) +static void tcp_v4_clear_md5_list(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); @@ -954,8 +962,8 @@ static void tcp_v4_clear_md5_list (struct sock *sk) } } -static int tcp_v4_parse_md5_keys (struct sock *sk, char __user *optval, - int optlen) +static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, + int optlen) { struct tcp_md5sig cmd; struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; @@ -964,7 +972,7 @@ static int tcp_v4_parse_md5_keys (struct sock *sk, char __user *optval, if (optlen < sizeof(cmd)) return -EINVAL; - if (copy_from_user (&cmd, optval, sizeof(cmd))) + if (copy_from_user(&cmd, optval, sizeof(cmd))) return -EFAULT; if (sin->sin_family != AF_INET) @@ -981,9 +989,8 @@ static int tcp_v4_parse_md5_keys (struct sock *sk, char __user *optval, if (!tcp_sk(sk)->md5sig_info) { struct tcp_sock *tp = tcp_sk(sk); - struct tcp_md5sig_info *p; + struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL); - p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); if (!p) return -EINVAL; @@ -1044,8 +1051,8 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, #ifdef CONFIG_TCP_MD5SIG_DEBUG printk("Calcuating hash for: "); - for (i = 0; i < sizeof (*bp); i++) - printk ("%02x ", (unsigned int)((unsigned char *)bp)[i]); + for (i = 0; i < sizeof(*bp); i++) + printk("%02x ", (unsigned int)((unsigned char *)bp)[i]); printk(" "); #endif @@ -1057,8 +1064,8 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); nbytes += sizeof(struct tcphdr); #ifdef CONFIG_TCP_MD5SIG_DEBUG - for (i = 0; i < sizeof (struct tcphdr); i++) - printk (" %02x", (unsigned int)((unsigned char *)th)[i]); + for (i = 0; i < sizeof(struct tcphdr); i++) + printk(" %02x", (unsigned int)((unsigned char *)th)[i]); #endif /* 3. the TCP segment data (if any) */ data_len = tcplen - (th->doff << 2); @@ -1075,9 +1082,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, nbytes += key->keylen; #ifdef CONFIG_TCP_MD5SIG_DEBUG - printk (" and password: "); + printk(" and password: "); for (i = 0; i < key->keylen; i++) - printk ("%02x ", (unsigned int)key->key[i]); + printk("%02x ", (unsigned int)key->key[i]); #endif /* Now store the Hash into the packet */ @@ -1099,7 +1106,7 @@ out: #ifdef CONFIG_TCP_MD5SIG_DEBUG printk(" result:"); for (i = 0; i < 16; i++) - printk (" %02x", (unsigned int)(((u8*)md5_hash)[i])); + printk(" %02x", (unsigned int)(((u8*)md5_hash)[i])); printk("\n"); #endif return 0; @@ -1135,7 +1142,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, EXPORT_SYMBOL(tcp_v4_calc_md5_hash); -static int tcp_v4_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) +static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) { /* * This gets called for each TCP segment that arrives @@ -1149,7 +1156,7 @@ static int tcp_v4_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) struct tcp_md5sig_key *hash_expected; struct iphdr *iph = skb->nh.iph; struct tcphdr *th = skb->h.th; - int length = (th->doff << 2) - sizeof (struct tcphdr); + int length = (th->doff << 2) - sizeof(struct tcphdr); int genhash; unsigned char *ptr; unsigned char newhash[16]; @@ -1200,22 +1207,18 @@ done_opts: return 0; if (hash_expected && !hash_location) { - if (net_ratelimit()) { - printk(KERN_INFO "MD5 Hash NOT expected but found " + LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", - NIPQUAD (iph->saddr), ntohs(th->source), - NIPQUAD (iph->daddr), ntohs(th->dest)); - } + NIPQUAD(iph->saddr), ntohs(th->source), + NIPQUAD(iph->daddr), ntohs(th->dest)); return 1; } if (!hash_expected && hash_location) { - if (net_ratelimit()) { - printk(KERN_INFO "MD5 Hash NOT expected but found " + LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", - NIPQUAD (iph->saddr), ntohs(th->source), - NIPQUAD (iph->daddr), ntohs(th->dest)); - } + NIPQUAD(iph->saddr), ntohs(th->source), + NIPQUAD(iph->daddr), ntohs(th->dest)); return 1; } @@ -1232,15 +1235,16 @@ done_opts: if (net_ratelimit()) { printk(KERN_INFO "MD5 Hash failed for " "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n", - NIPQUAD (iph->saddr), ntohs(th->source), - NIPQUAD (iph->daddr), ntohs(th->dest), + NIPQUAD(iph->saddr), ntohs(th->source), + NIPQUAD(iph->daddr), ntohs(th->dest), genhash ? " tcp_v4_calc_md5_hash failed" : ""); #ifdef CONFIG_TCP_MD5SIG_DEBUG do { int i; printk("Received: "); for (i = 0; i < 16; i++) - printk("%02x ", 0xff & (int)hash_location[i]); + printk("%02x ", + 0xff & (int)hash_location[i]); printk("\n"); printk("Calculated: "); for (i = 0; i < 16; i++) @@ -1582,7 +1586,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) * o We're expecting an MD5'd packet and this is no MD5 tcp option * o There is an MD5 option and we're not expecting one */ - if (tcp_v4_inbound_md5_hash (sk, skb)) + if (tcp_v4_inbound_md5_hash(sk, skb)) goto discard; #endif @@ -2155,7 +2159,7 @@ static void *established_get_idx(struct seq_file *seq, loff_t pos) while (rc && pos) { rc = established_get_next(seq, rc); --pos; - } + } return rc; } @@ -2284,7 +2288,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo) afinfo->seq_fops->read = seq_read; afinfo->seq_fops->llseek = seq_lseek; afinfo->seq_fops->release = seq_release_private; - + p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); if (p) p->data = afinfo; @@ -2298,7 +2302,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo) if (!afinfo) return; proc_net_remove(afinfo->name); - memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); + memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); } static void get_openreq4(struct sock *sk, struct request_sock *req, @@ -2356,7 +2360,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) "%08X %5d %8d %lu %d %p %u %u %u %u %d", i, src, srcp, dest, destp, sp->sk_state, tp->write_seq - tp->snd_una, - (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), + sp->sk_state == TCP_LISTEN ? sp->sk_ack_backlog : + (tp->rcv_nxt - tp->copied_seq), timer_active, jiffies_to_clock_t(timer_expires - jiffies), icsk->icsk_retransmits, @@ -2371,7 +2376,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); } -static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i) +static void get_timewait4_sock(struct inet_timewait_sock *tw, + char *tmpbuf, int i) { __be32 dest, src; __u16 destp, srcp; @@ -2484,7 +2490,8 @@ struct proto tcp_prot = { void __init tcp_v4_init(struct net_proto_family *ops) { - if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0) + if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, + IPPROTO_TCP) < 0) panic("Failed to create the TCP control socket.\n"); } -- cgit v1.2.3-70-g09d2 From f6685938f9181e95f814edfca287d4f04a925240 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 11:06:01 -0200 Subject: [TCP_IPV4]: Use kmemdup where appropriate Also use a variable to avoid the longish tp->md5sig_info-> use in tcp_v4_md5_do_add. Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/tcp_ipv4.o.before /tmp/tcp_ipv4.o.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv4/tcp_ipv4.c: tcp_v4_md5_do_add | -62 tcp_v4_syn_recv_sock | -32 tcp_v4_parse_md5_keys | -86 3 functions changed, 180 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/tcp_ipv4.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 010dff442a11..b7d5522092eb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -855,15 +855,18 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, struct tcp_sock *tp = tcp_sk(sk); struct tcp4_md5sig_key *keys; - key = (struct tcp4_md5sig_key *) tcp_v4_md5_do_lookup(sk, addr); + key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); if (key) { /* Pre-existing entry - just update that one. */ - kfree (key->key); + kfree(key->key); key->key = newkey; key->keylen = newkeylen; } else { + struct tcp_md5sig_info *md5sig; + if (!tp->md5sig_info) { - tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); + tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), + GFP_ATOMIC); if (!tp->md5sig_info) { kfree(newkey); return -ENOMEM; @@ -873,30 +876,31 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, kfree(newkey); return -ENOMEM; } - if (tp->md5sig_info->alloced4 == tp->md5sig_info->entries4) { - keys = kmalloc((sizeof(struct tcp4_md5sig_key) * - (tp->md5sig_info->entries4 + 1)), GFP_ATOMIC); + md5sig = tp->md5sig_info; + + if (md5sig->alloced4 == md5sig->entries4) { + keys = kmalloc((sizeof(*keys) * + (md5sig->entries4 + 1)), GFP_ATOMIC); if (!keys) { kfree(newkey); tcp_free_md5sig_pool(); return -ENOMEM; } - if (tp->md5sig_info->entries4) - memcpy(keys, tp->md5sig_info->keys4, - (sizeof (struct tcp4_md5sig_key) * - tp->md5sig_info->entries4)); + if (md5sig->entries4) + memcpy(keys, md5sig->keys4, + sizeof(*keys) * md5sig->entries4); /* Free old key list, and reference new one */ - if (tp->md5sig_info->keys4) - kfree(tp->md5sig_info->keys4); - tp->md5sig_info->keys4 = keys; - tp->md5sig_info->alloced4++; + if (md5sig->keys4) + kfree(md5sig->keys4); + md5sig->keys4 = keys; + md5sig->alloced4++; } - tp->md5sig_info->entries4++; - tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].addr = addr; - tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].key = newkey; - tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].keylen = newkeylen; + md5sig->entries4++; + md5sig->keys4[md5sig->entries4 - 1].addr = addr; + md5sig->keys4[md5sig->entries4 - 1].key = newkey; + md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; } return 0; } @@ -998,10 +1002,9 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, } - newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); if (!newkey) return -ENOMEM; - memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, newkey, cmd.tcpm_keylen); } @@ -1494,12 +1497,10 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * memory, then we end up not copying the key * across. Shucks. */ - char *newkey = kmalloc(key->keylen, GFP_ATOMIC); - if (newkey) { - memcpy(newkey, key->key, key->keylen); + char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); + if (newkey != NULL) tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, newkey, key->keylen); - } } #endif -- cgit v1.2.3-70-g09d2 From fac5d7315126f4b6745a8565c3a875617e02f8b8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 11:14:16 -0200 Subject: [NETLABEL]: Use kmemdup in cipso_ipv4.c Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/cipso_ipv4.o.before /tmp/cipso_ipv4.o.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv4/cipso_ipv4.c: cipso_v4_cache_add | -46 1 function changed, 46 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/cipso_ipv4.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c3a61ebbadef..095038ad72a4 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -377,12 +377,11 @@ int cipso_v4_cache_add(const struct sk_buff *skb, entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return -ENOMEM; - entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC); + entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC); if (entry->key == NULL) { ret_val = -ENOMEM; goto cache_add_failure; } - memcpy(entry->key, cipso_ptr, cipso_ptr_len); entry->key_len = cipso_ptr_len; entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); atomic_inc(&secattr->cache->refcount); -- cgit v1.2.3-70-g09d2 From 42e5ea466c1897c4ac2e3b4fe0b33a28e9e3d5de Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 11:18:20 -0200 Subject: [IPV4]: Use kmemdup in net/ipv4/devinet.c Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/devinet.o.before /tmp/devinet.o.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv4/devinet.c: devinet_sysctl_register | -38 1 function changed, 38 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/devinet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index a1b356c8aa59..2fd899160f85 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1564,12 +1564,12 @@ static void devinet_sysctl_register(struct in_device *in_dev, { int i; struct net_device *dev = in_dev ? in_dev->dev : NULL; - struct devinet_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL); + struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t), + GFP_KERNEL); char *dev_name = NULL; if (!t) return; - memcpy(t, &devinet_sysctl, sizeof(*t)); for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) { t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf; t->devinet_vars[i].de = NULL; -- cgit v1.2.3-70-g09d2 From c67862403e28dd67f38e896736f063d8dd522688 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 11:25:49 -0200 Subject: [TCP] minisocks: Use kmemdup and LIMIT_NETDEBUG Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/tcp_minisocks.o.before /tmp/tcp_minisocks.o.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv4/tcp_minisocks.c: tcp_check_req | -44 1 function changed, 44 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/tcp_minisocks.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 383cb38461c5..6dddf59c1fb9 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -351,8 +351,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) * socket up. We've got bigger problems than * non-graceful socket closings. */ - if (net_ratelimit()) - printk(KERN_INFO "TCP: time wait bucket table overflow\n"); + LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n"); } tcp_update_metrics(sk); @@ -667,11 +666,11 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, * newsk structure. If we fail to get memory then we * end up not copying the key across. Shucks. */ - char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + char *newkey = kmemdup(key->key, key->keylen, + GFP_ATOMIC); if (newkey) { if (!tcp_alloc_md5sig_pool()) BUG(); - memcpy(newkey, key->key, key->keylen); tp->af_specific->md5_add(child, child, newkey, key->keylen); -- cgit v1.2.3-70-g09d2 From af879cc704372ef762584e916129d19ffb39e844 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:14:37 -0200 Subject: [IPV6]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/ipv6.ko.before /tmp/ipv6.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/ip6_output.c: ip6_output | -52 ip6_append_data | +2 2 functions changed, 2 bytes added, 52 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/addrconf.c: addrconf_sysctl_register | -27 1 function changed, 27 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/tcp_ipv6.c: tcp_v6_syn_recv_sock | -32 tcp_v6_parse_md5_keys | -24 2 functions changed, 56 bytes removed /tmp/ipv6.ko.after: 5 functions changed, 2 bytes added, 135 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv6/addrconf.c | 3 +-- net/ipv6/ah6.c | 3 +-- net/ipv6/ip6_output.c | 3 +-- net/ipv6/tcp_ipv6.c | 9 +++------ 4 files changed, 6 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b41c5d8b2789..a5e8d207a51b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3969,10 +3969,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf struct addrconf_sysctl_table *t; char *dev_name = NULL; - t = kmalloc(sizeof(*t), GFP_KERNEL); + t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL); if (t == NULL) return; - memcpy(t, &addrconf_sysctl, sizeof(*t)); for (i=0; t->addrconf_vars[i].data; i++) { t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; t->addrconf_vars[i].de = NULL; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2d9e495cf691..12c5a4dec09e 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -354,10 +354,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) if (!pskb_may_pull(skb, ah_hlen)) goto out; - tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); if (!tmp_hdr) goto out; - memcpy(tmp_hdr, skb->nh.raw, hdr_len); if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) goto free_out; skb->nh.ipv6h->priority = 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 85f889270492..e05ecbb1412d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -624,14 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_shinfo(skb)->frag_list = NULL; /* BUILD HEADER */ - tmp_hdr = kmalloc(hlen, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); if (!tmp_hdr) { IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } *prevhdr = NEXTHDR_FRAGMENT; - memcpy(tmp_hdr, skb->nh.raw, hlen); __skb_pull(skb, hlen); fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); skb->nh.raw = __skb_push(skb, hlen); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 147ce499f509..d2170da77e5b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -720,10 +720,9 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, tp->md5sig_info = p; } - newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); if (!newkey) return -ENOMEM; - memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], newkey, cmd.tcpm_keylen); @@ -1503,12 +1502,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * memory, then we end up not copying the key * across. Shucks. */ - char *newkey = kmalloc(key->keylen, GFP_ATOMIC); - if (newkey) { - memcpy(newkey, key->key, key->keylen); + char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); + if (newkey != NULL) tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, newkey, key->keylen); - } } #endif -- cgit v1.2.3-70-g09d2 From eed73417d501c2c7bdef1bc8a1f7a1548a635b09 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:21:43 -0200 Subject: [DCCP]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/dccp.ko.before /tmp/dccp.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/dccp/feat.c: __dccp_feat_init | -16 dccp_feat_change_recv | -55 dccp_feat_clone | -56 3 functions changed, 127 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/feat.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 12cde2f2f13b..e808c418c992 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -286,12 +286,11 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) if (opt == NULL) return -ENOMEM; - copy = kmalloc(len, GFP_ATOMIC); + copy = kmemdup(val, len, GFP_ATOMIC); if (copy == NULL) { kfree(opt); return -ENOMEM; } - memcpy(copy, val, len); opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */ opt->dccpop_feat = feature; @@ -521,20 +520,18 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) { struct dccp_opt_pend *newopt; /* copy the value of the option */ - u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC); + u8 *val = kmemdup(opt->dccpop_val, opt->dccpop_len, GFP_ATOMIC); if (val == NULL) goto out_clean; - memcpy(val, opt->dccpop_val, opt->dccpop_len); - newopt = kmalloc(sizeof(*newopt), GFP_ATOMIC); + newopt = kmemdup(opt, sizeof(*newopt), GFP_ATOMIC); if (newopt == NULL) { kfree(val); goto out_clean; } /* insert the option */ - memcpy(newopt, opt, sizeof(*newopt)); newopt->dccpop_val = val; list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending); @@ -565,10 +562,9 @@ static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat, u8 *val, u8 len) { int rc = -ENOMEM; - u8 *copy = kmalloc(len, GFP_KERNEL); + u8 *copy = kmemdup(val, len, GFP_KERNEL); if (copy != NULL) { - memcpy(copy, val, len); rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL); if (rc) kfree(copy); -- cgit v1.2.3-70-g09d2 From c66b721a502cbbc15be8bd7c79c305fa40f1e6ce Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:29:21 -0200 Subject: [DECNET]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/decnet.ko.before /tmp/decnet.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/decnet/dn_dev.c: dn_dev_sysctl_register | -51 1 function changed, 51 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/decnet/dn_dev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 01861feb608d..5b451e196fb9 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -255,12 +255,10 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms * struct dn_dev_sysctl_table *t; int i; - t = kmalloc(sizeof(*t), GFP_KERNEL); + t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL); if (t == NULL) return; - memcpy(t, &dn_dev_sysctl, sizeof(*t)); - for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) { long offset = (long)t->dn_dev_vars[i].data; t->dn_dev_vars[i].data = ((char *)parms) + offset; -- cgit v1.2.3-70-g09d2 From 0459d70add3f7ca5d433d4b2334cc6ec9ddab05b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:43:07 -0200 Subject: [AX25]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/ax25.ko.before /tmp/ax25.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ax25/ax25_out.c: ax25_send_frame | -8 1 function changed, 8 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ax25/ax25_route.c: ax25_rt_autobind | -15 1 function changed, 15 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ax25/af_ax25.c: ax25_make_new | -33 1 function changed, 33 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ax25/sysctl_net_ax25.c: ax25_register_sysctl | -21 1 function changed, 21 bytes removed /tmp/ax25.ko.after: 4 functions changed, 77 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ax25/af_ax25.c | 6 +++--- net/ax25/ax25_out.c | 4 ++-- net/ax25/ax25_route.c | 5 +++-- net/ax25/sysctl_net_ax25.c | 5 +++-- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 000695c48583..6cabf6d8a751 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -906,13 +906,13 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) ax25->source_addr = oax25->source_addr; if (oax25->digipeat != NULL) { - if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { + ax25->digipeat = kmemdup(oax25->digipeat, sizeof(ax25_digi), + GFP_ATOMIC); + if (ax25->digipeat == NULL) { sk_free(sk); ax25_cb_put(ax25); return NULL; } - - memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi)); } sk->sk_protinfo = ax25; diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index d7736e585336..f84047d1e8ce 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -70,11 +70,11 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2 ax25->dest_addr = *dest; if (digi != NULL) { - if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { + ax25->digipeat = kmemdup(digi, sizeof(*digi), GFP_ATOMIC); + if (ax25->digipeat == NULL) { ax25_cb_put(ax25); return NULL; } - memcpy(ax25->digipeat, digi, sizeof(ax25_digi)); } switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 51b7bdaf27eb..8580356ace5c 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -432,11 +432,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) } if (ax25_rt->digipeat != NULL) { - if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { + ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi), + GFP_ATOMIC); + if (ax25->digipeat == NULL) { err = -ENOMEM; goto put; } - memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi)); ax25_adjust_path(addr, ax25->digipeat); } diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 867d42537979..d23a27f25d2f 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -209,7 +209,9 @@ void ax25_register_sysctl(void) } for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) { - ctl_table *child = kmalloc(sizeof(ax25_param_table), GFP_ATOMIC); + struct ctl_table *child = kmemdup(ax25_param_table, + sizeof(ax25_param_table), + GFP_ATOMIC); if (!child) { while (n--) kfree(ax25_table[n].child); @@ -217,7 +219,6 @@ void ax25_register_sysctl(void) spin_unlock_bh(&ax25_dev_lock); return; } - memcpy(child, ax25_param_table, sizeof(ax25_param_table)); ax25_table[n].child = ax25_dev->systable = child; ax25_table[n].ctl_name = n + 1; ax25_table[n].procname = ax25_dev->dev->name; -- cgit v1.2.3-70-g09d2 From eafff86d3bd80403c808f67f5389813fdb5bd6c8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 13:05:04 -0200 Subject: [NETROM]: Use kmemdup Signed-off-by: Arnaldo Carvalho de Melo --- net/netrom/nr_route.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index c11737f472d6..0096105bcd47 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -155,14 +155,15 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 atomic_set(&nr_neigh->refcount, 1); if (ax25_digi != NULL && ax25_digi->ndigi > 0) { - if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) { + nr_neigh->digipeat = kmemdup(ax25_digi, + sizeof(*ax25_digi), + GFP_KERNEL); + if (nr_neigh->digipeat == NULL) { kfree(nr_neigh); if (nr_node) nr_node_put(nr_node); return -ENOMEM; } - memcpy(nr_neigh->digipeat, ax25_digi, - sizeof(*ax25_digi)); } spin_lock_bh(&nr_neigh_list_lock); @@ -432,11 +433,12 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net atomic_set(&nr_neigh->refcount, 1); if (ax25_digi != NULL && ax25_digi->ndigi > 0) { - if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) { + nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi), + GFP_KERNEL); + if (nr_neigh->digipeat == NULL) { kfree(nr_neigh); return -ENOMEM; } - memcpy(nr_neigh->digipeat, ax25_digi, sizeof(*ax25_digi)); } spin_lock_bh(&nr_neigh_list_lock); -- cgit v1.2.3-70-g09d2 From 352d48008b6f3e02d8ce77868432e329dd921cb1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 19:59:12 -0200 Subject: [TCP]: Tidy up skb_entail Heck, it even saves us some few bytes: [acme@newtoy net-2.6.20]$ codiff -f /tmp/tcp.o.before ../OUTPUT/qemu/net-2.6.20/net/ipv4/tcp.o /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv4/tcp.c: tcp_sendpage | -7 tcp_sendmsg | -5 2 functions changed, 12 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/tcp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 168f9de906bc..a6b228914b8e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -463,11 +463,12 @@ static inline int forced_push(struct tcp_sock *tp) static inline void skb_entail(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb) { - skb->csum = 0; - TCP_SKB_CB(skb)->seq = tp->write_seq; - TCP_SKB_CB(skb)->end_seq = tp->write_seq; - TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; - TCP_SKB_CB(skb)->sacked = 0; + struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); + + skb->csum = 0; + tcb->seq = tcb->end_seq = tp->write_seq; + tcb->flags = TCPCB_FLAG_ACK; + tcb->sacked = 0; skb_header_release(skb); __skb_queue_tail(&sk->sk_write_queue, skb); sk_charge_skb(sk, skb); -- cgit v1.2.3-70-g09d2 From cd28786d6d4209ec32a375d92188ec7b4d98779f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:44 -0500 Subject: NetLabel: convert the unlabeled accept flag to use RCU Currently the NetLabel unlabeled packet accept flag is an atomic type and it is checked for every non-NetLabel packet which comes into the system but rarely ever changed. This patch changes this flag to a normal integer and protects it with RCU locking. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/netlabel/netlabel_unlabeled.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index a1d4ae51db04..07283e1dfad2 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -47,7 +47,8 @@ #include "netlabel_unlabeled.h" /* Accept unlabeled packets flag */ -static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(netlabel_unlabel_acceptflg_lock); +static u8 netlabel_unlabel_acceptflg = 0; /* NetLabel Generic NETLINK CIPSOv4 family */ static struct genl_family netlbl_unlabel_gnl_family = { @@ -82,8 +83,12 @@ static void netlbl_unlabel_acceptflg_set(u8 value, struct audit_buffer *audit_buf; u8 old_val; - old_val = atomic_read(&netlabel_unlabel_accept_flg); - atomic_set(&netlabel_unlabel_accept_flg, value); + rcu_read_lock(); + old_val = netlabel_unlabel_acceptflg; + spin_lock(&netlabel_unlabel_acceptflg_lock); + netlabel_unlabel_acceptflg = value; + spin_unlock(&netlabel_unlabel_acceptflg_lock); + rcu_read_unlock(); audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, audit_info); @@ -148,9 +153,11 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) goto list_failure; } + rcu_read_lock(); ret_val = nla_put_u8(ans_skb, NLBL_UNLABEL_A_ACPTFLG, - atomic_read(&netlabel_unlabel_accept_flg)); + netlabel_unlabel_acceptflg); + rcu_read_unlock(); if (ret_val != 0) goto list_failure; @@ -236,10 +243,17 @@ int netlbl_unlabel_genl_init(void) */ int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) { - if (atomic_read(&netlabel_unlabel_accept_flg) == 1) - return netlbl_secattr_init(secattr); + int ret_val; + + rcu_read_lock(); + if (netlabel_unlabel_acceptflg == 1) { + netlbl_secattr_init(secattr); + ret_val = 0; + } else + ret_val = -ENOMSG; + rcu_read_unlock(); - return -ENOMSG; + return ret_val; } /** -- cgit v1.2.3-70-g09d2 From 701a90bad99b8081a824cca52c178c8fc8f46bb2 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:46 -0500 Subject: NetLabel: make netlbl_lsm_secattr struct easier/quicker to understand The existing netlbl_lsm_secattr struct required the LSM to check all of the fields to determine if any security attributes were present resulting in a lot of work in the common case of no attributes. This patch adds a 'flags' field which is used to indicate which attributes are present in the structure; this should allow the LSM to do a quick comparison to determine if the structure holds any security attributes. Example: if (netlbl_lsm_secattr->flags) /* security attributes present */ else /* NO security attributes present */ Signed-off-by: Paul Moore Signed-off-by: James Morris --- include/net/netlabel.h | 13 +++++++++++-- net/ipv4/cipso_ipv4.c | 22 ++++++++++++++-------- net/netlabel/netlabel_kapi.c | 5 ++++- security/selinux/ss/services.c | 24 ++++++++++++++++-------- 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 4e223aa25e5b..d605d7954013 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -111,11 +111,17 @@ struct netlbl_lsm_cache { void (*free) (const void *data); void *data; }; +#define NETLBL_SECATTR_NONE 0x00000000 +#define NETLBL_SECATTR_DOMAIN 0x00000001 +#define NETLBL_SECATTR_CACHE 0x00000002 +#define NETLBL_SECATTR_MLS_LVL 0x00000004 +#define NETLBL_SECATTR_MLS_CAT 0x00000008 struct netlbl_lsm_secattr { + u32 flags; + char *domain; u32 mls_lvl; - u32 mls_lvl_vld; unsigned char *mls_cat; size_t mls_cat_len; @@ -174,7 +180,10 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache) */ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr) { - memset(secattr, 0, sizeof(*secattr)); + secattr->flags = 0; + secattr->domain = NULL; + secattr->mls_cat = NULL; + secattr->cache = NULL; } /** diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 095038ad72a4..f0a0785047fe 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key, entry->activity += 1; atomic_inc(&entry->lsm_data->refcount); secattr->cache = entry->lsm_data; + secattr->flags |= NETLBL_SECATTR_CACHE; if (prev_entry == NULL) { spin_unlock_bh(&cipso_v4_cache[bkt].lock); return 0; @@ -991,12 +992,15 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, unsigned char **buffer, u32 *buffer_len) { - int ret_val = -EPERM; + int ret_val; unsigned char *buf = NULL; u32 buf_len; u32 level; - if (secattr->mls_cat) { + if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) + return -EPERM; + + if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, GFP_ATOMIC); if (buf == NULL) @@ -1013,10 +1017,10 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, /* This will send packets using the "optimized" format when * possibile as specified in section 3.4.2.6 of the * CIPSO draft. */ - if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) - ret_val = 10; - - buf_len = 4 + ret_val; + if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) + buf_len = 14; + else + buf_len = 4 + ret_val; } else { buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); if (buf == NULL) @@ -1070,7 +1074,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, if (ret_val != 0) return ret_val; secattr->mls_lvl = level; - secattr->mls_lvl_vld = 1; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; if (tag_len > 4) { switch (doi_def->type) { @@ -1094,8 +1098,10 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, if (ret_val < 0) { kfree(secattr->mls_cat); return ret_val; + } else if (ret_val > 0) { + secattr->mls_cat_len = ret_val; + secattr->flags |= NETLBL_SECATTR_MLS_CAT; } - secattr->mls_cat_len = ret_val; } return 0; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index ff971103fd0c..da2f1975a042 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -62,6 +62,9 @@ int netlbl_socket_setattr(const struct socket *sock, int ret_val = -ENOENT; struct netlbl_dom_map *dom_entry; + if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0) + return -ENOENT; + rcu_read_lock(); dom_entry = netlbl_domhsh_getentry(secattr->domain); if (dom_entry == NULL) @@ -200,7 +203,7 @@ void netlbl_cache_invalidate(void) int netlbl_cache_add(const struct sk_buff *skb, const struct netlbl_lsm_secattr *secattr) { - if (secattr->cache == NULL) + if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) return -ENOMSG; if (CIPSO_V4_OPTEXIST(skb)) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 408820486af0..1f5bbb246d28 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2254,8 +2254,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) cache = kzalloc(sizeof(*cache), GFP_ATOMIC); if (cache == NULL) goto netlbl_cache_add_return; - secattr.cache->free = selinux_netlbl_cache_free; - secattr.cache->data = (void *)cache; cache->type = NETLBL_CACHE_T_MLS; if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, @@ -2268,6 +2266,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; + secattr.cache->free = selinux_netlbl_cache_free; + secattr.cache->data = (void *)cache; + secattr.flags = NETLBL_SECATTR_CACHE; + netlbl_cache_add(skb, &secattr); netlbl_cache_add_return: @@ -2313,7 +2315,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, POLICY_RDLOCK; - if (secattr->cache) { + if (secattr->flags & NETLBL_SECATTR_CACHE) { cache = NETLBL_CACHE(secattr->cache->data); switch (cache->type) { case NETLBL_CACHE_T_SID: @@ -2346,7 +2348,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, default: goto netlbl_secattr_to_sid_return; } - } else if (secattr->mls_lvl_vld) { + } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { ctx = sidtab_search(&sidtab, base_sid); if (ctx == NULL) goto netlbl_secattr_to_sid_return; @@ -2355,7 +2357,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ctx_new.role = ctx->role; ctx_new.type = ctx->type; mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); - if (secattr->mls_cat) { + if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { if (mls_import_cat(&ctx_new, secattr->mls_cat, secattr->mls_cat_len, @@ -2414,11 +2416,13 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, &secattr); - if (rc == 0) + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = selinux_netlbl_secattr_to_sid(skb, &secattr, base_sid, sid); + else + *sid = SECSID_NULL; netlbl_secattr_destroy(&secattr); return rc; @@ -2455,7 +2459,6 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], GFP_ATOMIC); mls_export_lvl(ctx, &secattr.mls_lvl, NULL); - secattr.mls_lvl_vld = 1; rc = mls_export_cat(ctx, &secattr.mls_cat, &secattr.mls_cat_len, @@ -2464,6 +2467,10 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) if (rc != 0) goto netlbl_socket_setsid_return; + secattr.flags |= NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; + if (secattr.mls_cat) + secattr.flags |= NETLBL_SECATTR_MLS_CAT; + rc = netlbl_socket_setattr(sock, &secattr); if (rc == 0) sksec->nlbl_state = NLBL_LABELED; @@ -2564,6 +2571,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) netlbl_secattr_init(&secattr); if (netlbl_sock_getattr(sk, &secattr) == 0 && + secattr.flags != NETLBL_SECATTR_NONE && selinux_netlbl_secattr_to_sid(NULL, &secattr, SECINITSID_UNLABELED, @@ -2756,7 +2764,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, sksec->nlbl_state == NLBL_LABELED) { netlbl_secattr_init(&secattr); rc = netlbl_socket_getattr(sock, &secattr); - if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = -EACCES; netlbl_secattr_destroy(&secattr); } -- cgit v1.2.3-70-g09d2 From 05e00cbf5036929355020dab4837b637203a0742 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:47 -0500 Subject: NetLabel: check for a CIPSOv4 option before we do call into the CIPSOv4 layer Right now the NetLabel code always jumps into the CIPSOv4 layer to determine if a CIPSO IP option is present. However, we can do this check directly in the NetLabel code by making use of the CIPSO_V4_OPTEXIST() macro which should save us a function call in the common case of not having a CIPSOv4 option present. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 2 -- net/netlabel/netlabel_kapi.c | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index f0a0785047fe..fb5d913f5815 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1435,8 +1435,6 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, u32 doi; struct cipso_v4_doi *doi_def; - if (!CIPSO_V4_OPTEXIST(skb)) - return -ENOMSG; cipso_ptr = CIPSO_V4_OPTPTR(skb); if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) return 0; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index da2f1975a042..b35ebf94918c 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -149,10 +149,8 @@ int netlbl_socket_getattr(const struct socket *sock, int netlbl_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_skbuff_getattr(skb, secattr); - if (ret_val == 0) + if (CIPSO_V4_OPTEXIST(skb) && + cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; return netlbl_unlabel_getattr(secattr); -- cgit v1.2.3-70-g09d2 From 6ce61a7c2678800cfe59a5f4a41ce8f785b9d355 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:48 -0500 Subject: NetLabel: add tag verification when adding new CIPSOv4 DOI definitions Currently the CIPSOv4 engine does not do any sort of checking when a new DOI definition is added. The tags are still verified but only as a side effect of normal NetLabel operation (packet processing, socket labeling, etc.) which would cause application errors due to the faulty configuration. This patch adds tag checking when new DOI definition are added allowing us to catch these configuration problems when they happen. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index fb5d913f5815..23a968f754be 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -447,8 +447,22 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) */ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) { + u32 iter; + if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) return -EINVAL; + for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) { + switch (doi_def->tags[iter]) { + case CIPSO_V4_TAG_RBITMAP: + break; + case CIPSO_V4_TAG_INVALID: + if (iter == 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + } doi_def->valid = 1; INIT_RCU_HEAD(&doi_def->rcu); -- cgit v1.2.3-70-g09d2 From 91b1ed0afdbffbda88c472ef72af37e19b7876fb Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:49 -0500 Subject: NetLabel: fixup the handling of CIPSOv4 tags to allow for multiple tag types While the original CIPSOv4 code had provisions for multiple tag types the implementation was not as great as it could be, pushing a lot of non-tag specific processing into the tag specific code blocks. This patch fixes that issue making it easier to support multiple tag types in the future. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 113 +++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 60 deletions(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 23a968f754be..a056278ad626 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -958,35 +958,28 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, * Protocol Handling Functions */ +#define CIPSO_V4_OPT_LEN_MAX 40 #define CIPSO_V4_HDR_LEN 6 /** * cipso_v4_gentag_hdr - Generate a CIPSO option header * @doi_def: the DOI definition - * @len: the total tag length in bytes + * @len: the total tag length in bytes, not including this header * @buf: the CIPSO option buffer * * Description: - * Write a CIPSO header into the beginning of @buffer. Return zero on success, - * negative values on failure. + * Write a CIPSO header into the beginning of @buffer. * */ -static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, - u32 len, - unsigned char *buf) +static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, + unsigned char *buf, + u32 len) { - if (CIPSO_V4_HDR_LEN + len > 40) - return -ENOSPC; - buf[0] = IPOPT_CIPSO; buf[1] = CIPSO_V4_HDR_LEN + len; *(__be32 *)&buf[2] = htonl(doi_def->doi); - - return 0; } -#define CIPSO_V4_TAG1_CAT_LEN 30 - /** * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) * @doi_def: the DOI definition @@ -997,71 +990,50 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, * Description: * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The * actual buffer length may be larger than the indicated size due to - * translation between host and network category bitmaps. Returns zero on - * success, negative values on failure. + * translation between host and network category bitmaps. Returns the size of + * the tag on success, negative values on failure. * */ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, const struct netlbl_lsm_secattr *secattr, - unsigned char **buffer, - u32 *buffer_len) + unsigned char *buffer, + u32 buffer_len) { int ret_val; - unsigned char *buf = NULL; - u32 buf_len; + u32 tag_len; u32 level; if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) return -EPERM; - if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { - buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, - GFP_ATOMIC); - if (buf == NULL) - return -ENOMEM; + ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); + if (ret_val != 0) + return ret_val; + if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { ret_val = cipso_v4_map_cat_rbm_hton(doi_def, secattr->mls_cat, secattr->mls_cat_len, - &buf[CIPSO_V4_HDR_LEN + 4], - CIPSO_V4_TAG1_CAT_LEN); + &buffer[4], + buffer_len - 4); if (ret_val < 0) - goto gentag_failure; + return ret_val; /* This will send packets using the "optimized" format when * possibile as specified in section 3.4.2.6 of the * CIPSO draft. */ if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) - buf_len = 14; + tag_len = 14; else - buf_len = 4 + ret_val; - } else { - buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); - if (buf == NULL) - return -ENOMEM; - buf_len = 4; - } - - ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); - if (ret_val != 0) - goto gentag_failure; - - ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); - if (ret_val != 0) - goto gentag_failure; - - buf[CIPSO_V4_HDR_LEN] = 0x01; - buf[CIPSO_V4_HDR_LEN + 1] = buf_len; - buf[CIPSO_V4_HDR_LEN + 3] = level; + tag_len = 4 + ret_val; + } else + tag_len = 4; - *buffer = buf; - *buffer_len = CIPSO_V4_HDR_LEN + buf_len; + buffer[0] = 0x01; + buffer[1] = tag_len; + buffer[3] = level; - return 0; - -gentag_failure: - kfree(buf); - return ret_val; + return tag_len; } /** @@ -1284,7 +1256,7 @@ int cipso_v4_socket_setattr(const struct socket *sock, { int ret_val = -EPERM; u32 iter; - unsigned char *buf = NULL; + unsigned char *buf; u32 buf_len = 0; u32 opt_len; struct ip_options *opt = NULL; @@ -1300,17 +1272,28 @@ int cipso_v4_socket_setattr(const struct socket *sock, if (sk == NULL) return 0; + /* We allocate the maximum CIPSO option size here so we are probably + * being a little wasteful, but it makes our life _much_ easier later + * on and after all we are only talking about 40 bytes. */ + buf_len = CIPSO_V4_OPT_LEN_MAX; + buf = kmalloc(buf_len, GFP_ATOMIC); + if (buf == NULL) { + ret_val = -ENOMEM; + goto socket_setattr_failure; + } + /* XXX - This code assumes only one tag per CIPSO option which isn't * really a good assumption to make but since we only support the MAC * tags right now it is a safe assumption. */ iter = 0; do { + memset(buf, 0, buf_len); switch (doi_def->tags[iter]) { case CIPSO_V4_TAG_RBITMAP: ret_val = cipso_v4_gentag_rbm(doi_def, - secattr, - &buf, - &buf_len); + secattr, + &buf[CIPSO_V4_HDR_LEN], + buf_len - CIPSO_V4_HDR_LEN); break; default: ret_val = -EPERM; @@ -1318,11 +1301,13 @@ int cipso_v4_socket_setattr(const struct socket *sock, } iter++; - } while (ret_val != 0 && + } while (ret_val < 0 && iter < CIPSO_V4_TAG_MAXCNT && doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); - if (ret_val != 0) + if (ret_val < 0) goto socket_setattr_failure; + cipso_v4_gentag_hdr(doi_def, buf, ret_val); + buf_len = CIPSO_V4_HDR_LEN + ret_val; /* We can't use ip_options_get() directly because it makes a call to * ip_options_get_alloc() which allocates memory with GFP_KERNEL and @@ -1396,6 +1381,10 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) rcu_read_unlock(); return -ENOMSG; } + + /* XXX - This code assumes only one tag per CIPSO option which isn't + * really a good assumption to make but since we only support the MAC + * tags right now it is a safe assumption. */ switch (cipso_ptr[6]) { case CIPSO_V4_TAG_RBITMAP: ret_val = cipso_v4_parsetag_rbm(doi_def, @@ -1458,6 +1447,10 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, doi_def = cipso_v4_doi_getdef(doi); if (doi_def == NULL) goto skbuff_getattr_return; + + /* XXX - This code assumes only one tag per CIPSO option which isn't + * really a good assumption to make but since we only support the MAC + * tags right now it is a safe assumption. */ switch (cipso_ptr[6]) { case CIPSO_V4_TAG_RBITMAP: ret_val = cipso_v4_parsetag_rbm(doi_def, -- cgit v1.2.3-70-g09d2 From 9fade4bf8eed3db2fd1306968da4d51bc611aca3 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:50 -0500 Subject: NetLabel: return the correct error for translated CIPSOv4 tags The CIPSOv4 translated tag #1 mapping does not always return the correct error code if the desired mapping does not exist; instead of returning -EPERM it returns -ENOSPC indicating that the buffer is not large enough to hold the translated value. This was caused by failing to check a specific error condition. This patch fixes this so that unknown mappings return -EPERM which is consistent with the rest of the related CIPSOv4 code. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index a056278ad626..c305de6fa206 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -867,6 +867,8 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, return -EPERM; net_spot = host_cat_array[host_spot]; + if (net_spot >= CIPSO_V4_INV_CAT) + return -EPERM; if (net_spot >= net_clen_bits) return -ENOSPC; cipso_v4_bitmap_setbit(net_cat, net_spot, 1); @@ -935,6 +937,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, return -EPERM; host_spot = net_cat_array[net_spot]; + if (host_spot >= CIPSO_V4_INV_CAT) + return -EPERM; if (host_spot >= host_clen_bits) return -ENOSPC; cipso_v4_bitmap_setbit(host_cat, host_spot, 1); -- cgit v1.2.3-70-g09d2 From 9bb5fd2b05cb4dba229e225536faa59eaadd837d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:52 -0500 Subject: NetLabel: use cipso_v4_doi_search() for local CIPSOv4 functions The cipso_v4_doi_search() function behaves the same as cipso_v4_doi_getdef() but is a local, static function so use it whenever possibile in the CIPSOv4 code base. Signed-of-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c305de6fa206..a60af8304073 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1135,7 +1135,7 @@ int cipso_v4_validate(unsigned char **option) } rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(ntohl(*((__be32 *)&opt[2]))); + doi_def = cipso_v4_doi_search(ntohl(*((u32 *)&opt[2]))); if (doi_def == NULL) { err_offset = 2; goto validate_return_locked; @@ -1380,7 +1380,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) doi = ntohl(*(__be32 *)&cipso_ptr[2]); rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(doi); + doi_def = cipso_v4_doi_search(doi); if (doi_def == NULL) { rcu_read_unlock(); return -ENOMSG; @@ -1448,7 +1448,7 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, doi = ntohl(*(__be32 *)&cipso_ptr[2]); rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(doi); + doi_def = cipso_v4_doi_search(doi); if (doi_def == NULL) goto skbuff_getattr_return; -- cgit v1.2.3-70-g09d2 From de64688ffb952a65ddbc5295ccd235d35f292593 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 17 Nov 2006 17:38:55 -0500 Subject: NetLabel: honor the audit_enabled flag The audit_enabled flag is used to signal when syscall auditing is to be performed. While NetLabel uses a Netlink interface instead of syscalls, it is reasonable to consider the NetLabel Netlink interface as a form of syscall so pay attention to the audit_enabled flag when generating audit messages in NetLabel. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/netlabel/netlabel_cipso_v4.c | 26 ++++++++++++--------- net/netlabel/netlabel_domainhash.c | 48 +++++++++++++++++--------------------- net/netlabel/netlabel_unlabeled.c | 8 +++++-- net/netlabel/netlabel_user.c | 7 ++++++ 4 files changed, 50 insertions(+), 39 deletions(-) (limited to 'net') diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index fe9851fac85d..743b05734a49 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -407,12 +407,14 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); - audit_log_format(audit_buf, - " cipso_doi=%u cipso_type=%s res=%u", - doi, - type_str, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " cipso_doi=%u cipso_type=%s res=%u", + doi, + type_str, + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } @@ -680,11 +682,13 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); - audit_log_format(audit_buf, - " cipso_doi=%u res=%u", - doi, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " cipso_doi=%u res=%u", + doi, + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index af4371d3b459..f46a0aeec44f 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -202,7 +202,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, int ret_val; u32 bkt; struct audit_buffer *audit_buf; - char *audit_domain; switch (entry->type) { case NETLBL_NLTYPE_UNLABELED: @@ -243,24 +242,24 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, } else ret_val = -EINVAL; - if (entry->domain != NULL) - audit_domain = entry->domain; - else - audit_domain = "(default)"; audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); - audit_log_format(audit_buf, " nlbl_domain=%s", audit_domain); - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - audit_log_format(audit_buf, " nlbl_protocol=unlbl"); - break; - case NETLBL_NLTYPE_CIPSOV4: + if (audit_buf != NULL) { audit_log_format(audit_buf, - " nlbl_protocol=cipsov4 cipso_doi=%u", - entry->type_def.cipsov4->doi); - break; + " nlbl_domain=%s", + entry->domain ? entry->domain : "(default)"); + switch (entry->type) { + case NETLBL_NLTYPE_UNLABELED: + audit_log_format(audit_buf, " nlbl_protocol=unlbl"); + break; + case NETLBL_NLTYPE_CIPSOV4: + audit_log_format(audit_buf, + " nlbl_protocol=cipsov4 cipso_doi=%u", + entry->type_def.cipsov4->doi); + break; + } + audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); } - audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); rcu_read_unlock(); @@ -310,7 +309,6 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) int ret_val = -ENOENT; struct netlbl_dom_map *entry; struct audit_buffer *audit_buf; - char *audit_domain; rcu_read_lock(); if (domain != NULL) @@ -348,16 +346,14 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) spin_unlock(&netlbl_domhsh_def_lock); } - if (entry->domain != NULL) - audit_domain = entry->domain; - else - audit_domain = "(default)"; audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); - audit_log_format(audit_buf, - " nlbl_domain=%s res=%u", - audit_domain, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " nlbl_domain=%s res=%u", + entry->domain ? entry->domain : "(default)", + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } if (ret_val == 0) call_rcu(&entry->rcu, netlbl_domhsh_free_entry); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 07283e1dfad2..5bc37181662e 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -92,8 +93,11 @@ static void netlbl_unlabel_acceptflg_set(u8 value, audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, audit_info); - audit_log_format(audit_buf, " unlbl_accept=%u old=%u", value, old_val); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " unlbl_accept=%u old=%u", value, old_val); + audit_log_end(audit_buf); + } } /* diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 98a416381e61..42f12bd65964 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c @@ -46,6 +46,10 @@ #include "netlabel_cipso_v4.h" #include "netlabel_user.h" +/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for + * details */ +extern int audit_enabled; + /* * NetLabel NETLINK Setup Functions */ @@ -101,6 +105,9 @@ struct audit_buffer *netlbl_audit_start_common(int type, char *secctx; u32 secctx_len; + if (audit_enabled == 0) + return NULL; + audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type); if (audit_buf == NULL) return NULL; -- cgit v1.2.3-70-g09d2 From 84116716cc9404356f775443b460f76766f08f65 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:26:03 -0200 Subject: [DCCP]: enable debug messages also for static builds This patch * makes debugging (when configured) work both for static / module build * provides generic debugging macros for use in other DCCP / CCID modules * adds missing information about debug parameters to Kconfig * performs some code tidy-up Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/Kconfig | 3 +++ net/dccp/ackvec.c | 11 ++++------- net/dccp/ccids/Kconfig | 14 ++++++++++++-- net/dccp/ccids/ccid2.c | 16 ++++++---------- net/dccp/dccp.h | 19 ++++++++++++------- 5 files changed, 37 insertions(+), 26 deletions(-) (limited to 'net') diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index 2fc5e55d2a8d..b8a68dd41000 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig @@ -38,6 +38,9 @@ config IP_DCCP_DEBUG ---help--- Only use this if you're hacking DCCP. + When compiling DCCP as a module, this debugging output can be toggled + by setting the parameter dccp_debug of the `dccp' module to 0 or 1. + Just say N. config NET_DCCPPROBE diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index bd20a2c55e25..d34badcd012e 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -318,21 +318,18 @@ out_duplicate: #ifdef CONFIG_IP_DCCP_DEBUG void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) { - if (!dccp_debug) - return; - - printk("ACK vector len=%d, ackno=%llu |", len, - (unsigned long long)ackno); + dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len, + (unsigned long long)ackno); while (len--) { const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; - printk("%d,%d|", state, rl); + dccp_pr_debug_cat("%d,%d|", state, rl); ++vector; } - printk("\n"); + dccp_pr_debug_cat("\n"); } void dccp_ackvec_print(const struct dccp_ackvec *av) diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 8533dabfb9f8..ba826d99ed03 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -28,13 +28,20 @@ config IP_DCCP_CCID2 This text was extracted from RFC 4340 (sec. 10.1), http://www.ietf.org/rfc/rfc4340.txt + To compile this CCID as a module, choose M here: the module will be + called dccp_ccid2. + If in doubt, say M. config IP_DCCP_CCID2_DEBUG - bool "CCID2 debug" + bool "CCID2 debugging messages" depends on IP_DCCP_CCID2 ---help--- - Enable CCID2 debug messages. + Enable CCID2-specific debugging messages. + + When compiling CCID2 as a module, this debugging output can + additionally be toggled by setting the ccid2_debug module + parameter to 0 or 1. If in doubt, say N. @@ -62,6 +69,9 @@ config IP_DCCP_CCID3 This text was extracted from RFC 4340 (sec. 10.2), http://www.ietf.org/rfc/rfc4340.txt + To compile this CCID as a module, choose M here: the module will be + called dccp_ccid3. + If in doubt, say M. config IP_DCCP_TFRC_LIB diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 6533cb2f27bb..0fb0d66544a2 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -33,18 +33,11 @@ #include "../dccp.h" #include "ccid2.h" -static int ccid2_debug; #ifdef CONFIG_IP_DCCP_CCID2_DEBUG -#define ccid2_pr_debug(format, a...) \ - do { if (ccid2_debug) \ - printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ - } while (0) -#else -#define ccid2_pr_debug(format, a...) -#endif +static int ccid2_debug; +#define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a) -#ifdef CONFIG_IP_DCCP_CCID2_DEBUG static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) { int len = 0; @@ -86,7 +79,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN); } #else -#define ccid2_hc_tx_check_sanity(hctx) do {} while (0) +#define ccid2_pr_debug(format, a...) +#define ccid2_hc_tx_check_sanity(hctx) #endif static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, @@ -841,8 +835,10 @@ static struct ccid_operations ccid2 = { .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, }; +#ifdef CONFIG_IP_DCCP_CCID2_DEBUG module_param(ccid2_debug, int, 0444); MODULE_PARM_DESC(ccid2_debug, "Enable debug messages"); +#endif static __init int ccid2_module_init(void) { diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index ecb4e7bd1a84..33d86f53138b 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -26,15 +26,20 @@ __stringify((cond))); \ } while (0) +#ifdef MODULE +#define DCCP_PRINTK(enable, fmt, args...) do { if (enable) \ + printk(fmt, ##args); \ + } while(0) +#else +#define DCCP_PRINTK(enable, fmt, args...) printk(fmt, ##args) +#endif +#define DCCP_PR_DEBUG(enable, fmt, a...) DCCP_PRINTK(enable, KERN_DEBUG \ + "%s: " fmt, __FUNCTION__, ##a) + #ifdef CONFIG_IP_DCCP_DEBUG extern int dccp_debug; - -#define dccp_pr_debug(format, a...) \ - do { if (dccp_debug) \ - printk(KERN_DEBUG "%s: " format, __FUNCTION__ , ##a); \ - } while (0) -#define dccp_pr_debug_cat(format, a...) do { if (dccp_debug) \ - printk(format, ##a); } while (0) +#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) +#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) #else #define dccp_pr_debug(format, a...) #define dccp_pr_debug_cat(format, a...) -- cgit v1.2.3-70-g09d2 From 56724aa434e9b4d73548021ede7a1474f533f3fe Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:28:09 -0200 Subject: [DCCP]: Add CCID3 debug support to Kconfig This adds a CCID3 debug option to the configuration menu which is missing in Kconfig, but already used by the code. CCID 2 already provides such an entry. To enable debugging, set CONFIG_IP_DCCP_CCID3_DEBUG=y NOTE: The use of ccid3_{t,r}x_state_name is safe, since now only enum values can appear. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/Kconfig | 11 +++++++++++ net/dccp/ccids/ccid3.c | 16 ++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index ba826d99ed03..dac89166eb18 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -78,4 +78,15 @@ config IP_DCCP_TFRC_LIB depends on IP_DCCP_CCID3 def_tristate IP_DCCP_CCID3 +config IP_DCCP_CCID3_DEBUG + bool "CCID3 debugging messages" + depends on IP_DCCP_CCID3 + ---help--- + Enable CCID3-specific debugging messages. + + When compiling CCID3 as a module, this debugging output can + additionally be toggled by setting the ccid3_debug module + parameter to 0 or 1. + + If in doubt, say N. endmenu diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 2fa0c6d1fbee..7db801ec1ab9 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -60,13 +60,11 @@ static u32 usecs_div(const u32 a, const u32 b) return (b >= 2 * div) ? tmp / (b / div) : tmp; } -static int ccid3_debug; -#ifdef CCID3_DEBUG -#define ccid3_pr_debug(format, a...) \ - do { if (ccid3_debug) \ - printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ - } while (0) + +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG +static int ccid3_debug; +#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) #else #define ccid3_pr_debug(format, a...) #endif @@ -75,7 +73,7 @@ static struct dccp_tx_hist *ccid3_tx_hist; static struct dccp_rx_hist *ccid3_rx_hist; static struct dccp_li_hist *ccid3_li_hist; -#ifdef CCID3_DEBUG +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) { static char *ccid3_state_names[] = { @@ -676,7 +674,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) * RX Half Connection methods */ -#ifdef CCID3_DEBUG +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) { static char *ccid3_rx_state_names[] = { @@ -1240,8 +1238,10 @@ static struct ccid_operations ccid3 = { .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, }; +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG module_param(ccid3_debug, int, 0444); MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); +#endif static __init int ccid3_module_init(void) { -- cgit v1.2.3-70-g09d2 From b1308dc015eb09cf094ca169296738a13ae049ad Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Nov 2006 18:30:17 -0200 Subject: [DCCP]: Set TX Queue Length Bounds via Sysctl Previously the transmit queue was unbounded. This patch: * puts a limit on transmit queue length and sends back EAGAIN if the buffer is full * sets the TX queue length to a sensible default * implements tx buffer sysctls for DCCP Signed-off-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/dccp.h | 1 + net/dccp/proto.c | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'net') diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 33d86f53138b..3a94625a1af3 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -87,6 +87,7 @@ extern int sysctl_dccp_feat_tx_ccid; extern int sysctl_dccp_feat_ack_ratio; extern int sysctl_dccp_feat_send_ack_vector; extern int sysctl_dccp_feat_send_ndp_count; +extern int sysctl_dccp_tx_qlen; /* is seq1 < seq2 ? */ static inline int before48(const u64 seq1, const u64 seq2) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 0225bdacd3b1..a7f345c8d0db 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -52,6 +52,9 @@ struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { EXPORT_SYMBOL_GPL(dccp_hashinfo); +/* the maximum queue length for tx in packets. 0 is no limit */ +int sysctl_dccp_tx_qlen __read_mostly = 5; + void dccp_set_state(struct sock *sk, const int state) { const int oldstate = sk->sk_state; @@ -645,6 +648,13 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return -EMSGSIZE; lock_sock(sk); + + if (sysctl_dccp_tx_qlen && + (sk->sk_write_queue.qlen >= sysctl_dccp_tx_qlen)) { + rc = -EAGAIN; + goto out_release; + } + timeo = sock_sndtimeo(sk, noblock); /* -- cgit v1.2.3-70-g09d2 From 59348b19efebfd6a8d0791ff81d207b16594c94b Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:39:23 -0200 Subject: [DCCP]: Simplified conditions due to use of enum:8 states This reaps the benefit of the earlier patch, which changed the type of CCID 3 states to use enums, in that many conditions are now simplified and the number of possible (unexpected) values is greatly reduced. In a few instances, this also allowed to simplify pre-conditions; where care has been taken to retain logical equivalence. [DCCP]: Introduce a consistent BUG/WARN message scheme This refines the existing set of DCCP messages so that * BUG(), BUG_ON(), WARN_ON() have meaningful DCCP-specific counterparts * DCCP_CRIT (for severe warnings) is not rate-limited * DCCP_WARN() is introduced as rate-limited wrapper Using these allows a faster and cleaner transition to their original counterparts once the code has matured into a full DCCP implementation. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ackvec.c | 5 +- net/dccp/ccids/ccid2.c | 2 +- net/dccp/ccids/ccid3.c | 132 ++++++++++++++++--------------------- net/dccp/ccids/lib/loss_interval.c | 6 +- net/dccp/ccids/lib/tfrc_equation.c | 7 +- net/dccp/dccp.h | 17 +++-- net/dccp/feat.c | 11 ++-- net/dccp/input.c | 25 ++++--- net/dccp/ipv4.c | 24 +++---- net/dccp/ipv6.c | 4 +- net/dccp/minisocks.c | 7 +- net/dccp/options.c | 10 ++- net/dccp/output.c | 16 ++--- net/dccp/proto.c | 5 +- 14 files changed, 115 insertions(+), 156 deletions(-) (limited to 'net') diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index d34badcd012e..1b4b60d8bdec 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -461,9 +461,6 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, return 0; } -static char dccp_ackvec_slab_msg[] __initdata = - KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n"; - int __init dccp_ackvec_init(void) { dccp_ackvec_slab = kmem_cache_create("dccp_ackvec", @@ -485,7 +482,7 @@ out_destroy_slab: kmem_cache_destroy(dccp_ackvec_slab); dccp_ackvec_slab = NULL; out_err: - printk(dccp_ackvec_slab_msg); + DCCP_CRIT("Unable to create Ack Vector slab cache"); return -ENOBUFS; } diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 0fb0d66544a2..207f7f9b36ca 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -420,7 +420,7 @@ static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset, return -1; out_invalid_option: - BUG_ON(1); /* should never happen... options were previously parsed ! */ + DCCP_BUG("Invalid option - this should not happen (previous parsing)!"); return -1; } diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 7db801ec1ab9..4eada515b773 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -176,8 +176,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ccid3_tx_state_name(hctx->ccid3hctx_state)); switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_TERM: - goto out; case TFRC_SSTATE_NO_FBACK: /* Halve send rate */ hctx->ccid3hctx_x /= 2; @@ -240,9 +238,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) 2 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x)); break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_NO_SENT: + DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); + /* fall through */ + case TFRC_SSTATE_TERM: goto out; } @@ -264,7 +263,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, long delay; int rc = -ENOTCONN; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); /* Check if pure ACK or Terminating*/ /* @@ -282,9 +281,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, rc = -ENOBUFS; if (unlikely(new_packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough " - "mem to add to history, send refused\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, not enough mem to add to history," + "send refused\n", dccp_role(sk), sk); goto out; } @@ -317,9 +315,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, /* divide by -1000 is to convert to ms and get sign right */ rc = delay > 0 ? delay : 0; break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); rc = -EINVAL; break; } @@ -343,7 +340,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct timeval now; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); dccp_timestamp(sk, &now); @@ -354,13 +351,11 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't " - "exists in history!\n", __FUNCTION__); + DCCP_WARN("packet doesn't exist in history!\n"); return; } if (unlikely(packet->dccphtx_sent)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in " - "history!\n", __FUNCTION__); + DCCP_WARN("no unsent packet in history!\n"); return; } packet->dccphtx_tstamp = now; @@ -395,9 +390,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) case TFRC_SSTATE_NO_SENT: /* if first wasn't pure ack */ if (len != 0) - printk(KERN_CRIT "%s: %s, First packet sent is noted " - "as a data packet\n", - __FUNCTION__, dccp_role(sk)); + DCCP_CRIT("%s, First packet sent is noted " + "as a data packet", dccp_role(sk)); return; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: @@ -410,9 +404,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) hctx->ccid3hctx_t_ipi); } break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); break; } } @@ -430,7 +423,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) u32 x_recv; u32 r_sample; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); /* we are only interested in ACKs */ if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || @@ -455,11 +448,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, DCCP_SKB_CB(skb)->dccpd_ack_seq); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno " - "%llu(%s) does't exist in history!\n", - __FUNCTION__, dccp_role(sk), sk, + DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist " + "in history!\n", dccp_role(sk), sk, (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, - dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); + dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); return; } @@ -467,9 +459,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) dccp_timestamp(sk, &now); r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); if (unlikely(r_sample <= t_elapsed)) - LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " - "t_elapsed=%uus\n", - __FUNCTION__, r_sample, t_elapsed); + DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n", + r_sample, t_elapsed); else r_sample -= t_elapsed; @@ -554,9 +545,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); break; } } @@ -596,9 +586,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, switch (option) { case TFRC_OPT_LOSS_EVENT_RATE: if (unlikely(len != 4)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " - "len for TFRC_OPT_LOSS_EVENT_RATE\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, invalid len %d " + "for TFRC_OPT_LOSS_EVENT_RATE\n", + dccp_role(sk), sk, len); rc = -EINVAL; } else { opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); @@ -617,9 +607,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, break; case TFRC_OPT_RECEIVE_RATE: if (unlikely(len != 4)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " - "len for TFRC_OPT_RECEIVE_RATE\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, invalid len %d " + "for TFRC_OPT_RECEIVE_RATE\n", + dccp_role(sk), sk, len); rc = -EINVAL; } else { opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); @@ -722,17 +712,15 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) delta); } break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hcrx->ccid3hcrx_state); + case TFRC_RSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); return; } packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " - "in history!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, no data packet in history!\n", + dccp_role(sk), sk); return; } @@ -820,29 +808,29 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) } if (unlikely(step == 0)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history " - "contains no data packets!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, packet history has no data packets!\n", + dccp_role(sk), sk); return ~0; } if (unlikely(interval == 0)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a " - "win_count interval > 0. Defaulting to 1\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0." + "Defaulting to 1\n", dccp_role(sk), sk); interval = 1; } found: if (!tail) { - LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", - __FUNCTION__); + DCCP_CRIT("tail is null\n"); return ~0; } rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", dccp_role(sk), sk, rtt); - if (rtt == 0) - rtt = 1; + + if (rtt == 0) { + DCCP_WARN("RTT==0, setting to 1\n"); + rtt = 1; + } dccp_timestamp(sk, &tstamp); delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); @@ -856,9 +844,7 @@ found: tmp2 = (u32)tmp1; if (!tmp2) { - LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " - "%s: x_recv = %u, rtt =%u\n", - __FUNCTION__, x_recv, rtt); + DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt); return ~0; } @@ -904,8 +890,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); if (entry == NULL) { - printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__); - dump_stack(); + DCCP_BUG("out of memory - can not allocate entry"); return; } @@ -984,9 +969,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) u32 p_prev, rtt_prev, r_sample, t_elapsed; int loss; - BUG_ON(hcrx == NULL || - !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || - hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA)); + BUG_ON(hcrx == NULL); opt_recv = &dccp_sk(sk)->dccps_options_received; @@ -1004,9 +987,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) t_elapsed = opt_recv->dccpor_elapsed_time * 10; if (unlikely(r_sample <= t_elapsed)) - LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " - "t_elapsed=%uus\n", - __FUNCTION__, r_sample, t_elapsed); + DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n", + r_sample, t_elapsed); else r_sample -= t_elapsed; @@ -1030,9 +1012,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, skb, SLAB_ATOMIC); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to " - "add rx packet to history, consider it lost!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet " + "to history, consider it lost!\n", dccp_role(sk), sk); return; } @@ -1065,9 +1046,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_hc_rx_send_feedback(sk); } return; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hcrx->ccid3hcrx_state); + case TFRC_RSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); return; } @@ -1084,10 +1064,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) /* Scaling up by 1000000 as fixed decimal */ if (i_mean != 0) hcrx->ccid3hcrx_p = 1000000 / i_mean; - } else { - printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__); - dump_stack(); - } + } else + DCCP_BUG("empty loss history"); if (hcrx->ccid3hcrx_p > p_prev) { ccid3_hc_rx_send_feedback(sk); diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 906c81ab9d4f..48b9b93f8acb 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c @@ -13,7 +13,7 @@ #include #include - +#include "../../dccp.h" #include "loss_interval.h" struct dccp_li_hist *dccp_li_hist_new(const char *name) @@ -109,7 +109,7 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) i_tot = max(i_tot0, i_tot1); if (!w_tot) { - LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__); + DCCP_WARN("w_tot = 0\n"); return 1; } @@ -128,7 +128,7 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist, entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); if (entry == NULL) { dccp_li_hist_purge(hist, list); - dump_stack(); + DCCP_BUG("loss interval list entry is NULL"); return 0; } entry->dccplih_interval = ~0; diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 44076e0c6591..2601012383fb 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c @@ -13,9 +13,8 @@ */ #include - #include - +#include "../../dccp.h" #include "tfrc.h" #define TFRC_CALC_X_ARRSIZE 500 @@ -588,8 +587,10 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) /* p should be 0 unless there is a bug in my code */ index = 0; - if (R == 0) + if (R == 0) { + DCCP_WARN("RTT==0, setting to 1\n"); R = 1; /* RTT can't be zero or else divide by zero */ + } BUG_ON(index >= TFRC_CALC_X_ARRSIZE); diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 3a94625a1af3..68886986c8e4 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -18,12 +18,17 @@ #include #include "ackvec.h" -#define DCCP_CRIT(fmt, a...) LIMIT_NETDEBUG(KERN_CRIT fmt " at %s:%d/%s()\n", \ - ##a, __FILE__, __LINE__, __FUNCTION__) -#define DCCP_BUG(fmt, a...) do { DCCP_CRIT(fmt, ##a); dump_stack(); } while (0) -#define DCCP_BUG_ON(cond) do { if (unlikely((cond) == 0)) \ - DCCP_BUG("BUG: condition \"%s\" fails",\ - __stringify((cond))); \ +/* + * DCCP - specific warning and debugging macros. + */ +#define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt, \ + __FUNCTION__, ##a) +#define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \ + __FILE__, __LINE__, __FUNCTION__) +#define DCCP_BUG(a...) do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0) +#define DCCP_BUG_ON(cond) do { if (unlikely((cond) != 0)) \ + DCCP_BUG("\"%s\" holds (exception!)", \ + __stringify(cond)); \ } while (0) #ifdef MODULE diff --git a/net/dccp/feat.c b/net/dccp/feat.c index e808c418c992..4dc487f27a1f 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -25,11 +25,11 @@ int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, dccp_feat_debug(type, feature, *val); if (!dccp_feat_is_valid_type(type)) { - pr_info("option type %d invalid in negotiation\n", type); + DCCP_WARN("option type %d invalid in negotiation\n", type); return 1; } if (!dccp_feat_is_valid_length(type, feature, len)) { - pr_info("invalid length %d\n", len); + DCCP_WARN("invalid length %d\n", len); return 1; } /* XXX add further sanity checks */ @@ -169,7 +169,8 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, break; default: - WARN_ON(1); /* XXX implement res */ + DCCP_BUG("Fell through, feat=%d", opt->dccpop_feat); + /* XXX implement res */ return -EFAULT; } @@ -328,7 +329,7 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, switch (type) { case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break; case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break; - default: pr_info("invalid type %d\n", type); return; + default: DCCP_WARN("invalid type %d\n", type); return; } opt->dccpop_feat = feature; @@ -426,7 +427,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, switch (type) { case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break; case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break; - default: pr_info("invalid type %d\n", type); + default: DCCP_WARN("invalid type %d\n", type); return 1; } diff --git a/net/dccp/input.c b/net/dccp/input.c index 97ccdc30fd89..7371a2f3acf4 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -128,21 +128,18 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) DCCP_PKT_WITHOUT_ACK_SEQ)) dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq; } else { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, " - "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " - "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " - "sending SYNC...\n", - dccp_packet_name(dh->dccph_type), - (unsigned long long) lswl, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_seq, - (unsigned long long) dp->dccps_swh, - (DCCP_SKB_CB(skb)->dccpd_ack_seq == + DCCP_WARN("DCCP: Step 6 failed for %s packet, " + "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " + "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " + "sending SYNC...\n", dccp_packet_name(dh->dccph_type), + (unsigned long long) lswl, + (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq, + (unsigned long long) dp->dccps_swh, + (DCCP_SKB_CB(skb)->dccpd_ack_seq == DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists", - (unsigned long long) lawl, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_ack_seq, - (unsigned long long) dp->dccps_awh); + (unsigned long long) lawl, + (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq, + (unsigned long long) dp->dccps_awh); dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); return -1; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 7114befe7d50..ff81679c9f17 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -747,7 +747,7 @@ int dccp_invalid_packet(struct sk_buff *skb) /* If the packet is shorter than 12 bytes, drop packet and return */ if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n"); + DCCP_WARN("pskb_may_pull failed\n"); return 1; } @@ -755,7 +755,7 @@ int dccp_invalid_packet(struct sk_buff *skb) /* If P.type is not understood, drop packet and return */ if (dh->dccph_type >= DCCP_PKT_INVALID) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n"); + DCCP_WARN("invalid packet type\n"); return 1; } @@ -763,16 +763,14 @@ int dccp_invalid_packet(struct sk_buff *skb) * If P.Data Offset is too small for packet type, drop packet and return */ if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " - "too small\n", dh->dccph_doff); + DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff); return 1; } /* * If P.Data Offset is too too large for packet, drop packet and return */ if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " - "too large\n", dh->dccph_doff); + DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff); return 1; } @@ -782,9 +780,8 @@ int dccp_invalid_packet(struct sk_buff *skb) */ if (dh->dccph_type >= DCCP_PKT_DATA && dh->dccph_type <= DCCP_PKT_DATAACK && dh->dccph_x == 0) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data||Ack||" - "DataAck, while P.X == 0\n", - dccp_packet_name(dh->dccph_type)); + DCCP_WARN("P.type (%s) not Data || [Data]Ack, while P.X == 0\n", + dccp_packet_name(dh->dccph_type)); return 1; } @@ -794,9 +791,8 @@ int dccp_invalid_packet(struct sk_buff *skb) */ cscov = dccp_csum_coverage(skb); if (cscov > skb->len) { - LIMIT_NETDEBUG(KERN_WARNING - "DCCP: P.CsCov %u exceeds packet length %d\n", - dh->dccph_cscov, skb->len); + DCCP_WARN("P.CsCov %u exceeds packet length %d\n", + dh->dccph_cscov, skb->len); return 1; } @@ -823,9 +819,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) /* Step 1: If header checksum is incorrect, drop packet and return */ if (dccp_v4_csum_finish(skb, skb->nh.iph->saddr, skb->nh.iph->daddr)) { - LIMIT_NETDEBUG(KERN_WARNING - "%s: dropped packet with invalid checksum\n", - __FUNCTION__); + DCCP_WARN("dropped packet with invalid checksum\n"); goto discard_it; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 03bb8298250a..c7aaa2574f52 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -828,9 +828,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb) /* Step 1: If header checksum is incorrect, drop packet and return. */ if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr)) { - LIMIT_NETDEBUG(KERN_WARNING - "%s: dropped packet with invalid checksum\n", - __FUNCTION__); + DCCP_WARN("dropped packet with invalid checksum\n"); goto discard_it; } diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 3975048d8094..7b52f2a03eef 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -84,8 +84,7 @@ void dccp_time_wait(struct sock *sk, int state, int timeo) * socket up. We've got bigger problems than * non-graceful socket closings. */ - LIMIT_NETDEBUG(KERN_INFO "DCCP: time wait bucket " - "table overflow\n"); + DCCP_WARN("time wait bucket table overflow\n"); } dccp_done(sk); @@ -289,9 +288,7 @@ EXPORT_SYMBOL_GPL(dccp_child_process); void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk) { - pr_info(KERN_WARNING "DCCP: ACK packets are never sent in " - "LISTEN/RESPOND state\n"); - dump_stack(); + DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state"); } EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); diff --git a/net/dccp/options.c b/net/dccp/options.c index 7e50678e2471..ee709ae0a97f 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -238,9 +238,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) } break; default: - pr_info("DCCP(%p): option %d(len=%d) not " - "implemented, ignoring\n", - sk, opt, len); + DCCP_CRIT("DCCP(%p): option %d(len=%d) not " + "implemented, ignoring", sk, opt, len); break; } @@ -257,7 +256,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) out_invalid_option: DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR; - pr_info("DCCP(%p): invalid option %d, len=%d\n", sk, opt, len); + DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len); return -1; } @@ -447,8 +446,7 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, u8 *to; if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small" - " to insert feature %d option!\n", feat); + DCCP_WARN("packet too small for feature %d option!\n", feat); return -1; } diff --git a/net/dccp/output.c b/net/dccp/output.c index c34eada7f025..bfd9c5757897 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -257,11 +257,8 @@ void dccp_write_xmit(struct sock *sk, int block) err = dccp_wait_for_ccid(sk, skb, &timeo); timeo = DCCP_XMIT_TIMEO; } - if (err) { - printk(KERN_CRIT "%s:err at dccp_wait_for_ccid" - " %d\n", __FUNCTION__, err); - dump_stack(); - } + if (err) + DCCP_BUG("err=%d after dccp_wait_for_ccid", err); } skb_dequeue(&sk->sk_write_queue); @@ -283,12 +280,9 @@ void dccp_write_xmit(struct sock *sk, int block) err = dccp_transmit_skb(sk, skb); ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); - if (err) { - printk(KERN_CRIT "%s:err from " - "ccid_hc_tx_packet_sent %d\n", - __FUNCTION__, err); - dump_stack(); - } + if (err) + DCCP_BUG("err=%d after ccid_hc_tx_packet_sent", + err); } else kfree(skb); } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index a7f345c8d0db..3c44d502e5c1 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1033,8 +1033,7 @@ static int __init dccp_init(void) } while (!dccp_hashinfo.ehash && --ehash_order > 0); if (!dccp_hashinfo.ehash) { - printk(KERN_CRIT "Failed to allocate DCCP " - "established hash table\n"); + DCCP_CRIT("Failed to allocate DCCP established hash table"); goto out_free_bind_bucket_cachep; } @@ -1056,7 +1055,7 @@ static int __init dccp_init(void) } while (!dccp_hashinfo.bhash && --bhash_order >= 0); if (!dccp_hashinfo.bhash) { - printk(KERN_CRIT "Failed to allocate DCCP bind hash table\n"); + DCCP_CRIT("Failed to allocate DCCP bind hash table"); goto out_free_dccp_ehash; } -- cgit v1.2.3-70-g09d2 From 23ea8945f6be2287fec67c85abcf24736c1ded80 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:40:42 -0200 Subject: [CCID 3]: Add annotations for socket structures This adds documentation to the CCID 3 rx/tx socket fields, plus some minor re-formatting. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.h | 90 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 35 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index c122e757eb7f..e2e43c1a4726 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -81,26 +81,28 @@ enum ccid3_hc_tx_states { TFRC_SSTATE_TERM, }; -/** struct ccid3_hc_tx_sock - CCID3 sender half connection sock +/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket * - * @ccid3hctx_state - Sender state - * @ccid3hctx_x - Current sending rate - * @ccid3hctx_x_recv - Receive rate - * @ccid3hctx_x_calc - Calculated send (?) rate - * @ccid3hctx_s - Packet size - * @ccid3hctx_rtt - Estimate of current round trip time in usecs - * @@ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 - * @ccid3hctx_last_win_count - Last window counter sent - * @ccid3hctx_t_last_win_count - Timestamp of earliest packet - * with last_win_count value sent - * @ccid3hctx_no_feedback_timer - Handle to no feedback timer - * @ccid3hctx_idle - FIXME - * @ccid3hctx_t_ld - Time last doubled during slow start - * @ccid3hctx_t_nom - Nominal send time of next packet - * @ccid3hctx_t_ipi - Interpacket (send) interval - * @ccid3hctx_delta - Send timer delta - * @ccid3hctx_hist - Packet history - */ + * @ccid3hctx_x - Current sending rate + * @ccid3hctx_x_recv - Receive rate + * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1) + * @ccid3hctx_rtt - Estimate of current round trip time in usecs + * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 + * @ccid3hctx_s - Packet size + * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1) + * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) + * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states + * @ccid3hctx_last_win_count - Last window counter sent + * @ccid3hctx_t_last_win_count - Timestamp of earliest packet + * with last_win_count value sent + * @ccid3hctx_no_feedback_timer - Handle to no feedback timer + * @ccid3hctx_idle - Flag indicating that sender is idling + * @ccid3hctx_t_ld - Time last doubled during slow start + * @ccid3hctx_t_nom - Nominal send time of next packet + * @ccid3hctx_delta - Send timer delta + * @ccid3hctx_hist - Packet history + * @ccid3hctx_options_received - Parsed set of retrieved options + */ struct ccid3_hc_tx_sock { struct tfrc_tx_info ccid3hctx_tfrc; #define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x @@ -130,23 +132,41 @@ enum ccid3_hc_rx_states { TFRC_RSTATE_TERM = 127, }; +/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket + * + * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3) + * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) + * @ccid3hcrx_p - current loss event rate (RFC 3448 5.4) + * @ccid3hcrx_seqno_nonloss - Last received non-loss sequence number + * @ccid3hcrx_ccval_nonloss - Last received non-loss Window CCVal + * @ccid3hcrx_ccval_last_counter - Tracks window counter (RFC 4342, 8.1) + * @ccid3hcrx_state - receiver state, one of %ccid3_hc_rx_states + * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes + * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent + * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent + * @ccid3hcrx_hist - Packet history + * @ccid3hcrx_li_hist - Loss Interval History + * @ccid3hcrx_s - Received packet size in bytes + * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) + * @ccid3hcrx_elapsed_time - Time since packet reception + */ struct ccid3_hc_rx_sock { - struct tfrc_rx_info ccid3hcrx_tfrc; -#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv -#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt -#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p - u64 ccid3hcrx_seqno_nonloss:48, - ccid3hcrx_ccval_nonloss:4, - ccid3hcrx_ccval_last_counter:4; - enum ccid3_hc_rx_states ccid3hcrx_state:8; - u32 ccid3hcrx_bytes_recv; - struct timeval ccid3hcrx_tstamp_last_feedback; - struct timeval ccid3hcrx_tstamp_last_ack; - struct list_head ccid3hcrx_hist; - struct list_head ccid3hcrx_li_hist; - u16 ccid3hcrx_s; - u32 ccid3hcrx_pinv; - u32 ccid3hcrx_elapsed_time; + struct tfrc_rx_info ccid3hcrx_tfrc; +#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv +#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt +#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p + u64 ccid3hcrx_seqno_nonloss:48, + ccid3hcrx_ccval_nonloss:4, + ccid3hcrx_ccval_last_counter:4; + enum ccid3_hc_rx_states ccid3hcrx_state:8; + u32 ccid3hcrx_bytes_recv; + struct timeval ccid3hcrx_tstamp_last_feedback; + struct timeval ccid3hcrx_tstamp_last_ack; + struct list_head ccid3hcrx_hist; + struct list_head ccid3hcrx_li_hist; + u16 ccid3hcrx_s; + u32 ccid3hcrx_pinv; + u32 ccid3hcrx_elapsed_time; }; static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) -- cgit v1.2.3-70-g09d2 From e1b7441e803442828780a6d6d792643f79d5665b Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Nov 2006 18:41:37 -0200 Subject: [DCCP]: Make dccp_probe more portable This makes the code of the dccp_probe module more portable. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/probe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/dccp/probe.c b/net/dccp/probe.c index fded1493c1dc..f81e37de35d5 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -106,8 +106,10 @@ static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk, } static struct jprobe dccp_send_probe = { - .kp = { .addr = (kprobe_opcode_t *)&dccp_sendmsg, }, - .entry = (kprobe_opcode_t *)&jdccp_sendmsg, + .kp = { + .symbol_name = "dccp_sendmsg", + }, + .entry = JPROBE_ENTRY(jdccp_sendmsg), }; static int dccpprobe_open(struct inode *inode, struct file *file) -- cgit v1.2.3-70-g09d2 From 455431739ca2f4c7f02d0a5979559ac5a68a6f95 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Nov 2006 18:44:03 -0200 Subject: [DCCP] CCID3: Remove non-referenced variable This removes a non-referenced variable. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 4eada515b773..fb21f2d9ffc6 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -965,7 +965,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) const struct dccp_options_received *opt_recv; struct dccp_rx_hist_entry *packet; struct timeval now; - u8 win_count; u32 p_prev, rtt_prev, r_sample, t_elapsed; int loss; @@ -1017,8 +1016,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) return; } - win_count = packet->dccphrx_ccval; - loss = ccid3_hc_rx_detect_loss(sk, packet); if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) -- cgit v1.2.3-70-g09d2 From 82e3ab9dbeebd5c8d5402ad1607d22086271a56d Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Nov 2006 19:19:32 -0200 Subject: [DCCP]: Adds the tx buffer sysctls This one got lost on the way from Ian to Gerrit to me, fix it. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/networking/dccp.txt | 4 ++++ include/linux/sysctl.h | 1 + net/dccp/sysctl.c | 9 +++++++++ 3 files changed, 14 insertions(+) (limited to 'net') diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index 1910d097a0ad..dda15886bcb5 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -100,6 +100,10 @@ rx_ccid = 2 seq_window = 100 The initial sequence window (sec. 7.5.2). +tx_qlen = 5 + The size of the transmit buffer in packets. A value of 0 corresponds + to an unbounded transmit buffer. + Notes ===== diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 2e8c5ad82793..61dd99c6c2a5 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -617,6 +617,7 @@ enum { NET_DCCP_DEFAULT_REQ_RETRIES = 7, NET_DCCP_DEFAULT_RETRIES1 = 8, NET_DCCP_DEFAULT_RETRIES2 = 9, + NET_DCCP_DEFAULT_TX_QLEN = 10, }; /* /proc/sys/net/ipx */ diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 8b62061e5701..4775ba3faa04 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -91,6 +91,15 @@ static struct ctl_table dccp_default_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .ctl_name = NET_DCCP_DEFAULT_TX_QLEN, + .procname = "tx_qlen", + .data = &sysctl_dccp_tx_qlen, + .maxlen = sizeof(sysctl_dccp_tx_qlen), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { .ctl_name = 0, } }; -- cgit v1.2.3-70-g09d2 From 746859625d879688adb99f1e5e8108fea876d369 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 20 Nov 2006 16:20:22 -0800 Subject: [BRIDGE] netlink: Convert bridge netlink code to new netlink interface Removes dependency on buggy rta_buf, fixes a memory corruption bug due to a unvalidated netlink attribute, and simplifies the code. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/bridge/br_netlink.c | 92 ++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 54 deletions(-) (limited to 'net') diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 15d6efbe7519..a9139682c49b 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -36,51 +36,43 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por { const struct net_bridge *br = port->br; const struct net_device *dev = port->dev; - struct ifinfomsg *r; + struct ifinfomsg *hdr; struct nlmsghdr *nlh; - unsigned char *b = skb->tail; - u32 mtu = dev->mtu; u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; - u8 portstate = port->state; pr_debug("br_fill_info event %d port %s master %s\n", event, dev->name, br->dev->name); - nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); - r = NLMSG_DATA(nlh); - r->ifi_family = AF_BRIDGE; - r->__ifi_pad = 0; - r->ifi_type = dev->type; - r->ifi_index = dev->ifindex; - r->ifi_flags = dev_get_flags(dev); - r->ifi_change = 0; + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); + if (nlh == NULL) + return -ENOBUFS; - RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); + hdr = nlmsg_data(nlh); + hdr->ifi_family = AF_BRIDGE; + hdr->__ifi_pad = 0; + hdr->ifi_type = dev->type; + hdr->ifi_index = dev->ifindex; + hdr->ifi_flags = dev_get_flags(dev); + hdr->ifi_change = 0; - RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex); + NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); + NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex); + NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); + NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate); if (dev->addr_len) - RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); + NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); if (dev->ifindex != dev->iflink) - RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); - - - RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); + NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); if (event == RTM_NEWLINK) - RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate); - - nlh->nlmsg_len = skb->tail - b; + NLA_PUT_U8(skb, IFLA_PROTINFO, port->state); - return skb->len; - -nlmsg_failure: -rtattr_failure: + return nlmsg_end(skb, nlh); - skb_trim(skb, b - skb->data); - return -EINVAL; +nla_put_failure: + return nlmsg_cancel(skb, nlh); } /* @@ -113,25 +105,18 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { struct net_device *dev; int idx; - int s_idx = cb->args[0]; - int err = 0; read_lock(&dev_base_lock); for (dev = dev_base, idx = 0; dev; dev = dev->next) { - struct net_bridge_port *p = dev->br_port; - /* not a bridge port */ - if (!p) - continue; + if (dev->br_port == NULL || idx < cb->args[0]) + goto skip; - if (idx < s_idx) - goto cont; - - err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI); - if (err <= 0) + if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, RTM_NEWLINK, + NLM_F_MULTI) < 0) break; -cont: +skip: ++idx; } read_unlock(&dev_base_lock); @@ -147,26 +132,27 @@ cont: */ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct rtattr **rta = arg; - struct ifinfomsg *ifm = NLMSG_DATA(nlh); + struct ifinfomsg *ifm; + struct nlattr *protinfo; struct net_device *dev; struct net_bridge_port *p; u8 new_state; + if (nlmsg_len(nlh) < sizeof(*ifm)) + return -EINVAL; + + ifm = nlmsg_data(nlh); if (ifm->ifi_family != AF_BRIDGE) return -EPFNOSUPPORT; - /* Must pass valid state as PROTINFO */ - if (rta[IFLA_PROTINFO-1]) { - u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]); - new_state = *pstate; - } else + protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); + if (!protinfo || nla_len(protinfo) < sizeof(u8)) return -EINVAL; + new_state = nla_get_u8(protinfo); if (new_state > BR_STATE_BLOCKING) return -EINVAL; - /* Find bridge port */ dev = __dev_get_by_index(ifm->ifi_index); if (!dev) return -ENODEV; @@ -179,10 +165,8 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (p->br->stp_enabled) return -EBUSY; - if (!netif_running(dev)) - return -ENETDOWN; - - if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED) + if (!netif_running(dev) || + (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)) return -ENETDOWN; p->state = new_state; -- cgit v1.2.3-70-g09d2 From 1459bb36b12ac52bde68d70e2ba7a6f1f2e8be17 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Nov 2006 16:51:22 -0800 Subject: [XFRM]: Make copy_to_user_policy_type take a type Make copy_to_user_policy_type take a type instead a policy and fix its users to pass the type Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2ee14f8a1908..6ddb49367c13 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1083,12 +1083,12 @@ static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *s } #ifdef CONFIG_XFRM_SUB_POLICY -static int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) +static int copy_to_user_policy_type(__u8 type, struct sk_buff *skb) { struct xfrm_userpolicy_type upt; memset(&upt, 0, sizeof(upt)); - upt.type = xp->type; + upt.type = type; RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); @@ -1099,7 +1099,7 @@ rtattr_failure: } #else -static inline int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) +static inline int copy_to_user_policy_type(__u8 type, struct sk_buff *skb) { return 0; } @@ -1128,7 +1128,7 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr goto nlmsg_failure; if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) + if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; @@ -1908,7 +1908,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, goto nlmsg_failure; if (copy_to_user_state_sec_ctx(x, skb)) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) + if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; @@ -2018,7 +2018,7 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, goto nlmsg_failure; if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) + if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; upe->hard = !!hard; @@ -2097,7 +2097,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * copy_to_user_policy(xp, p, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) + if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; -- cgit v1.2.3-70-g09d2 From 89c89458152c4d387eeca6532b6e50780fc59f8b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 16:56:48 -0800 Subject: [IPV6] net/ipv6/sit.c: make 2 functions static This patch makes two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- include/net/ipip.h | 4 ---- net/ipv6/sit.c | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/net/ipip.h b/include/net/ipip.h index 84058858eea7..7cdc914322f0 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -44,8 +44,4 @@ struct ip_tunnel } \ } while (0) - -extern int sit_init(void); -extern void sit_cleanup(void); - #endif diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 85ff3dc45148..77b7b0911438 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -809,7 +809,7 @@ static void __exit sit_destroy_tunnels(void) } } -void __exit sit_cleanup(void) +static void __exit sit_cleanup(void) { inet_del_protocol(&sit_protocol, IPPROTO_IPV6); @@ -819,7 +819,7 @@ void __exit sit_cleanup(void) rtnl_unlock(); } -int __init sit_init(void) +static int __init sit_init(void) { int err; -- cgit v1.2.3-70-g09d2 From 5bf2db03908b9121805af3c76e3ac2d0759e199f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 16:59:45 -0800 Subject: [SCTP]: Annotate sctp_init_cause(). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 2 +- net/sctp/sm_make_chunk.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index de313de4fefe..a3b0e1e896f0 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -213,7 +213,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, const struct sctp_chunk *); struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, const struct sctp_chunk *); -void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t); +void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t); struct sctp_chunk *sctp_make_abort(const struct sctp_association *, const struct sctp_chunk *, const size_t hint); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 507dff72c585..37472be16014 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -111,7 +111,7 @@ static const struct sctp_paramhdr prsctp_param = { * provided chunk, as most cause codes will be embedded inside an * abort chunk. */ -void sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code, +void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, const void *payload, size_t paylen) { sctp_errhdr_t err; -- cgit v1.2.3-70-g09d2 From 63706c5c6fd07f58bed85d0aa031ffbce3a0385f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:00:05 -0800 Subject: [SCTP]: sctp_make_op_error() annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 2 +- net/sctp/sm_make_chunk.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index a3b0e1e896f0..a7b935a76a62 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -236,7 +236,7 @@ struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *, const size_t paylen); struct sctp_chunk *sctp_make_op_error(const struct sctp_association *, const struct sctp_chunk *chunk, - __u16 cause_code, + __be16 cause_code, const void *payload, size_t paylen); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 37472be16014..a3bde93bd8a3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -951,7 +951,7 @@ nodata: /* Create an Operation Error chunk. */ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, const struct sctp_chunk *chunk, - __u16 cause_code, const void *payload, + __be16 cause_code, const void *payload, size_t paylen) { struct sctp_chunk *retval; -- cgit v1.2.3-70-g09d2 From f94c0198dd98c2ca66a7a44e9ad310a3eb21ad31 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:00:25 -0800 Subject: [SCTP]: sctp_stop_t1_and_abort() annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 1c42fe983a5b..b9063ed2a659 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, - __u16 error, int sk_err, + __be16 error, int sk_err, const struct sctp_association *asoc, struct sctp_transport *transport); @@ -443,7 +443,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, __u32 init_tag; struct sctp_chunk *err_chunk; struct sctp_packet *packet; - __u16 error; + sctp_error_t error; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -2295,7 +2295,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, { struct sctp_chunk *chunk = arg; unsigned len; - __u16 error = SCTP_ERROR_NO_ERROR; + __be16 error = SCTP_ERROR_NO_ERROR; if (!sctp_vtag_verify_either(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -2357,7 +2357,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, * This is common code called by several sctp_sf_*_abort() functions above. */ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, - __u16 error, int sk_err, + __be16 error, int sk_err, const struct sctp_association *asoc, struct sctp_transport *transport) { -- cgit v1.2.3-70-g09d2 From dc251b2b1c4bfea51903cb9fbc141a5b33f6aca7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:00:44 -0800 Subject: [SCTP]: SCTP_CMD_INIT_FAILED annotations. argument stored for SCTP_CMD_INIT_FAILED is always __be16 (protocol error). Introduced new field and accessor for it (SCTP_PERR()); switched to their use (from SCTP_U32() and .u32) Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/command.h | 2 ++ net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 807d6f1ef4b5..dfe5d44b61ab 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -119,6 +119,7 @@ typedef union { __u16 u16; __u8 u8; int error; + __be16 err; sctp_state_t state; sctp_event_timeout_t to; unsigned long zero; @@ -167,6 +168,7 @@ SCTP_ARG_CONSTRUCTOR(U32, __u32, u32) SCTP_ARG_CONSTRUCTOR(U16, __u16, u16) SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) SCTP_ARG_CONSTRUCTOR(ERROR, int, error) +SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */ SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 9c10bdec1afe..e4c43a3438db 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1360,7 +1360,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; case SCTP_CMD_INIT_FAILED: - sctp_cmd_init_failed(commands, asoc, cmd->obj.u32); + sctp_cmd_init_failed(commands, asoc, cmd->obj.err); break; case SCTP_CMD_ASSOC_FAILED: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b9063ed2a659..f462a227c7ae 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2138,7 +2138,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(SCTP_ERROR_STALE_COOKIE)); + SCTP_PERR(SCTP_ERROR_STALE_COOKIE)); return SCTP_DISPOSITION_DELETE_TCB; } @@ -2370,7 +2370,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); /* CMD_INIT_FAILED will DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(error)); + SCTP_PERR(error)); return SCTP_DISPOSITION_ABORT; } @@ -3743,7 +3743,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNREFUSED)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); + SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); } else { sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); @@ -4199,7 +4199,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( SCTP_ERROR(ECONNREFUSED)); /* Delete the established association. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(SCTP_ERROR_USER_ABORT)); + SCTP_PERR(SCTP_ERROR_USER_ABORT)); return retval; } @@ -4693,7 +4693,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); return SCTP_DISPOSITION_DELETE_TCB; } @@ -4745,7 +4745,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); return SCTP_DISPOSITION_DELETE_TCB; } -- cgit v1.2.3-70-g09d2 From 5be291fe2d0d76681190589f6480ce1e28c2406b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:01:06 -0800 Subject: [SCTP]: SCTP_CMD_ASSOC_FAILED annotations. also always get __be16 protocol error; switch to SCTP_PERR() Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e4c43a3438db..2423b8ef9ce0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1365,7 +1365,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_ASSOC_FAILED: sctp_cmd_assoc_failed(commands, asoc, event_type, - subtype, chunk, cmd->obj.u32); + subtype, chunk, cmd->obj.err); break; case SCTP_CMD_INIT_COUNTER_INC: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f462a227c7ae..b70e3258b6d3 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -886,7 +886,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, SCTP_ERROR(ETIMEDOUT)); /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_DELETE_TCB; @@ -2250,7 +2250,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, { struct sctp_chunk *chunk = arg; unsigned len; - __u16 error = SCTP_ERROR_NO_ERROR; + __be16 error = SCTP_ERROR_NO_ERROR; if (!sctp_vtag_verify_either(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -2275,7 +2275,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); /* ASSOC_FAILED will DELETE_TCB. */ - sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); @@ -3360,7 +3360,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_ASCONF_ACK)); + SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_ABORT; @@ -3388,7 +3388,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_ASCONF_ACK)); + SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_ABORT; @@ -3748,7 +3748,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); + SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); } @@ -4062,7 +4062,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( SCTP_ERROR(ECONNABORTED)); /* Delete the established association. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_USER_ABORT)); + SCTP_PERR(SCTP_ERROR_USER_ABORT)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); @@ -4571,7 +4571,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, SCTP_ERROR(ETIMEDOUT)); /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_DELETE_TCB; @@ -4781,7 +4781,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, SCTP_ERROR(ETIMEDOUT)); /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_DELETE_TCB; @@ -4859,7 +4859,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire( sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_INC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_ABORT; @@ -4915,7 +4915,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_ERROR)); + SCTP_PERR(SCTP_ERROR_NO_ERROR)); return SCTP_DISPOSITION_DELETE_TCB; nomem: @@ -5365,7 +5365,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_DATA)); + SCTP_PERR(SCTP_ERROR_NO_DATA)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_IERROR_NO_DATA; -- cgit v1.2.3-70-g09d2 From dbc16db1e58da6c346ca3e63870c17b93fbed0f0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:01:42 -0800 Subject: [SCTP]: Trivial sctp endianness annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/constants.h | 2 +- include/net/sctp/sctp.h | 2 +- include/net/sctp/sm.h | 2 +- include/net/sctp/structs.h | 2 +- net/sctp/associola.c | 2 +- net/sctp/ipv6.c | 4 ++-- net/sctp/protocol.c | 2 +- net/sctp/sm_make_chunk.c | 18 +++++++++--------- 8 files changed, 17 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 6c632e26f72d..5ddb85599863 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -356,7 +356,7 @@ typedef enum { * addresses. */ #define IS_IPV4_UNUSABLE_ADDRESS(a) \ - ((INADDR_BROADCAST == *a) || \ + ((htonl(INADDR_BROADCAST) == *a) || \ (MULTICAST(*a)) || \ (((unsigned char *)(a))[0] == 0) || \ ((((unsigned char *)(a))[0] == 198) && \ diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 764e3af5be93..215461f18db1 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -585,7 +585,7 @@ static inline int ipver2af(__u8 ipver) } /* Convert from an address parameter type to an address family. */ -static inline int param_type2af(__u16 type) +static inline int param_type2af(__be16 type) { switch (type) { case SCTP_PARAM_IPV4_ADDRESS: diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index a7b935a76a62..3269ed1cc222 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -243,7 +243,7 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *, struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, union sctp_addr *, struct sockaddr *, - int, __u16); + int, __be16); struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, union sctp_addr *addr); struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 5596f5d97ed2..ca77bc5b7ff5 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1482,7 +1482,7 @@ struct sctp_association { /* This mask is used to disable sending the ASCONF chunk * with specified parameter to peer. */ - __u16 addip_disabled_mask; + __be16 addip_disabled_mask; struct sctp_inithdr i; int cookie_len; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ed0445fe85e7..a5d7abba89e4 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -868,7 +868,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, struct list_head *entry, *pos; struct sctp_transport *transport; struct sctp_chunk *chunk; - __u32 key = htonl(tsn); + __be32 key = htonl(tsn); match = NULL; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3c316c688ade..1f9f5ec07595 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -239,7 +239,7 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, int i, j; for (i = 0; i < 4 ; i++) { - __u32 a1xora2; + __be32 a1xora2; a1xora2 = a1->s6_addr32[i] ^ a2->s6_addr32[i]; @@ -425,7 +425,7 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, int length = sizeof(sctp_ipv6addr_param_t); param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; - param->v6.param_hdr.length = ntohs(length); + param->v6.param_hdr.length = htons(length); ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); return length; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index c107d45f6e65..4310e7fac443 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -307,7 +307,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, int length = sizeof(sctp_ipv4addr_param_t); param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; - param->v4.param_hdr.length = ntohs(length); + param->v4.param_hdr.length = htons(length); param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; return length; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index a3bde93bd8a3..ccbba6b24d1d 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1190,7 +1190,7 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { ssn = 0; } else { - sid = htons(chunk->subh.data_hdr->stream); + sid = ntohs(chunk->subh.data_hdr->stream); if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG) ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid); else @@ -2230,7 +2230,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc, union sctp_addr *laddr, struct sockaddr *addrs, int addrcnt, - __u16 flags) + __be16 flags) { sctp_addip_param_t param; struct sctp_chunk *retval; @@ -2364,13 +2364,13 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as /* Add response parameters to an ASCONF_ACK chunk. */ static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id, - __u16 err_code, sctp_addip_param_t *asconf_param) + __be16 err_code, sctp_addip_param_t *asconf_param) { sctp_addip_param_t ack_param; sctp_errhdr_t err_param; int asconf_param_len = 0; int err_param_len = 0; - __u16 response_type; + __be16 response_type; if (SCTP_ERROR_NO_ERROR == err_code) { response_type = SCTP_PARAM_SUCCESS_REPORT; @@ -2404,7 +2404,7 @@ static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id, } /* Process a asconf parameter. */ -static __u16 sctp_process_asconf_param(struct sctp_association *asoc, +static __be16 sctp_process_asconf_param(struct sctp_association *asoc, struct sctp_chunk *asconf, sctp_addip_param_t *asconf_param) { @@ -2487,7 +2487,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, sctp_addip_param_t *asconf_param; struct sctp_chunk *asconf_ack; - __u16 err_code; + __be16 err_code; int length = 0; int chunk_len = asconf->skb->len; __u32 serial; @@ -2630,7 +2630,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, * All TLVs after the failed response are considered unsuccessful unless a * specific success indication is present for the parameter. */ -static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, +static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, sctp_addip_param_t *asconf_param, int no_err) { @@ -2638,7 +2638,7 @@ static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, sctp_errhdr_t *err_param; int length; int asconf_ack_len = asconf_ack->skb->len; - __u16 err_code; + __be16 err_code; if (no_err) err_code = SCTP_ERROR_NO_ERROR; @@ -2694,7 +2694,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, int all_param_pass = 0; int no_err = 1; int retval = 0; - __u16 err_code = SCTP_ERROR_NO_ERROR; + __be16 err_code = SCTP_ERROR_NO_ERROR; /* Skip the chunkhdr and addiphdr from the last asconf sent and store * a pointer to address parameter. -- cgit v1.2.3-70-g09d2 From 04afd8b282d702bc122051751466000e9513ef96 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:02:01 -0800 Subject: [SCTP]: Beginning of sin_port fixes. That's going to be a long series. Introduced temporary helpers doing copy-and-convert for sctp_addr; they are used to kill flip-in-place in global data structures and will be used to gradually push host-endian uses of sctp_addr out of existence. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 22 ++++++++++++++++++++++ net/sctp/socket.c | 29 ++++++++++++----------------- 2 files changed, 34 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index ca77bc5b7ff5..2aa61ac9a9f3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -74,6 +74,28 @@ union sctp_addr { struct sockaddr sa; }; +static inline void flip_to_n(union sctp_addr *to, const union sctp_addr *from) +{ + size_t len; + if (from->sa.sa_family == AF_INET6) + len = sizeof(struct sockaddr_in6); + else + len = sizeof(struct sockaddr); + memcpy(to, from, len); + to->v4.sin_port = htons(from->v4.sin_port); +} + +static inline void flip_to_h(union sctp_addr *to, const union sctp_addr *from) +{ + size_t len; + if (from->sa.sa_family == AF_INET6) + len = sizeof(struct sockaddr_in6); + else + len = sizeof(struct sockaddr); + memcpy(to, from, len); + to->v4.sin_port = ntohs(from->v4.sin_port); +} + /* Forward declarations for data structures. */ struct sctp_globals; struct sctp_endpoint; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 935bc9187fd8..f4d13ab79f49 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -228,12 +228,12 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; struct sctp_transport *transport; union sctp_addr *laddr = (union sctp_addr *)addr; + union sctp_addr tmp; - laddr->v4.sin_port = ntohs(laddr->v4.sin_port); + flip_to_h(&tmp, laddr); addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, - (union sctp_addr *)addr, + &tmp, &transport); - laddr->v4.sin_port = htons(laddr->v4.sin_port); if (!addr_asoc) return NULL; @@ -313,6 +313,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) struct sctp_af *af; unsigned short snum; int ret = 0; + union sctp_addr tmp; /* Common sockaddr verification. */ af = sctp_sockaddr_af(sp, addr, len); @@ -368,9 +369,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) sctp_write_lock(&ep->base.addr_lock); /* Use GFP_ATOMIC since BHs are disabled. */ - addr->v4.sin_port = ntohs(addr->v4.sin_port); - ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); - addr->v4.sin_port = htons(addr->v4.sin_port); + flip_to_h(&tmp, addr); + ret = sctp_add_bind_addr(bp, &tmp, 1, GFP_ATOMIC); sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); @@ -4194,12 +4194,8 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, if (!asoc->peer.primary_path) return -ENOTCONN; - asoc->peer.primary_path->ipaddr.v4.sin_port = - htons(asoc->peer.primary_path->ipaddr.v4.sin_port); - memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, - sizeof(union sctp_addr)); - asoc->peer.primary_path->ipaddr.v4.sin_port = - ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port); + flip_to_n((union sctp_addr *)&prim.ssp_addr, + &asoc->peer.primary_path->ipaddr); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, (union sctp_addr *)&prim.ssp_addr); @@ -4642,12 +4638,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) { struct sctp_bind_hashbucket *head; /* hash list */ struct sctp_bind_bucket *pp; /* hash list port iterator */ + union sctp_addr tmp; unsigned short snum; int ret; - /* NOTE: Remember to put this back to net order. */ - addr->v4.sin_port = ntohs(addr->v4.sin_port); - snum = addr->v4.sin_port; + flip_to_h(&tmp, addr); + snum = ntohs(addr->v4.sin_port); SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum); sctp_local_bh_disable(); @@ -4744,7 +4740,7 @@ pp_found: if (reuse && sk2->sk_reuse) continue; - if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, + if (sctp_bind_addr_match(&ep2->base.bind_addr, &tmp, sctp_sk(sk))) { ret = (long)sk2; goto fail_unlock; @@ -4784,7 +4780,6 @@ fail_unlock: fail: sctp_local_bh_enable(); - addr->v4.sin_port = htons(addr->v4.sin_port); return ret; } -- cgit v1.2.3-70-g09d2 From 39940a48c42441da5e7428483ac515e822d52b1d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:02:22 -0800 Subject: [SCTP] bug: sctp_assoc_lookup_laddr() is broken with ipv6. It expects (and gets) laddr with net-endian sin_port. And then it calls sctp_bind_addr_match(), which *does* care about port numbers in case of ipv6 and expects them to be host-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a5d7abba89e4..7639044b0074 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1335,10 +1335,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, const union sctp_addr *laddr) { int found; + union sctp_addr tmp; + flip_to_h(&tmp, laddr); sctp_read_lock(&asoc->base.addr_lock); if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && - sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_bind_addr_match(&asoc->base.bind_addr, &tmp, sctp_sk(asoc->base.sk))) { found = 1; goto out; -- cgit v1.2.3-70-g09d2 From d5c747f6efc03495635f129c8eb1dad0200ab183 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:02:40 -0800 Subject: [SCTP] bug: sctp_find_unmatch_addr() compares net-endian to host-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 2b9c12a170e5..23b5b664a8a0 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -332,12 +332,14 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, addr_buf = (union sctp_addr *)addrs; for (i = 0; i < addrcnt; i++) { + union sctp_addr tmp; addr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(addr->v4.sin_family); if (!af) return NULL; + flip_to_h(&tmp, addr); - if (opt->pf->cmp_addr(&laddr->a, addr, opt)) + if (opt->pf->cmp_addr(&laddr->a, &tmp, opt)) break; addr_buf += af->sockaddr_len; -- cgit v1.2.3-70-g09d2 From 0906e20fa03afdb14faf7fd166bfe4ed67c8db55 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:03:01 -0800 Subject: [SCTP] bug: sctp_assoc_control_transport() breakage a) struct sockaddr_storage * passed to sctp_ulpevent_make_peer_addr_change() actually points at union sctp_addr field in a structure. Then that sucker gets copied to userland, with whatever junk we might have there. b) it's actually having host-endian sin_port. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 7639044b0074..746b0b0f5ace 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -709,6 +709,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, struct sctp_transport *first; struct sctp_transport *second; struct sctp_ulpevent *event; + struct sockaddr_storage addr; struct list_head *pos; int spc_state = 0; @@ -731,8 +732,9 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the * user. */ - event = sctp_ulpevent_make_peer_addr_change(asoc, - (struct sockaddr_storage *) &transport->ipaddr, + memset(&addr, 0, sizeof(struct sockaddr_storage)); + flip_to_n((union sctp_addr *)&addr, &transport->ipaddr); + event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 0, spc_state, error, GFP_ATOMIC); if (event) sctp_ulpq_tail_event(&asoc->ulpq, event); -- cgit v1.2.3-70-g09d2 From 30330ee00ce077de9d459c17125573ff618bd7a9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:03:18 -0800 Subject: [SCTP] bug: endianness problem in sctp_getsockopt_sctp_status() Again, invalid sockaddr passed to userland - host-endiand sin_port. Potential leak, again, but less dramatic than in previous case. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f4d13ab79f49..b6e038a387c2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3217,8 +3217,8 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, status.sstat_outstrms = asoc->c.sinit_num_ostreams; status.sstat_fragmentation_point = asoc->frag_point; status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); - memcpy(&status.sstat_primary.spinfo_address, - &(transport->ipaddr), sizeof(union sctp_addr)); + flip_to_n((union sctp_addr *)&status.sstat_primary.spinfo_address, + &transport->ipaddr); /* Map ipv4 address into v4-mapped-on-v6 address. */ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), (union sctp_addr *)&status.sstat_primary.spinfo_address); -- cgit v1.2.3-70-g09d2 From 09ef7fecea40c5e4c0dfe35bed3f0ed8da554cf5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:04:10 -0800 Subject: [SCTP]: Beginning of conversion to net-endian for embedded sctp_addr. Part 1: rename sctp_chunk->source, sctp_sockaddr_entry->a, sctp_transport->ipaddr and sctp_transport->saddr (to ..._h) The next patch will reintroduce these fields and keep them as net-endian mirrors of the original (renamed) ones. Split in two patches to make sure that we hadn't forgotten any instanes. Later in the series we'll eliminate uses of host-endian variants (basically switching users to net-endian counterparts as we progress through that mess). Then host-endian ones will die. Other embedded host-endian sctp_addr will be easier to switch directly, so we leave them alone for now. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 8 ++++---- net/sctp/associola.c | 30 +++++++++++++++--------------- net/sctp/bind_addr.c | 22 +++++++++++----------- net/sctp/endpointola.c | 2 +- net/sctp/ipv6.c | 24 ++++++++++++------------ net/sctp/proc.c | 6 +++--- net/sctp/protocol.c | 20 ++++++++++---------- net/sctp/sm_make_chunk.c | 8 ++++---- net/sctp/sm_sideeffect.c | 8 ++++---- net/sctp/sm_statefuns.c | 8 ++++---- net/sctp/socket.c | 32 ++++++++++++++++---------------- net/sctp/transport.c | 14 +++++++------- 12 files changed, 91 insertions(+), 91 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 2aa61ac9a9f3..953a73f9689c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -713,7 +713,7 @@ struct sctp_chunk { unsigned long sent_at; /* What is the origin IP address for this chunk? */ - union sctp_addr source; + union sctp_addr source_h; /* Destination address for this chunk. */ union sctp_addr dest; @@ -756,7 +756,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk); /* This is a structure for holding either an IPv6 or an IPv4 address. */ struct sctp_sockaddr_entry { struct list_head list; - union sctp_addr a; + union sctp_addr a_h; __u8 use_as_src; }; @@ -842,7 +842,7 @@ struct sctp_transport { int dead; /* This is the peer's IP address and port. */ - union sctp_addr ipaddr; + union sctp_addr ipaddr_h; /* These are the functions we call to handle LLP stuff. */ struct sctp_af *af_specific; @@ -900,7 +900,7 @@ struct sctp_transport { /* Destination */ struct dst_entry *dst; /* Source address. */ - union sctp_addr saddr; + union sctp_addr saddr_h; /* When was the last time(in jiffies) that a data packet was sent on * this transport? This is used to adjust the cwnd when the transport diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 746b0b0f5ace..83318e727905 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -442,7 +442,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, asoc->peer.primary_path = transport; /* Set a default msg_name for events. */ - memcpy(&asoc->peer.primary_addr, &transport->ipaddr, + memcpy(&asoc->peer.primary_addr, &transport->ipaddr_h, sizeof(union sctp_addr)); /* If the primary path is changing, assume that the @@ -487,8 +487,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", " port: %d\n", asoc, - (&peer->ipaddr), - peer->ipaddr.v4.sin_port); + (&peer->ipaddr_h), + peer->ipaddr_h.v4.sin_port); /* If we are to remove the current retran_path, update it * to the next peer before removing this peer from the list. @@ -669,7 +669,7 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { + if (sctp_cmp_addr_exact(addr, &transport->ipaddr_h)) { /* Do book keeping for removing the peer and free it. */ sctp_assoc_rm_peer(asoc, transport); break; @@ -689,7 +689,7 @@ struct sctp_transport *sctp_assoc_lookup_paddr( list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(address, &t->ipaddr)) + if (sctp_cmp_addr_exact(address, &t->ipaddr_h)) return t; } @@ -733,7 +733,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, * user. */ memset(&addr, 0, sizeof(struct sockaddr_storage)); - flip_to_n((union sctp_addr *)&addr, &transport->ipaddr); + flip_to_n((union sctp_addr *)&addr, &transport->ipaddr_h); event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 0, spc_state, error, GFP_ATOMIC); if (event) @@ -1043,8 +1043,8 @@ void sctp_assoc_update(struct sctp_association *asoc, /* Remove any peer addresses not present in the new association. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { trans = list_entry(pos, struct sctp_transport, transports); - if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) - sctp_assoc_del_peer(asoc, &trans->ipaddr); + if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr_h)) + sctp_assoc_del_peer(asoc, &trans->ipaddr_h); } /* If the case is A (association restart), use @@ -1067,8 +1067,8 @@ void sctp_assoc_update(struct sctp_association *asoc, list_for_each(pos, &new->peer.transport_addr_list) { trans = list_entry(pos, struct sctp_transport, transports); - if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) - sctp_assoc_add_peer(asoc, &trans->ipaddr, + if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr_h)) + sctp_assoc_add_peer(asoc, &trans->ipaddr_h, GFP_ATOMIC, trans->state); } @@ -1136,8 +1136,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) " %p addr: ", " port: %d\n", asoc, - (&t->ipaddr), - t->ipaddr.v4.sin_port); + (&t->ipaddr_h), + t->ipaddr_h.v4.sin_port); } /* Choose the transport for sending a INIT packet. */ @@ -1161,8 +1161,8 @@ struct sctp_transport *sctp_assoc_choose_init_transport( " %p addr: ", " port: %d\n", asoc, - (&t->ipaddr), - t->ipaddr.v4.sin_port); + (&t->ipaddr_h), + t->ipaddr_h.v4.sin_port); return t; } @@ -1307,7 +1307,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, /* Use scoping rules to determine the subset of addresses from * the endpoint. */ - scope = sctp_scope(&asoc->peer.active_path->ipaddr); + scope = sctp_scope(&asoc->peer.active_path->ipaddr_h); flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; if (asoc->peer.ipv4_address) flags |= SCTP_ADDR4_PEERSUPP; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 23b5b664a8a0..b8115cb31ae3 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -77,7 +77,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, /* Extract the addresses which are relevant for this scope. */ list_for_each(pos, &src->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - error = sctp_copy_one_addr(dest, &addr->a, scope, + error = sctp_copy_one_addr(dest, &addr->a_h, scope, gfp, flags); if (error < 0) goto out; @@ -91,7 +91,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, list_for_each(pos, &src->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - error = sctp_copy_one_addr(dest, &addr->a, + error = sctp_copy_one_addr(dest, &addr->a_h, SCTP_SCOPE_LINK, gfp, flags); if (error < 0) @@ -155,13 +155,13 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, if (!addr) return -ENOMEM; - memcpy(&addr->a, new, sizeof(*new)); + memcpy(&addr->a_h, new, sizeof(*new)); /* Fix up the port if it has not yet been set. * Both v4 and v6 have the port at the same offset. */ - if (!addr->a.v4.sin_port) - addr->a.v4.sin_port = bp->port; + if (!addr->a_h.v4.sin_port) + addr->a_h.v4.sin_port = bp->port; addr->use_as_src = use_as_src; @@ -182,7 +182,7 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) list_for_each_safe(pos, temp, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&addr->a, del_addr)) { + if (sctp_cmp_addr_exact(&addr->a_h, del_addr)) { /* Found the exact match. */ list_del(pos); kfree(addr); @@ -237,8 +237,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - af = sctp_get_af_specific(addr->a.v4.sin_family); - len = af->to_addr_param(&addr->a, &rawaddr); + af = sctp_get_af_specific(addr->a_h.v4.sin_family); + len = af->to_addr_param(&addr->a_h, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; @@ -305,7 +305,7 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (opt->pf->cmp_addr(&laddr->a, addr, opt)) + if (opt->pf->cmp_addr(&laddr->a_h, addr, opt)) return 1; } @@ -339,13 +339,13 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, return NULL; flip_to_h(&tmp, addr); - if (opt->pf->cmp_addr(&laddr->a, &tmp, opt)) + if (opt->pf->cmp_addr(&laddr->a_h, &tmp, opt)) break; addr_buf += af->sockaddr_len; } if (i == addrcnt) - return &laddr->a; + return &laddr->a_h; } return NULL; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 090f2b2a0cab..75904b037ec6 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -305,7 +305,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, bp = &ep->base.bind_addr; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_has_association(&addr->a, paddr)) { + if (sctp_has_association(&addr->a_h, paddr)) { sctp_read_unlock(&ep->base.addr_lock); return 1; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 1f9f5ec07595..e533970fa335 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -161,17 +161,17 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, /* Fill in the dest address from the route entry passed with the skb * and the source address from the transport. */ - ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr.v6.sin6_addr); - ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr); + ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr_h.v6.sin6_addr); + ipv6_addr_copy(&fl.fl6_src, &transport->saddr_h.v6.sin6_addr); fl.fl6_flowlabel = np->flow_label; IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); if (ipv6_addr_type(&fl.fl6_src) & IPV6_ADDR_LINKLOCAL) - fl.oif = transport->saddr.v6.sin6_scope_id; + fl.oif = transport->saddr_h.v6.sin6_scope_id; else fl.oif = sk->sk_bound_dev_if; fl.fl_ip_sport = inet_sk(sk)->sport; - fl.fl_ip_dport = transport->ipaddr.v6.sin6_port; + fl.fl_ip_dport = transport->ipaddr_h.v6.sin6_port; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; @@ -290,11 +290,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((laddr->use_as_src) && - (laddr->a.sa.sa_family == AF_INET6) && - (scope <= sctp_scope(&laddr->a))) { - bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); + (laddr->a_h.sa.sa_family == AF_INET6) && + (scope <= sctp_scope(&laddr->a_h))) { + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a_h); if (!baddr || (matchlen < bmatchlen)) { - baddr = &laddr->a; + baddr = &laddr->a_h; matchlen = bmatchlen; } } @@ -332,10 +332,10 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, /* Add the address to the local list. */ addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { - addr->a.v6.sin6_family = AF_INET6; - addr->a.v6.sin6_port = 0; - addr->a.v6.sin6_addr = ifp->addr; - addr->a.v6.sin6_scope_id = dev->ifindex; + addr->a_h.v6.sin6_family = AF_INET6; + addr->a_h.v6.sin6_port = 0; + addr->a_h.v6.sin6_addr = ifp->addr; + addr->a_h.v6.sin6_scope_id = dev->ifindex; INIT_LIST_HEAD(&addr->list); list_add_tail(&addr->list, addrlist); } diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 7f49e769080e..47ccec565a24 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -155,12 +155,12 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { asoc = sctp_assoc(epb); peer = asoc->peer.primary_path; - primary = &peer->saddr; + primary = &peer->saddr_h; } list_for_each(pos, &epb->bind_addr.address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - addr = (union sctp_addr *)&laddr->a; + addr = (union sctp_addr *)&laddr->a_h; af = sctp_get_af_specific(addr->sa.sa_family); if (primary && af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); @@ -180,7 +180,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa primary = &(assoc->peer.primary_addr); list_for_each(pos, &assoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - addr = (union sctp_addr *)&transport->ipaddr; + addr = (union sctp_addr *)&transport->ipaddr_h; af = sctp_get_af_specific(addr->sa.sa_family); if (af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 4310e7fac443..20883ffd51d9 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -150,9 +150,9 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, /* Add the address to the local list. */ addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { - addr->a.v4.sin_family = AF_INET; - addr->a.v4.sin_port = 0; - addr->a.v4.sin_addr.s_addr = ifa->ifa_local; + addr->a_h.v4.sin_family = AF_INET; + addr->a_h.v4.sin_port = 0; + addr->a_h.v4.sin_addr.s_addr = ifa->ifa_local; list_add_tail(&addr->list, addrlist); } } @@ -223,17 +223,17 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_in_scope(&addr->a, scope)) { + if (sctp_in_scope(&addr->a_h, scope)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local * sock as well as the remote peer. */ - if ((((AF_INET == addr->a.sa.sa_family) && + if ((((AF_INET == addr->a_h.sa.sa_family) && (copy_flags & SCTP_ADDR4_PEERSUPP))) || - (((AF_INET6 == addr->a.sa.sa_family) && + (((AF_INET6 == addr->a_h.sa.sa_family) && (copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_PEERSUPP)))) { - error = sctp_add_bind_addr(bp, &addr->a, 1, + error = sctp_add_bind_addr(bp, &addr->a_h, 1, GFP_ATOMIC); if (error) goto end_copy; @@ -482,7 +482,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, if (!laddr->use_as_src) continue; sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); - if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) + if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a_h)) goto out_unlock; } sctp_read_unlock(addr_lock); @@ -502,8 +502,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((laddr->use_as_src) && - (AF_INET == laddr->a.sa.sa_family)) { - fl.fl4_src = laddr->a.v4.sin_addr.s_addr; + (AF_INET == laddr->a_h.sa.sa_family)) { + fl.fl4_src = laddr->a_h.v4.sin_addr.s_addr; if (!ip_route_output_key(&rt, &fl)) { dst = &rt->u.dst; goto out_unlock; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index ccbba6b24d1d..13109cfc3ae5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1031,7 +1031,7 @@ nodata: void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, union sctp_addr *dest) { - memcpy(&chunk->source, src, sizeof(union sctp_addr)); + memcpy(&chunk->source_h, src, sizeof(union sctp_addr)); memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); } @@ -1040,10 +1040,10 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) { /* If we have a known transport, use that. */ if (chunk->transport) { - return &chunk->transport->ipaddr; + return &chunk->transport->ipaddr_h; } else { /* Otherwise, extract it from the IP header. */ - return &chunk->source; + return &chunk->source_h; } } @@ -2594,7 +2594,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, sctp_write_lock(&asoc->base.addr_lock); list_for_each(pos, &bp->address_list) { saddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&saddr->a, &addr)) + if (sctp_cmp_addr_exact(&saddr->a_h, &addr)) saddr->use_as_src = 1; } sctp_write_unlock(&asoc->base.addr_lock); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2423b8ef9ce0..e1c5cddf32da 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -441,8 +441,8 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", " transport IP: port:%d failed.\n", asoc, - (&transport->ipaddr), - transport->ipaddr.v4.sin_port); + (&transport->ipaddr_h), + transport->ipaddr_h.v4.sin_port); sctp_assoc_control_transport(asoc, transport, SCTP_TRANSPORT_DOWN, SCTP_FAILED_THRESHOLD); @@ -833,9 +833,9 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - if (!sctp_cmp_addr_exact(&t->ipaddr, + if (!sctp_cmp_addr_exact(&t->ipaddr_h, &asoc->peer.primary_addr)) { - sctp_assoc_del_peer(asoc, &t->ipaddr); + sctp_assoc_del_peer(asoc, &t->ipaddr_h); } } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b70e3258b6d3..f46072767549 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -852,7 +852,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); - hbinfo.daddr = transport->ipaddr; + hbinfo.daddr = transport->ipaddr_h; hbinfo.sent_at = jiffies; hbinfo.hb_nonce = transport->hb_nonce; @@ -1167,8 +1167,8 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, list_for_each(pos2, &asoc->peer.transport_addr_list) { addr = list_entry(pos2, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(&new_addr->ipaddr, - &addr->ipaddr)) { + if (sctp_cmp_addr_exact(&new_addr->ipaddr_h, + &addr->ipaddr_h)) { found = 1; break; } @@ -1179,7 +1179,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, /* If a new address was added, ABORT the sender. */ if (!found && new_addr) { - sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); + sctp_sf_send_restart_abort(&new_addr->ipaddr_h, init, commands); } /* Return success if all addresses were found. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b6e038a387c2..459f32c5c3ae 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -551,7 +551,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, laddr = list_entry(p, struct sctp_sockaddr_entry, list); sctp_read_unlock(&asoc->base.addr_lock); - chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs, + chunk = sctp_make_asconf_update_ip(asoc, &laddr->a_h, addrs, addrcnt, SCTP_PARAM_ADD_IP); if (!chunk) { retval = -ENOMEM; @@ -779,7 +779,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, saddr = list_entry(pos1, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&saddr->a, &saveaddr)) + if (sctp_cmp_addr_exact(&saddr->a_h, &saveaddr)) saddr->use_as_src = 0; } addr_buf += af->sockaddr_len; @@ -3218,7 +3218,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, status.sstat_fragmentation_point = asoc->frag_point; status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); flip_to_n((union sctp_addr *)&status.sstat_primary.spinfo_address, - &transport->ipaddr); + &transport->ipaddr_h); /* Map ipv4 address into v4-mapped-on-v6 address. */ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), (union sctp_addr *)&status.sstat_primary.spinfo_address); @@ -3767,7 +3767,7 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, to = (void __user *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); - memcpy(&temp, &from->ipaddr, sizeof(temp)); + memcpy(&temp, &from->ipaddr_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; temp.v4.sin_port = htons(temp.v4.sin_port); @@ -3816,7 +3816,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); - memcpy(&temp, &from->ipaddr, sizeof(temp)); + memcpy(&temp, &from->ipaddr_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; if(space_left < addrlen) @@ -3882,14 +3882,14 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(&addr->a_h)) { sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a.sa.sa_family)) + (AF_INET6 == addr->a_h.sa.sa_family)) continue; cnt++; } @@ -3927,9 +3927,9 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a.sa.sa_family)) + (AF_INET6 == addr->a_h.sa.sa_family)) continue; - memcpy(&temp, &addr->a, sizeof(temp)); + memcpy(&temp, &addr->a_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; @@ -3962,9 +3962,9 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a.sa.sa_family)) + (AF_INET6 == addr->a_h.sa.sa_family)) continue; - memcpy(&temp, &addr->a, sizeof(temp)); + memcpy(&temp, &addr->a_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; @@ -4038,7 +4038,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(&addr->a_h)) { cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, getaddrs.addr_num, to); @@ -4052,7 +4052,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - memcpy(&temp, &addr->a, sizeof(temp)); + memcpy(&temp, &addr->a_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; temp.v4.sin_port = htons(temp.v4.sin_port); @@ -4128,7 +4128,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(&addr->a_h)) { cnt = sctp_copy_laddrs_to_user(sk, bp->port, &to, space_left); if (cnt < 0) { @@ -4141,7 +4141,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - memcpy(&temp, &addr->a, sizeof(temp)); + memcpy(&temp, &addr->a_h, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if(space_left < addrlen) @@ -4195,7 +4195,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, return -ENOTCONN; flip_to_n((union sctp_addr *)&prim.ssp_addr, - &asoc->peer.primary_path->ipaddr); + &asoc->peer.primary_path->ipaddr_h); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, (union sctp_addr *)&prim.ssp_addr); diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 3e5936a5f671..1f56c9d95739 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -61,12 +61,12 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, gfp_t gfp) { /* Copy in the address. */ - peer->ipaddr = *addr; + peer->ipaddr_h = *addr; peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; peer->dst = NULL; - memset(&peer->saddr, 0, sizeof(union sctp_addr)); + memset(&peer->saddr_h, 0, sizeof(union sctp_addr)); /* From 6.3.1 RTO Calculation: * @@ -232,7 +232,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport) { struct dst_entry *dst; - dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); + dst = transport->af_specific->get_dst(NULL, &transport->ipaddr_h, NULL); if (dst) { transport->pathmtu = dst_mtu(dst); @@ -249,15 +249,15 @@ void sctp_transport_route(struct sctp_transport *transport, { struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; - union sctp_addr *daddr = &transport->ipaddr; + union sctp_addr *daddr = &transport->ipaddr_h; struct dst_entry *dst; dst = af->get_dst(asoc, daddr, saddr); if (saddr) - memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); + memcpy(&transport->saddr_h, saddr, sizeof(union sctp_addr)); else - af->get_saddr(asoc, dst, daddr, &transport->saddr); + af->get_saddr(asoc, dst, daddr, &transport->saddr_h); transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { @@ -270,7 +270,7 @@ void sctp_transport_route(struct sctp_transport *transport, * association's active path for getsockname(). */ if (asoc && (transport == asoc->peer.active_path)) - opt->pf->af->to_sk_saddr(&transport->saddr, + opt->pf->af->to_sk_saddr(&transport->saddr_h, asoc->base.sk); } else transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; -- cgit v1.2.3-70-g09d2 From 2a6fd78adec062f16f8662563115679e669efaca Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:04:42 -0800 Subject: [SCTP] embedded sctp_addr: net-endian mirrors Add sctp_chunk->source, sctp_sockaddr_entry->a, sctp_transport->ipaddr and sctp_transport->saddr, maintain them as net-endian mirrors of their host-endian counterparts. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 4 ++++ net/sctp/bind_addr.c | 2 ++ net/sctp/ipv6.c | 9 +++++---- net/sctp/protocol.c | 7 ++++--- net/sctp/sm_make_chunk.c | 1 + net/sctp/transport.c | 3 +++ 6 files changed, 19 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 953a73f9689c..2c35f2fd5601 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -713,6 +713,7 @@ struct sctp_chunk { unsigned long sent_at; /* What is the origin IP address for this chunk? */ + union sctp_addr source; union sctp_addr source_h; /* Destination address for this chunk. */ union sctp_addr dest; @@ -756,6 +757,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk); /* This is a structure for holding either an IPv6 or an IPv4 address. */ struct sctp_sockaddr_entry { struct list_head list; + union sctp_addr a; union sctp_addr a_h; __u8 use_as_src; }; @@ -842,6 +844,7 @@ struct sctp_transport { int dead; /* This is the peer's IP address and port. */ + union sctp_addr ipaddr; union sctp_addr ipaddr_h; /* These are the functions we call to handle LLP stuff. */ @@ -900,6 +903,7 @@ struct sctp_transport { /* Destination */ struct dst_entry *dst; /* Source address. */ + union sctp_addr saddr; union sctp_addr saddr_h; /* When was the last time(in jiffies) that a data packet was sent on diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index b8115cb31ae3..2b36e4238170 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -163,6 +163,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, if (!addr->a_h.v4.sin_port) addr->a_h.v4.sin_port = bp->port; + flip_to_n(&addr->a, &addr->a_h); + addr->use_as_src = use_as_src; INIT_LIST_HEAD(&addr->list); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index e533970fa335..8ebd177296ba 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -332,10 +332,11 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, /* Add the address to the local list. */ addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { - addr->a_h.v6.sin6_family = AF_INET6; - addr->a_h.v6.sin6_port = 0; - addr->a_h.v6.sin6_addr = ifp->addr; - addr->a_h.v6.sin6_scope_id = dev->ifindex; + addr->a.v6.sin6_family = AF_INET6; + addr->a.v6.sin6_port = 0; + addr->a.v6.sin6_addr = ifp->addr; + addr->a.v6.sin6_scope_id = dev->ifindex; + addr->a_h = addr->a; INIT_LIST_HEAD(&addr->list); list_add_tail(&addr->list, addrlist); } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 20883ffd51d9..363274045032 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -150,9 +150,10 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, /* Add the address to the local list. */ addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); if (addr) { - addr->a_h.v4.sin_family = AF_INET; - addr->a_h.v4.sin_port = 0; - addr->a_h.v4.sin_addr.s_addr = ifa->ifa_local; + addr->a.v4.sin_family = AF_INET; + addr->a.v4.sin_port = 0; + addr->a.v4.sin_addr.s_addr = ifa->ifa_local; + addr->a_h = addr->a; list_add_tail(&addr->list, addrlist); } } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 13109cfc3ae5..b8e0f72b319f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1032,6 +1032,7 @@ void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, union sctp_addr *dest) { memcpy(&chunk->source_h, src, sizeof(union sctp_addr)); + flip_to_n(&chunk->source, &chunk->source_h); memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); } diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 1f56c9d95739..bacd09448b8e 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -62,10 +62,12 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, { /* Copy in the address. */ peer->ipaddr_h = *addr; + flip_to_n(&peer->ipaddr, &peer->ipaddr_h); peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; peer->dst = NULL; + memset(&peer->saddr, 0, sizeof(union sctp_addr)); memset(&peer->saddr_h, 0, sizeof(union sctp_addr)); /* From 6.3.1 RTO Calculation: @@ -258,6 +260,7 @@ void sctp_transport_route(struct sctp_transport *transport, memcpy(&transport->saddr_h, saddr, sizeof(union sctp_addr)); else af->get_saddr(asoc, dst, daddr, &transport->saddr_h); + flip_to_n(&transport->saddr, &transport->saddr_h); transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { -- cgit v1.2.3-70-g09d2 From c604e368a477ed1f7dd532605a8f1990d2b128ee Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:04:59 -0800 Subject: [SCTP]: Pass net-endian to ->seq_dump_addr() No actual modifications of method instances are needed - they don't look at port numbers. Switch callers... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 47ccec565a24..bf0144ed3e3a 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -165,7 +165,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo if (primary && af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); } - af->seq_dump_addr(seq, addr); + af->seq_dump_addr(seq, &laddr->a); } } @@ -185,7 +185,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa if (af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); } - af->seq_dump_addr(seq, addr); + af->seq_dump_addr(seq, &transport->ipaddr); } } -- cgit v1.2.3-70-g09d2 From 5f242a13e8505e0f3efd3113da6e029f6e7dfa32 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:05:23 -0800 Subject: [SCTP]: Switch ->cmp_addr() and sctp_cmp_addr_exact() to net-endian. instances of ->cmp_addr() are fine with switching both arguments to net-endian; callers other than in sctp_cmp_addr_exact() (both as ->cmp_addr(...) and direct calls of instances) adjusted; sctp_cmp_addr_exact() switched to net-endian itself and adjustment is done in its callers Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 9 +++++++-- net/sctp/bind_addr.c | 13 ++++++++----- net/sctp/proc.c | 14 ++++++++------ net/sctp/protocol.c | 4 +++- net/sctp/sm_make_chunk.c | 11 ++++++++--- net/sctp/sm_sideeffect.c | 6 ++++-- net/sctp/sm_statefuns.c | 4 ++-- net/sctp/socket.c | 5 +---- 8 files changed, 41 insertions(+), 25 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 83318e727905..72199d149573 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -666,10 +666,13 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, struct list_head *pos; struct list_head *temp; struct sctp_transport *transport; + union sctp_addr tmp; + + flip_to_n(&tmp, addr); list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(addr, &transport->ipaddr_h)) { + if (sctp_cmp_addr_exact(&tmp, &transport->ipaddr)) { /* Do book keeping for removing the peer and free it. */ sctp_assoc_rm_peer(asoc, transport); break; @@ -684,12 +687,14 @@ struct sctp_transport *sctp_assoc_lookup_paddr( { struct sctp_transport *t; struct list_head *pos; + union sctp_addr tmp; + flip_to_n(&tmp, address); /* Cycle through all transports searching for a peer address. */ list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(address, &t->ipaddr_h)) + if (sctp_cmp_addr_exact(&tmp, &t->ipaddr)) return t; } diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 2b36e4238170..9085e531d575 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -181,10 +181,13 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) { struct list_head *pos, *temp; struct sctp_sockaddr_entry *addr; + union sctp_addr tmp; + + flip_to_n(&tmp, del_addr); list_for_each_safe(pos, temp, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&addr->a_h, del_addr)) { + if (sctp_cmp_addr_exact(&addr->a, &tmp)) { /* Found the exact match. */ list_del(pos); kfree(addr); @@ -304,10 +307,12 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, { struct sctp_sockaddr_entry *laddr; struct list_head *pos; + union sctp_addr tmp; + flip_to_n(&tmp, addr); list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (opt->pf->cmp_addr(&laddr->a_h, addr, opt)) + if (opt->pf->cmp_addr(&laddr->a, &tmp, opt)) return 1; } @@ -334,14 +339,12 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, addr_buf = (union sctp_addr *)addrs; for (i = 0; i < addrcnt; i++) { - union sctp_addr tmp; addr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(addr->v4.sin_family); if (!af) return NULL; - flip_to_h(&tmp, addr); - if (opt->pf->cmp_addr(&laddr->a_h, &tmp, opt)) + if (opt->pf->cmp_addr(&laddr->a, addr, opt)) break; addr_buf += af->sockaddr_len; diff --git a/net/sctp/proc.c b/net/sctp/proc.c index bf0144ed3e3a..04faa4a706d4 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -155,17 +155,17 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { asoc = sctp_assoc(epb); peer = asoc->peer.primary_path; - primary = &peer->saddr_h; + primary = &peer->saddr; } list_for_each(pos, &epb->bind_addr.address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - addr = (union sctp_addr *)&laddr->a_h; + addr = &laddr->a; af = sctp_get_af_specific(addr->sa.sa_family); if (primary && af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); } - af->seq_dump_addr(seq, &laddr->a); + af->seq_dump_addr(seq, addr); } } @@ -175,17 +175,19 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa struct list_head *pos; struct sctp_transport *transport; union sctp_addr *addr, *primary; + union sctp_addr tmp; struct sctp_af *af; primary = &(assoc->peer.primary_addr); + flip_to_n(&tmp, primary); list_for_each(pos, &assoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - addr = (union sctp_addr *)&transport->ipaddr_h; + addr = &transport->ipaddr; af = sctp_get_af_specific(addr->sa.sa_family); - if (af->cmp_addr(addr, primary)) { + if (af->cmp_addr(addr, &tmp)) { seq_printf(seq, "*"); } - af->seq_dump_addr(seq, &transport->ipaddr); + af->seq_dump_addr(seq, addr); } } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 363274045032..2db140e901d0 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -478,12 +478,14 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, */ sctp_read_lock(addr_lock); list_for_each(pos, &bp->address_list) { + union sctp_addr tmp; laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if (!laddr->use_as_src) continue; sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); - if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a_h)) + flip_to_n(&tmp, &dst_saddr); + if (sctp_v4_cmp_addr(&tmp, &laddr->a)) goto out_unlock; } sctp_read_unlock(addr_lock); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b8e0f72b319f..ee907ea7eed1 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2414,7 +2414,8 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, union sctp_addr addr; struct list_head *pos; union sctp_addr_param *addr_param; - + union sctp_addr tmp, tmp_addr; + addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); @@ -2423,6 +2424,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, return SCTP_ERROR_INV_PARAM; af->from_addr_param(&addr, addr_param, asoc->peer.port, 0); + flip_to_n(&tmp_addr, &addr); switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address @@ -2457,7 +2459,8 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * an Error Cause TLV set to the new error code 'Request to * Delete Source IP Address' */ - if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) + flip_to_n(&tmp, sctp_source(asconf)); + if (sctp_cmp_addr_exact(&tmp, &tmp_addr)) return SCTP_ERROR_DEL_SRC_IP; sctp_assoc_del_peer(asoc, &addr); @@ -2581,6 +2584,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, struct sctp_transport *transport; struct sctp_sockaddr_entry *saddr; int retval = 0; + union sctp_addr tmp; addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); @@ -2588,6 +2592,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, /* We have checked the packet before, so we do not check again. */ af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); af->from_addr_param(&addr, addr_param, bp->port, 0); + flip_to_n(&tmp, &addr); switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: @@ -2595,7 +2600,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, sctp_write_lock(&asoc->base.addr_lock); list_for_each(pos, &bp->address_list) { saddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&saddr->a_h, &addr)) + if (sctp_cmp_addr_exact(&saddr->a, &tmp)) saddr->use_as_src = 1; } sctp_write_unlock(&asoc->base.addr_lock); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e1c5cddf32da..3d9213dfaa10 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -830,11 +830,13 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) struct sctp_transport *t; struct list_head *pos; struct list_head *temp; + union sctp_addr tmp; + flip_to_n(&tmp, &asoc->peer.primary_addr); list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - if (!sctp_cmp_addr_exact(&t->ipaddr_h, - &asoc->peer.primary_addr)) { + if (!sctp_cmp_addr_exact(&t->ipaddr, + &tmp)) { sctp_assoc_del_peer(asoc, &t->ipaddr_h); } } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f46072767549..ac776fd20667 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1167,8 +1167,8 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, list_for_each(pos2, &asoc->peer.transport_addr_list) { addr = list_entry(pos2, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(&new_addr->ipaddr_h, - &addr->ipaddr_h)) { + if (sctp_cmp_addr_exact(&new_addr->ipaddr, + &addr->ipaddr)) { found = 1; break; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 459f32c5c3ae..e03ba9055eb1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -693,7 +693,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk, struct sctp_bind_addr *bp; struct sctp_chunk *chunk; union sctp_addr *laddr; - union sctp_addr saveaddr; void *addr_buf; struct sctp_af *af; struct list_head *pos, *pos1; @@ -773,13 +772,11 @@ static int sctp_send_asconf_del_ip(struct sock *sk, for (i = 0; i < addrcnt; i++) { laddr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(laddr->v4.sin_family); - memcpy(&saveaddr, laddr, af->sockaddr_len); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); list_for_each(pos1, &bp->address_list) { saddr = list_entry(pos1, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&saddr->a_h, &saveaddr)) + if (sctp_cmp_addr_exact(&saddr->a, laddr)) saddr->use_as_src = 0; } addr_buf += af->sockaddr_len; -- cgit v1.2.3-70-g09d2 From 7e1e4a2b9dcc63ac3328f786f9d98bde90c8fc6c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:05:43 -0800 Subject: [SCTP]: Switch sctp_bind_addr_match() to net-endian. Callers adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 8 ++++---- net/sctp/bind_addr.c | 4 +--- net/sctp/endpointola.c | 4 +++- net/sctp/socket.c | 4 +--- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 72199d149573..8d841f16dcbd 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -930,6 +930,8 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, const union sctp_addr *paddr) { struct sctp_transport *transport; + union sctp_addr tmp; + flip_to_n(&tmp, laddr); sctp_read_lock(&asoc->base.addr_lock); @@ -939,7 +941,7 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, if (!transport) goto out; - if (sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + if (sctp_bind_addr_match(&asoc->base.bind_addr, &tmp, sctp_sk(asoc->base.sk))) goto out; } @@ -1342,12 +1344,10 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, const union sctp_addr *laddr) { int found; - union sctp_addr tmp; - flip_to_h(&tmp, laddr); sctp_read_lock(&asoc->base.addr_lock); if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && - sctp_bind_addr_match(&asoc->base.bind_addr, &tmp, + sctp_bind_addr_match(&asoc->base.bind_addr, laddr, sctp_sk(asoc->base.sk))) { found = 1; goto out; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 9085e531d575..442d891f68ea 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -307,12 +307,10 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, { struct sctp_sockaddr_entry *laddr; struct list_head *pos; - union sctp_addr tmp; - flip_to_n(&tmp, addr); list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (opt->pf->cmp_addr(&laddr->a, &tmp, opt)) + if (opt->pf->cmp_addr(&laddr->a, addr, opt)) return 1; } diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 75904b037ec6..d77fe9232dd1 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -228,10 +228,12 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, const union sctp_addr *laddr) { struct sctp_endpoint *retval; + union sctp_addr tmp; + flip_to_n(&tmp, laddr); sctp_read_lock(&ep->base.addr_lock); if (ep->base.bind_addr.port == laddr->v4.sin_port) { - if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, + if (sctp_bind_addr_match(&ep->base.bind_addr, &tmp, sctp_sk(ep->base.sk))) { retval = ep; goto out; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e03ba9055eb1..d42953efa355 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4635,11 +4635,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) { struct sctp_bind_hashbucket *head; /* hash list */ struct sctp_bind_bucket *pp; /* hash list port iterator */ - union sctp_addr tmp; unsigned short snum; int ret; - flip_to_h(&tmp, addr); snum = ntohs(addr->v4.sin_port); SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum); @@ -4737,7 +4735,7 @@ pp_found: if (reuse && sk2->sk_reuse) continue; - if (sctp_bind_addr_match(&ep2->base.bind_addr, &tmp, + if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, sctp_sk(sk))) { ret = (long)sk2; goto fail_unlock; -- cgit v1.2.3-70-g09d2 From acd2bc96e19535fcd74c6eb94532c19c817857bd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:06:04 -0800 Subject: [SCTP]: Switch ->primary_addr to net-endian. Users adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 2 +- net/sctp/proc.c | 6 ++---- net/sctp/sm_sideeffect.c | 4 +--- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8d841f16dcbd..22c2519d3fd8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -442,7 +442,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, asoc->peer.primary_path = transport; /* Set a default msg_name for events. */ - memcpy(&asoc->peer.primary_addr, &transport->ipaddr_h, + memcpy(&asoc->peer.primary_addr, &transport->ipaddr, sizeof(union sctp_addr)); /* If the primary path is changing, assume that the diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 04faa4a706d4..b3493bdbcacb 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -175,16 +175,14 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa struct list_head *pos; struct sctp_transport *transport; union sctp_addr *addr, *primary; - union sctp_addr tmp; struct sctp_af *af; - primary = &(assoc->peer.primary_addr); - flip_to_n(&tmp, primary); + primary = &assoc->peer.primary_addr; list_for_each(pos, &assoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); addr = &transport->ipaddr; af = sctp_get_af_specific(addr->sa.sa_family); - if (af->cmp_addr(addr, &tmp)) { + if (af->cmp_addr(addr, primary)) { seq_printf(seq, "*"); } af->seq_dump_addr(seq, addr); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 3d9213dfaa10..50d4ccc15ad1 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -830,13 +830,11 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) struct sctp_transport *t; struct list_head *pos; struct list_head *temp; - union sctp_addr tmp; - flip_to_n(&tmp, &asoc->peer.primary_addr); list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); if (!sctp_cmp_addr_exact(&t->ipaddr, - &tmp)) { + &asoc->peer.primary_addr)) { sctp_assoc_del_peer(asoc, &t->ipaddr_h); } } -- cgit v1.2.3-70-g09d2 From 854d43a465cc8ba8e501320b3bc27359d909da2f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:06:24 -0800 Subject: [SCTP]: Annotate ->dst_saddr() switched to taking a pointer to net-endian sctp_addr and a net-endian port number. Instances and callers adjusted; interestingly enough, the only calls are direct calls of specific instances - the method is not used at all. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 2c35f2fd5601..1616a38a0be3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -559,7 +559,7 @@ struct sctp_af { struct net_device *); void (*dst_saddr) (union sctp_addr *saddr, struct dst_entry *dst, - unsigned short port); + __be16 port); int (*cmp_addr) (const union sctp_addr *addr1, const union sctp_addr *addr2); void (*addr_copy) (union sctp_addr *dst, diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 8ebd177296ba..6139d1d964eb 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -434,7 +434,7 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, - unsigned short port) + __be16 port) { struct rt6_info *rt = (struct rt6_info *)dst; addr->sa.sa_family = AF_INET6; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 2db140e901d0..d1fbd1f5c6d1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -316,7 +316,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, - unsigned short port) + __be16 port) { struct rtable *rt = (struct rtable *)dst; saddr->v4.sin_family = AF_INET; @@ -478,14 +478,12 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, */ sctp_read_lock(addr_lock); list_for_each(pos, &bp->address_list) { - union sctp_addr tmp; laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if (!laddr->use_as_src) continue; - sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); - flip_to_n(&tmp, &dst_saddr); - if (sctp_v4_cmp_addr(&tmp, &laddr->a)) + sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); + if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) goto out_unlock; } sctp_read_unlock(addr_lock); -- cgit v1.2.3-70-g09d2 From 38a03145efcdbbcc60465fdffc0546208a52daf8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:06:45 -0800 Subject: [SCTP]: sctp_assoc_del_peer() switched to net-endian. Callers adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 7 ++----- net/sctp/sm_make_chunk.c | 2 +- net/sctp/sm_sideeffect.c | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 22c2519d3fd8..ab3141f05921 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -666,13 +666,10 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, struct list_head *pos; struct list_head *temp; struct sctp_transport *transport; - union sctp_addr tmp; - - flip_to_n(&tmp, addr); list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(&tmp, &transport->ipaddr)) { + if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { /* Do book keeping for removing the peer and free it. */ sctp_assoc_rm_peer(asoc, transport); break; @@ -1051,7 +1048,7 @@ void sctp_assoc_update(struct sctp_association *asoc, list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { trans = list_entry(pos, struct sctp_transport, transports); if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr_h)) - sctp_assoc_del_peer(asoc, &trans->ipaddr_h); + sctp_assoc_del_peer(asoc, &trans->ipaddr); } /* If the case is A (association restart), use diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index ee907ea7eed1..303830b40ab3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2463,7 +2463,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (sctp_cmp_addr_exact(&tmp, &tmp_addr)) return SCTP_ERROR_DEL_SRC_IP; - sctp_assoc_del_peer(asoc, &addr); + sctp_assoc_del_peer(asoc, &tmp_addr); break; case SCTP_PARAM_SET_PRIMARY: peer = sctp_assoc_lookup_paddr(asoc, &addr); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 50d4ccc15ad1..a11bd4ff9303 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -835,7 +835,7 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) t = list_entry(pos, struct sctp_transport, transports); if (!sctp_cmp_addr_exact(&t->ipaddr, &asoc->peer.primary_addr)) { - sctp_assoc_del_peer(asoc, &t->ipaddr_h); + sctp_assoc_del_peer(asoc, &t->ipaddr); } } -- cgit v1.2.3-70-g09d2 From be29681edfbad72167df735e243e8621840dca4f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:07:06 -0800 Subject: [SCTP]: Switch sctp_assoc_lookup_paddr() to net-endian. Callers updated. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 17 +++++++++-------- net/sctp/endpointola.c | 4 +++- net/sctp/sm_make_chunk.c | 2 +- net/sctp/sm_statefuns.c | 4 +++- net/sctp/socket.c | 5 +++-- 5 files changed, 19 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ab3141f05921..3be8b6081a15 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -533,6 +533,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, struct sctp_transport *peer; struct sctp_sock *sp; unsigned short port; + union sctp_addr tmp; + flip_to_n(&tmp, addr); sp = sctp_sk(asoc->base.sk); @@ -551,7 +553,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, asoc->peer.port = port; /* Check to see if this is a duplicate. */ - peer = sctp_assoc_lookup_paddr(asoc, addr); + peer = sctp_assoc_lookup_paddr(asoc, &tmp); if (peer) { if (peer->state == SCTP_UNKNOWN) { if (peer_state == SCTP_ACTIVE) @@ -684,14 +686,12 @@ struct sctp_transport *sctp_assoc_lookup_paddr( { struct sctp_transport *t; struct list_head *pos; - union sctp_addr tmp; - flip_to_n(&tmp, address); /* Cycle through all transports searching for a peer address. */ list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - if (sctp_cmp_addr_exact(&tmp, &t->ipaddr)) + if (sctp_cmp_addr_exact(address, &t->ipaddr)) return t; } @@ -927,14 +927,15 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, const union sctp_addr *paddr) { struct sctp_transport *transport; - union sctp_addr tmp; + union sctp_addr tmp, tmp2; flip_to_n(&tmp, laddr); + flip_to_n(&tmp2, paddr); sctp_read_lock(&asoc->base.addr_lock); if ((asoc->base.bind_addr.port == laddr->v4.sin_port) && (asoc->peer.port == paddr->v4.sin_port)) { - transport = sctp_assoc_lookup_paddr(asoc, paddr); + transport = sctp_assoc_lookup_paddr(asoc, &tmp2); if (!transport) goto out; @@ -1047,7 +1048,7 @@ void sctp_assoc_update(struct sctp_association *asoc, /* Remove any peer addresses not present in the new association. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { trans = list_entry(pos, struct sctp_transport, transports); - if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr_h)) + if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) sctp_assoc_del_peer(asoc, &trans->ipaddr); } @@ -1071,7 +1072,7 @@ void sctp_assoc_update(struct sctp_association *asoc, list_for_each(pos, &new->peer.transport_addr_list) { trans = list_entry(pos, struct sctp_transport, transports); - if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr_h)) + if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) sctp_assoc_add_peer(asoc, &trans->ipaddr_h, GFP_ATOMIC, trans->state); } diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index d77fe9232dd1..7c781d663603 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -259,6 +259,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( int rport; struct sctp_association *asoc; struct list_head *pos; + union sctp_addr tmp; + flip_to_n(&tmp, paddr); rport = paddr->v4.sin_port; @@ -266,7 +268,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( asoc = list_entry(pos, struct sctp_association, asocs); if (rport == asoc->peer.port) { sctp_read_lock(&asoc->base.addr_lock); - *transport = sctp_assoc_lookup_paddr(asoc, paddr); + *transport = sctp_assoc_lookup_paddr(asoc, &tmp); sctp_read_unlock(&asoc->base.addr_lock); if (*transport) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 303830b40ab3..cc1b01152c34 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2466,7 +2466,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, sctp_assoc_del_peer(asoc, &tmp_addr); break; case SCTP_PARAM_SET_PRIMARY: - peer = sctp_assoc_lookup_paddr(asoc, &addr); + peer = sctp_assoc_lookup_paddr(asoc, &tmp_addr); if (!peer) return SCTP_ERROR_INV_PARAM; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ac776fd20667..7d722f5a31d7 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1018,6 +1018,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, struct sctp_transport *link; sctp_sender_hb_info_t *hbinfo; unsigned long max_interval; + union sctp_addr tmp; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -1035,7 +1036,8 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, } from_addr = hbinfo->daddr; - link = sctp_assoc_lookup_paddr(asoc, &from_addr); + flip_to_n(&tmp, &from_addr); + link = sctp_assoc_lookup_paddr(asoc, &tmp); /* This should never happen, but lets log it if so. */ if (unlikely(!link)) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d42953efa355..ffdad8e842ac 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1370,7 +1370,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, struct sctp_association *new_asoc=NULL, *asoc=NULL; struct sctp_transport *transport, *chunk_tp; struct sctp_chunk *chunk; - union sctp_addr to; + union sctp_addr to, tmp; struct sockaddr *msg_name = NULL; struct sctp_sndrcvinfo default_sinfo = { 0 }; struct sctp_sndrcvinfo *sinfo; @@ -1424,6 +1424,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, if (msg_namelen > sizeof(to)) msg_namelen = sizeof(to); memcpy(&to, msg->msg_name, msg_namelen); + memcpy(&tmp, msg->msg_name, msg_namelen); SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is " "0x%x:%u.\n", to.v4.sin_addr.s_addr, to.v4.sin_port); @@ -1691,7 +1692,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, */ if ((sctp_style(sk, TCP) && msg_name) || (sinfo_flags & SCTP_ADDR_OVER)) { - chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); + chunk_tp = sctp_assoc_lookup_paddr(asoc, &tmp); if (!chunk_tp) { err = -EINVAL; goto out_free; -- cgit v1.2.3-70-g09d2 From 63de08f45bb73a445edb482850f4cdccd84def48 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:07:25 -0800 Subject: [SCTP]: Switch address inside the heartbeat opaque data to net-endian. Its only use happens on the same host, when it gets quoted back to us. So we are free to flip to net-endian and avoid extra PITA. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 7d722f5a31d7..0848309773a5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -852,7 +852,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); - hbinfo.daddr = transport->ipaddr_h; + hbinfo.daddr = transport->ipaddr; hbinfo.sent_at = jiffies; hbinfo.hb_nonce = transport->hb_nonce; @@ -1018,7 +1018,6 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, struct sctp_transport *link; sctp_sender_hb_info_t *hbinfo; unsigned long max_interval; - union sctp_addr tmp; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -1036,8 +1035,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, } from_addr = hbinfo->daddr; - flip_to_n(&tmp, &from_addr); - link = sctp_assoc_lookup_paddr(asoc, &tmp); + link = sctp_assoc_lookup_paddr(asoc, &from_addr); /* This should never happen, but lets log it if so. */ if (unlikely(!link)) { -- cgit v1.2.3-70-g09d2 From c9a08505ec0a0260fc94a823c014cc3970f72d25 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:07:48 -0800 Subject: [SCTP]: Switch sctp_del_bind_addr() to net-endian. Callers adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 5 +---- net/sctp/sm_make_chunk.c | 2 +- net/sctp/socket.c | 17 +++++------------ 3 files changed, 7 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 442d891f68ea..eafdd11152d0 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -181,13 +181,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) { struct list_head *pos, *temp; struct sctp_sockaddr_entry *addr; - union sctp_addr tmp; - - flip_to_n(&tmp, del_addr); list_for_each_safe(pos, temp, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&addr->a, &tmp)) { + if (sctp_cmp_addr_exact(&addr->a, del_addr)) { /* Found the exact match. */ list_del(pos); kfree(addr); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index cc1b01152c34..cb8cecd85a2e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2609,7 +2609,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, case SCTP_PARAM_DEL_IP: sctp_local_bh_disable(); sctp_write_lock(&asoc->base.addr_lock); - retval = sctp_del_bind_addr(bp, &addr); + retval = sctp_del_bind_addr(bp, &tmp); sctp_write_unlock(&asoc->base.addr_lock); sctp_local_bh_enable(); list_for_each(pos, &asoc->peer.transport_addr_list) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ffdad8e842ac..f00b03845247 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -607,9 +607,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) int cnt; struct sctp_bind_addr *bp = &ep->base.bind_addr; int retval = 0; - union sctp_addr saveaddr; void *addr_buf; - struct sockaddr *sa_addr; + union sctp_addr *sa_addr; struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", @@ -627,19 +626,13 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) goto err_bindx_rem; } - /* The list may contain either IPv4 or IPv6 address; - * determine the address length to copy the address to - * saveaddr. - */ - sa_addr = (struct sockaddr *)addr_buf; - af = sctp_get_af_specific(sa_addr->sa_family); + sa_addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa.sa_family); if (!af) { retval = -EINVAL; goto err_bindx_rem; } - memcpy(&saveaddr, sa_addr, af->sockaddr_len); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); - if (saveaddr.v4.sin_port != bp->port) { + if (sa_addr->v4.sin_port != htons(bp->port)) { retval = -EINVAL; goto err_bindx_rem; } @@ -654,7 +647,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) sctp_local_bh_disable(); sctp_write_lock(&ep->base.addr_lock); - retval = sctp_del_bind_addr(bp, &saveaddr); + retval = sctp_del_bind_addr(bp, sa_addr); sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); -- cgit v1.2.3-70-g09d2 From 1c7d1fc14974f44809b22521bd9796411d8ba440 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:08:09 -0800 Subject: [SCTP]: Switch sctp_endpoint_is_match() to net-endian. The only caller (__sctp_rcv_lookup_endpoint()) also switched, its caller adjusted Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 6 ++---- net/sctp/input.c | 7 +++++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 7c781d663603..c543f3250645 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -228,12 +228,10 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, const union sctp_addr *laddr) { struct sctp_endpoint *retval; - union sctp_addr tmp; - flip_to_n(&tmp, laddr); sctp_read_lock(&ep->base.addr_lock); - if (ep->base.bind_addr.port == laddr->v4.sin_port) { - if (sctp_bind_addr_match(&ep->base.bind_addr, &tmp, + if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) { + if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, sctp_sk(ep->base.sk))) { retval = ep; goto out; diff --git a/net/sctp/input.c b/net/sctp/input.c index 6d82f400d13c..1bb3f264da1f 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -127,6 +127,7 @@ int sctp_rcv(struct sk_buff *skb) struct sctphdr *sh; union sctp_addr src; union sctp_addr dest; + union sctp_addr tmp; int family; struct sctp_af *af; @@ -180,8 +181,10 @@ int sctp_rcv(struct sk_buff *skb) asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); + flip_to_n(&tmp, &dest); + if (!asoc) - ep = __sctp_rcv_lookup_endpoint(&dest); + ep = __sctp_rcv_lookup_endpoint(&tmp); /* Retrieve the common input handling substructure. */ rcvr = asoc ? &asoc->base : &ep->base; @@ -726,7 +729,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l struct sctp_endpoint *ep; int hash; - hash = sctp_ep_hashfn(laddr->v4.sin_port); + hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); head = &sctp_ep_hashtable[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { -- cgit v1.2.3-70-g09d2 From e2fccedb0136205d02e97a41851503e2b96d2a17 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:08:41 -0800 Subject: [SCTP]: Switch sctp_assoc_is_match to net-endian. Along with it, statics in input.c that end up calling it (__sctp_lookup_association, sctp_lookup_association, __sctp_rcv_init_lookup, __sctp_rcv_lookup). Callers are adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 11 ++++------- net/sctp/input.c | 23 ++++++++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 3be8b6081a15..4bd916c808c1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -927,19 +927,16 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, const union sctp_addr *paddr) { struct sctp_transport *transport; - union sctp_addr tmp, tmp2; - flip_to_n(&tmp, laddr); - flip_to_n(&tmp2, paddr); sctp_read_lock(&asoc->base.addr_lock); - if ((asoc->base.bind_addr.port == laddr->v4.sin_port) && - (asoc->peer.port == paddr->v4.sin_port)) { - transport = sctp_assoc_lookup_paddr(asoc, &tmp2); + if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) && + (htons(asoc->peer.port) == paddr->v4.sin_port)) { + transport = sctp_assoc_lookup_paddr(asoc, paddr); if (!transport) goto out; - if (sctp_bind_addr_match(&asoc->base.bind_addr, &tmp, + if (sctp_bind_addr_match(&asoc->base.bind_addr, laddr, sctp_sk(asoc->base.sk))) goto out; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 1bb3f264da1f..85b3441c4a23 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -127,7 +127,7 @@ int sctp_rcv(struct sk_buff *skb) struct sctphdr *sh; union sctp_addr src; union sctp_addr dest; - union sctp_addr tmp; + union sctp_addr tmp, tmp2; int family; struct sctp_af *af; @@ -179,9 +179,10 @@ int sctp_rcv(struct sk_buff *skb) !af->addr_valid(&dest, NULL, skb)) goto discard_it; - asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); - flip_to_n(&tmp, &dest); + flip_to_n(&tmp2, &src); + + asoc = __sctp_rcv_lookup(skb, &tmp2, &tmp, &transport); if (!asoc) ep = __sctp_rcv_lookup_endpoint(&tmp); @@ -443,6 +444,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, struct sock *sk = NULL; struct sctp_association *asoc; struct sctp_transport *transport = NULL; + union sctp_addr tmp, tmp2; *app = NULL; *tpp = NULL; @@ -454,11 +456,13 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, /* Initialize local addresses for lookups. */ af->from_skb(&saddr, skb, 1); af->from_skb(&daddr, skb, 0); + flip_to_n(&tmp, &saddr); + flip_to_n(&tmp2, &daddr); /* Look for an association that matches the incoming ICMP error * packet. */ - asoc = __sctp_lookup_association(&saddr, &daddr, &transport); + asoc = __sctp_lookup_association(&tmp, &tmp2, &transport); if (!asoc) return NULL; @@ -833,7 +837,7 @@ static struct sctp_association *__sctp_lookup_association( /* Optimize here for direct hit, only listening connections can * have wildcards anyways. */ - hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port); + hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); head = &sctp_assoc_hashtable[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { @@ -875,8 +879,11 @@ int sctp_has_association(const union sctp_addr *laddr, { struct sctp_association *asoc; struct sctp_transport *transport; + union sctp_addr tmp, tmp2; + flip_to_n(&tmp, laddr); + flip_to_n(&tmp2, paddr); - if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { + if ((asoc = sctp_lookup_association(&tmp, &tmp2, &transport))) { sctp_association_put(asoc); return 1; } @@ -914,6 +921,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, sctp_init_chunk_t *init; struct sctp_transport *transport; struct sctp_af *af; + union sctp_addr tmp2; ch = (sctp_chunkhdr_t *) skb->data; @@ -961,8 +969,9 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, continue; af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); + flip_to_n(&tmp2, paddr); - asoc = __sctp_lookup_association(laddr, paddr, &transport); + asoc = __sctp_lookup_association(laddr, &tmp2, &transport); if (asoc) return asoc; } -- cgit v1.2.3-70-g09d2 From f235fca389f23cd6c9e0f466611bb2d6a05ae758 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:09:01 -0800 Subject: [SCTP]: sctp_init_addrs() switched to net-endian. Caller adjusted. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/input.c | 2 +- net/sctp/sm_make_chunk.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/input.c b/net/sctp/input.c index 85b3441c4a23..0e5ac5e42c96 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -245,7 +245,7 @@ int sctp_rcv(struct sk_buff *skb) chunk->sctp_hdr = sh; /* Set the source and destination addresses of the incoming chunk. */ - sctp_init_addrs(chunk, &src, &dest); + sctp_init_addrs(chunk, &tmp2, &tmp); /* Remember where we came from. */ chunk->transport = transport; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index cb8cecd85a2e..b5d4a61ed7a7 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1031,9 +1031,9 @@ nodata: void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, union sctp_addr *dest) { - memcpy(&chunk->source_h, src, sizeof(union sctp_addr)); - flip_to_n(&chunk->source, &chunk->source_h); - memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); + memcpy(&chunk->source, src, sizeof(union sctp_addr)); + flip_to_h(&chunk->source_h, &chunk->source); + flip_to_h(&chunk->dest, dest); } /* Extract the source address from a chunk. */ -- cgit v1.2.3-70-g09d2 From 9b1dfad011d409bc56476a81810342751645ee54 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:09:17 -0800 Subject: [SCTP]: Switch sctp_cookie ->peer_addr to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 6 ++++-- net/sctp/sm_statefuns.c | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b5d4a61ed7a7..59536368f79a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1227,6 +1227,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sk_buff *skb; sctp_scope_t scope; struct sctp_af *af; + union sctp_addr tmp; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1239,7 +1240,8 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); if (unlikely(!af)) goto fail; - af->from_skb(&asoc->c.peer_addr, skb, 1); + af->from_skb(&tmp, skb, 1); + flip_to_n(&asoc->c.peer_addr, &tmp); nodata: return asoc; @@ -1439,7 +1441,7 @@ no_hmac: goto fail; } - if (ntohs(chunk->sctp_hdr->source) != bear_cookie->peer_addr.v4.sin_port || + if (chunk->sctp_hdr->source != bear_cookie->peer_addr.v4.sin_port || ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) { *error = -SCTP_IERROR_BAD_PORTS; goto fail; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 0848309773a5..174acc3c5526 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -598,6 +598,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, struct sctp_ulpevent *ev, *ai_ev = NULL; int error = 0; struct sctp_chunk *err_chk_p; + union sctp_addr tmp; /* If the packet is an OOTB packet which is temporarily on the * control endpoint, respond with an ABORT. @@ -665,8 +666,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; + flip_to_h(&tmp, &chunk->subh.cookie_hdr->c.peer_addr); if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - &chunk->subh.cookie_hdr->c.peer_addr, + &tmp, peer_init, GFP_ATOMIC)) goto nomem_init; -- cgit v1.2.3-70-g09d2 From d55c41b115e74b30a3d1a61db806bd03bdd9dd6f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:09:40 -0800 Subject: [SCTP]: Switch ->from_skb() to net-endian. All instances switched, callers updated. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/input.c | 15 ++++----------- net/sctp/ipv6.c | 6 +++--- net/sctp/protocol.c | 6 +++--- net/sctp/sm_make_chunk.c | 4 +--- 4 files changed, 11 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/net/sctp/input.c b/net/sctp/input.c index 0e5ac5e42c96..3b4a552c9f18 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -127,7 +127,6 @@ int sctp_rcv(struct sk_buff *skb) struct sctphdr *sh; union sctp_addr src; union sctp_addr dest; - union sctp_addr tmp, tmp2; int family; struct sctp_af *af; @@ -179,13 +178,10 @@ int sctp_rcv(struct sk_buff *skb) !af->addr_valid(&dest, NULL, skb)) goto discard_it; - flip_to_n(&tmp, &dest); - flip_to_n(&tmp2, &src); - - asoc = __sctp_rcv_lookup(skb, &tmp2, &tmp, &transport); + asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); if (!asoc) - ep = __sctp_rcv_lookup_endpoint(&tmp); + ep = __sctp_rcv_lookup_endpoint(&dest); /* Retrieve the common input handling substructure. */ rcvr = asoc ? &asoc->base : &ep->base; @@ -245,7 +241,7 @@ int sctp_rcv(struct sk_buff *skb) chunk->sctp_hdr = sh; /* Set the source and destination addresses of the incoming chunk. */ - sctp_init_addrs(chunk, &tmp2, &tmp); + sctp_init_addrs(chunk, &src, &dest); /* Remember where we came from. */ chunk->transport = transport; @@ -444,7 +440,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, struct sock *sk = NULL; struct sctp_association *asoc; struct sctp_transport *transport = NULL; - union sctp_addr tmp, tmp2; *app = NULL; *tpp = NULL; @@ -456,13 +451,11 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, /* Initialize local addresses for lookups. */ af->from_skb(&saddr, skb, 1); af->from_skb(&daddr, skb, 0); - flip_to_n(&tmp, &saddr); - flip_to_n(&tmp2, &daddr); /* Look for an association that matches the incoming ICMP error * packet. */ - asoc = __sctp_lookup_association(&tmp, &tmp2, &transport); + asoc = __sctp_lookup_association(&saddr, &daddr, &transport); if (!asoc) return NULL; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 6139d1d964eb..d6b585b85cbb 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -351,7 +351,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, int is_saddr) { void *from; - __u16 *port; + __be16 *port; struct sctphdr *sh; port = &addr->v6.sin6_port; @@ -361,10 +361,10 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, sh = (struct sctphdr *) skb->h.raw; if (is_saddr) { - *port = ntohs(sh->source); + *port = sh->source; from = &skb->nh.ipv6h->saddr; } else { - *port = ntohs(sh->dest); + *port = sh->dest; from = &skb->nh.ipv6h->daddr; } ipv6_addr_copy(&addr->v6.sin6_addr, from); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d1fbd1f5c6d1..d08bafd4439e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -252,7 +252,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, int is_saddr) { void *from; - __u16 *port; + __be16 *port; struct sctphdr *sh; port = &addr->v4.sin_port; @@ -260,10 +260,10 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, sh = (struct sctphdr *) skb->h.raw; if (is_saddr) { - *port = ntohs(sh->source); + *port = sh->source; from = &skb->nh.iph->saddr; } else { - *port = ntohs(sh->dest); + *port = sh->dest; from = &skb->nh.iph->daddr; } memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 59536368f79a..632a1159610e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1227,7 +1227,6 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sk_buff *skb; sctp_scope_t scope; struct sctp_af *af; - union sctp_addr tmp; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1240,8 +1239,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); if (unlikely(!af)) goto fail; - af->from_skb(&tmp, skb, 1); - flip_to_n(&asoc->c.peer_addr, &tmp); + af->from_skb(&asoc->c.peer_addr, skb, 1); nodata: return asoc; -- cgit v1.2.3-70-g09d2 From b488c7dd58f61e07b54e5d286c7b45c43dd52f1a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:10:03 -0800 Subject: [SCTP]: sctp_transport_{init,new}() switched to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 2 +- net/sctp/sm_statefuns.c | 4 +++- net/sctp/transport.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 4bd916c808c1..7824aeaa3d60 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -564,7 +564,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, return peer; } - peer = sctp_transport_new(addr, gfp); + peer = sctp_transport_new(&tmp, gfp); if (!peer) return NULL; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 174acc3c5526..c5362638d672 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5105,6 +5105,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc __u16 sport; __u16 dport; __u32 vtag; + union sctp_addr tmp; /* Get the source and destination port from the inbound packet. */ sport = ntohs(chunk->sctp_hdr->dest); @@ -5135,7 +5136,8 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc } /* Make a transport for the bucket, Eliza... */ - transport = sctp_transport_new(sctp_source(chunk), GFP_ATOMIC); + flip_to_n(&tmp, sctp_source(chunk)); + transport = sctp_transport_new(&tmp, GFP_ATOMIC); if (!transport) goto nomem; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index bacd09448b8e..e1448addcd93 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -61,8 +61,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, gfp_t gfp) { /* Copy in the address. */ - peer->ipaddr_h = *addr; - flip_to_n(&peer->ipaddr, &peer->ipaddr_h); + peer->ipaddr = *addr; + flip_to_h(&peer->ipaddr_h, &peer->ipaddr); peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; -- cgit v1.2.3-70-g09d2 From 4bdf4b5fe22c26750c39fdd2939a5f33df0cc341 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:10:20 -0800 Subject: [SCTP]: Switch sctp_assoc_add_peer() to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 12 +++++------- net/sctp/sm_make_chunk.c | 15 ++++++++++----- net/sctp/socket.c | 13 ++++++------- 3 files changed, 21 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 7824aeaa3d60..5b8971be9775 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -533,19 +533,17 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, struct sctp_transport *peer; struct sctp_sock *sp; unsigned short port; - union sctp_addr tmp; - flip_to_n(&tmp, addr); sp = sctp_sk(asoc->base.sk); /* AF_INET and AF_INET6 share common port field. */ - port = addr->v4.sin_port; + port = ntohs(addr->v4.sin_port); SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", " port: %d state:%d\n", asoc, addr, - addr->v4.sin_port, + port, peer_state); /* Set the port if it has not been set yet. */ @@ -553,7 +551,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, asoc->peer.port = port; /* Check to see if this is a duplicate. */ - peer = sctp_assoc_lookup_paddr(asoc, &tmp); + peer = sctp_assoc_lookup_paddr(asoc, addr); if (peer) { if (peer->state == SCTP_UNKNOWN) { if (peer_state == SCTP_ACTIVE) @@ -564,7 +562,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, return peer; } - peer = sctp_transport_new(&tmp, gfp); + peer = sctp_transport_new(addr, gfp); if (!peer) return NULL; @@ -1070,7 +1068,7 @@ void sctp_assoc_update(struct sctp_association *asoc, trans = list_entry(pos, struct sctp_transport, transports); if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) - sctp_assoc_add_peer(asoc, &trans->ipaddr_h, + sctp_assoc_add_peer(asoc, &trans->ipaddr, GFP_ATOMIC, trans->state); } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 632a1159610e..2c887d3f3911 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1842,6 +1842,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, struct sctp_transport *transport; struct list_head *pos, *temp; char *cookie; + union sctp_addr tmp; /* We must include the address that the INIT packet came from. * This is the only address that matters for an INIT packet. @@ -1853,9 +1854,11 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * added as the primary transport. The source address seems to * be a a better choice than any of the embedded addresses. */ - if (peer_addr) - if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) + if (peer_addr) { + flip_to_n(&tmp, peer_addr); + if(!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_ACTIVE)) goto nomem; + } /* Process the initialization parameters. */ @@ -2016,6 +2019,7 @@ static int sctp_process_param(struct sctp_association *asoc, sctp_scope_t scope; time_t stale; struct sctp_af *af; + union sctp_addr tmp; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -2029,9 +2033,10 @@ static int sctp_process_param(struct sctp_association *asoc, case SCTP_PARAM_IPV4_ADDRESS: af = sctp_get_af_specific(param_type2af(param.p->type)); af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); + flip_to_n(&tmp, &addr); scope = sctp_scope(peer_addr); - if (sctp_in_scope(&addr, scope)) - if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) + if (sctp_in_scope(&tmp, scope)) + if (!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_UNCONFIRMED)) return 0; break; @@ -2434,7 +2439,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * Due to Resource Shortage'. */ - peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED); + peer = sctp_assoc_add_peer(asoc, &tmp_addr, GFP_ATOMIC, SCTP_UNCONFIRMED); if (!peer) return SCTP_ERROR_RSRC_LOW; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f00b03845247..3dd7ada8026c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -969,7 +969,7 @@ static int __sctp_connect(struct sock* sk, int err = 0; int addrcnt = 0; int walk_size = 0; - struct sockaddr *sa_addr; + union sctp_addr *sa_addr; void *addr_buf; sp = sctp_sk(sk); @@ -989,8 +989,8 @@ static int __sctp_connect(struct sock* sk, /* Walk through the addrs buffer and count the number of addresses. */ addr_buf = kaddrs; while (walk_size < addrs_size) { - sa_addr = (struct sockaddr *)addr_buf; - af = sctp_get_af_specific(sa_addr->sa_family); + sa_addr = (union sctp_addr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa.sa_family); /* If the address family is not supported or if this address * causes the address buffer to overflow return EINVAL. @@ -1000,8 +1000,7 @@ static int __sctp_connect(struct sock* sk, goto out_free; } - err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, - af->sockaddr_len); + err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); if (err) goto out_free; @@ -1064,7 +1063,7 @@ static int __sctp_connect(struct sock* sk, } /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, + transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; @@ -1618,7 +1617,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); + transport = sctp_assoc_add_peer(asoc, &tmp, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; goto out_free; -- cgit v1.2.3-70-g09d2 From 5ab7b859ab58e3479a5a66e383ecd6bc447f6c1d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:10:38 -0800 Subject: [SCTP]: Switch sctp_add_bind_addr() to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 16 ++++++++++------ net/sctp/protocol.c | 2 +- net/sctp/sm_make_chunk.c | 4 +++- net/sctp/socket.c | 5 +---- 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index eafdd11152d0..eb3a5e25777d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -155,15 +155,15 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, if (!addr) return -ENOMEM; - memcpy(&addr->a_h, new, sizeof(*new)); + memcpy(&addr->a, new, sizeof(*new)); /* Fix up the port if it has not yet been set. * Both v4 and v6 have the port at the same offset. */ - if (!addr->a_h.v4.sin_port) - addr->a_h.v4.sin_port = bp->port; + if (!addr->a.v4.sin_port) + addr->a.v4.sin_port = htons(bp->port); - flip_to_n(&addr->a, &addr->a_h); + flip_to_h(&addr->a_h, &addr->a); addr->use_as_src = use_as_src; @@ -264,6 +264,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, int retval = 0; int len; struct sctp_af *af; + union sctp_addr tmp; /* Convert the raw address to standard address format */ while (addrs_len) { @@ -278,7 +279,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, } af->from_addr_param(&addr, rawaddr, port, 0); - retval = sctp_add_bind_addr(bp, &addr, 1, gfp); + flip_to_n(&tmp, &addr); + retval = sctp_add_bind_addr(bp, &tmp, 1, gfp); if (retval) { /* Can't finish building the list, clean up. */ sctp_bind_addr_clean(bp); @@ -358,6 +360,8 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, int flags) { int error = 0; + union sctp_addr tmp; + flip_to_n(&tmp, addr); if (sctp_is_any(addr)) { error = sctp_copy_local_addr_list(dest, scope, gfp, flags); @@ -371,7 +375,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, (((AF_INET6 == addr->sa.sa_family) && (flags & SCTP_ADDR6_ALLOWED) && (flags & SCTP_ADDR6_PEERSUPP)))) - error = sctp_add_bind_addr(dest, addr, 1, gfp); + error = sctp_add_bind_addr(dest, &tmp, 1, gfp); } return error; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d08bafd4439e..a6bcbf560e36 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -234,7 +234,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, (((AF_INET6 == addr->a_h.sa.sa_family) && (copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_PEERSUPP)))) { - error = sctp_add_bind_addr(bp, &addr->a_h, 1, + error = sctp_add_bind_addr(bp, &addr->a, 1, GFP_ATOMIC); if (error) goto end_copy; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 2c887d3f3911..46cfcca5e41b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1507,7 +1507,9 @@ no_hmac: /* Also, add the destination address. */ if (list_empty(&retval->base.bind_addr.address_list)) { - sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1, + union sctp_addr tmp; + flip_to_n(&tmp, &chunk->dest); + sctp_add_bind_addr(&retval->base.bind_addr, &tmp, 1, GFP_ATOMIC); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3dd7ada8026c..d09589a51c44 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -313,7 +313,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) struct sctp_af *af; unsigned short snum; int ret = 0; - union sctp_addr tmp; /* Common sockaddr verification. */ af = sctp_sockaddr_af(sp, addr, len); @@ -369,8 +368,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) sctp_write_lock(&ep->base.addr_lock); /* Use GFP_ATOMIC since BHs are disabled. */ - flip_to_h(&tmp, addr); - ret = sctp_add_bind_addr(bp, &tmp, 1, GFP_ATOMIC); + ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); @@ -572,7 +570,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk, addr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(addr->v4.sin_family); memcpy(&saveaddr, addr, af->sockaddr_len); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); retval = sctp_add_bind_addr(bp, &saveaddr, 0, GFP_ATOMIC); addr_buf += af->sockaddr_len; -- cgit v1.2.3-70-g09d2 From dd86d136f9feb72c52a5b07707affe80edbc8dda Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:11:13 -0800 Subject: [SCTP]: Switch ->from_addr_param() to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/bind_addr.c | 6 ++---- net/sctp/input.c | 6 ++---- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- net/sctp/sm_make_chunk.c | 29 ++++++++++++----------------- 6 files changed, 19 insertions(+), 28 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 1616a38a0be3..8f6619dbb666 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -575,7 +575,7 @@ struct sctp_af { struct sock *sk); void (*from_addr_param) (union sctp_addr *, union sctp_addr_param *, - __u16 port, int iif); + __be16 port, int iif); int (*to_addr_param) (const union sctp_addr *, union sctp_addr_param *); int (*addr_valid) (union sctp_addr *, diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index eb3a5e25777d..fd0f812f8a46 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -264,7 +264,6 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, int retval = 0; int len; struct sctp_af *af; - union sctp_addr tmp; /* Convert the raw address to standard address format */ while (addrs_len) { @@ -278,9 +277,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, break; } - af->from_addr_param(&addr, rawaddr, port, 0); - flip_to_n(&tmp, &addr); - retval = sctp_add_bind_addr(bp, &tmp, 1, gfp); + af->from_addr_param(&addr, rawaddr, htons(port), 0); + retval = sctp_add_bind_addr(bp, &addr, 1, gfp); if (retval) { /* Can't finish building the list, clean up. */ sctp_bind_addr_clean(bp); diff --git a/net/sctp/input.c b/net/sctp/input.c index 3b4a552c9f18..2d660f8d94fd 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -914,7 +914,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, sctp_init_chunk_t *init; struct sctp_transport *transport; struct sctp_af *af; - union sctp_addr tmp2; ch = (sctp_chunkhdr_t *) skb->data; @@ -961,10 +960,9 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, if (!af) continue; - af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); - flip_to_n(&tmp2, paddr); + af->from_addr_param(paddr, params.addr, sh->source, 0); - asoc = __sctp_lookup_association(laddr, &tmp2, &transport); + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index d6b585b85cbb..566cdc9977c4 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -408,7 +408,7 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) /* Initialize a sctp_addr from an address parameter. */ static void sctp_v6_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, - __u16 port, int iif) + __be16 port, int iif) { addr->v6.sin6_family = AF_INET6; addr->v6.sin6_port = port; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a6bcbf560e36..87d36f440d1d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -292,7 +292,7 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) /* Initialize a sctp_addr from an address parameter. */ static void sctp_v4_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, - __u16 port, int iif) + __be16 port, int iif) { addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 46cfcca5e41b..b367ad59ed4a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2021,7 +2021,6 @@ static int sctp_process_param(struct sctp_association *asoc, sctp_scope_t scope; time_t stale; struct sctp_af *af; - union sctp_addr tmp; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -2034,11 +2033,10 @@ static int sctp_process_param(struct sctp_association *asoc, /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: af = sctp_get_af_specific(param_type2af(param.p->type)); - af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); - flip_to_n(&tmp, &addr); + af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); scope = sctp_scope(peer_addr); - if (sctp_in_scope(&tmp, scope)) - if (!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_UNCONFIRMED)) + if (sctp_in_scope(&addr, scope)) + if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) return 0; break; @@ -2421,7 +2419,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, union sctp_addr addr; struct list_head *pos; union sctp_addr_param *addr_param; - union sctp_addr tmp, tmp_addr; + union sctp_addr tmp; addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); @@ -2430,8 +2428,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (unlikely(!af)) return SCTP_ERROR_INV_PARAM; - af->from_addr_param(&addr, addr_param, asoc->peer.port, 0); - flip_to_n(&tmp_addr, &addr); + af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address @@ -2441,7 +2438,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * Due to Resource Shortage'. */ - peer = sctp_assoc_add_peer(asoc, &tmp_addr, GFP_ATOMIC, SCTP_UNCONFIRMED); + peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED); if (!peer) return SCTP_ERROR_RSRC_LOW; @@ -2467,13 +2464,13 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * Delete Source IP Address' */ flip_to_n(&tmp, sctp_source(asconf)); - if (sctp_cmp_addr_exact(&tmp, &tmp_addr)) + if (sctp_cmp_addr_exact(&tmp, &addr)) return SCTP_ERROR_DEL_SRC_IP; - sctp_assoc_del_peer(asoc, &tmp_addr); + sctp_assoc_del_peer(asoc, &addr); break; case SCTP_PARAM_SET_PRIMARY: - peer = sctp_assoc_lookup_paddr(asoc, &tmp_addr); + peer = sctp_assoc_lookup_paddr(asoc, &addr); if (!peer) return SCTP_ERROR_INV_PARAM; @@ -2591,15 +2588,13 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, struct sctp_transport *transport; struct sctp_sockaddr_entry *saddr; int retval = 0; - union sctp_addr tmp; addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); /* We have checked the packet before, so we do not check again. */ af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); - af->from_addr_param(&addr, addr_param, bp->port, 0); - flip_to_n(&tmp, &addr); + af->from_addr_param(&addr, addr_param, htons(bp->port), 0); switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: @@ -2607,7 +2602,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, sctp_write_lock(&asoc->base.addr_lock); list_for_each(pos, &bp->address_list) { saddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_cmp_addr_exact(&saddr->a, &tmp)) + if (sctp_cmp_addr_exact(&saddr->a, &addr)) saddr->use_as_src = 1; } sctp_write_unlock(&asoc->base.addr_lock); @@ -2616,7 +2611,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, case SCTP_PARAM_DEL_IP: sctp_local_bh_disable(); sctp_write_lock(&asoc->base.addr_lock); - retval = sctp_del_bind_addr(bp, &tmp); + retval = sctp_del_bind_addr(bp, &addr); sctp_write_unlock(&asoc->base.addr_lock); sctp_local_bh_enable(); list_for_each(pos, &asoc->peer.transport_addr_list) { -- cgit v1.2.3-70-g09d2 From cd4ff034e3572679f7ff8f126469b3addd1a4fbc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:11:33 -0800 Subject: [SCTP]: sctp_endpoint_lookup_assoc() switched to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 10 +++++----- net/sctp/socket.c | 8 +++----- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index c543f3250645..5ffb1af336c0 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -257,16 +257,14 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( int rport; struct sctp_association *asoc; struct list_head *pos; - union sctp_addr tmp; - flip_to_n(&tmp, paddr); - rport = paddr->v4.sin_port; + rport = ntohs(paddr->v4.sin_port); list_for_each(pos, &ep->asocs) { asoc = list_entry(pos, struct sctp_association, asocs); if (rport == asoc->peer.port) { sctp_read_lock(&asoc->base.addr_lock); - *transport = sctp_assoc_lookup_paddr(asoc, &tmp); + *transport = sctp_assoc_lookup_paddr(asoc, paddr); sctp_read_unlock(&asoc->base.addr_lock); if (*transport) @@ -348,8 +346,10 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep) * COOKIE-ECHO chunk. */ if (NULL == chunk->asoc) { + union sctp_addr tmp; + flip_to_n(&tmp, sctp_source(chunk)); asoc = sctp_endpoint_lookup_assoc(ep, - sctp_source(chunk), + &tmp, &transport); chunk->asoc = asoc; chunk->transport = transport; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d09589a51c44..6beaa7821ca6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -228,11 +228,9 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; struct sctp_transport *transport; union sctp_addr *laddr = (union sctp_addr *)addr; - union sctp_addr tmp; - flip_to_h(&tmp, laddr); addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, - &tmp, + laddr, &transport); if (!addr_asoc) @@ -1007,7 +1005,7 @@ static int __sctp_connect(struct sock* sk, /* Check if there already is a matching association on the * endpoint (other than the one created here). */ - asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); + asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); if (asoc2 && asoc2 != asoc) { if (asoc2->state >= SCTP_STATE_ESTABLISHED) err = -EISCONN; @@ -1468,7 +1466,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* If a msg_name has been specified, assume this is to be used. */ if (msg_name) { /* Look for a matching association on the endpoint. */ - asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); + asoc = sctp_endpoint_lookup_assoc(ep, &tmp, &transport); if (!asoc) { /* If we could not find a matching association on the * endpoint, make sure that it is not a TCP-style -- cgit v1.2.3-70-g09d2 From 6c7be55ca0c204473d07a030a03c49a7471b4508 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:11:50 -0800 Subject: [SCTP]: sctp_has_association() switched to net-endian. Ditto for its only caller (sctp_endpoint_is_peeled_off) Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 2 +- net/sctp/input.c | 5 +---- net/sctp/socket.c | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 5ffb1af336c0..4cca7792c961 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -305,7 +305,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, bp = &ep->base.bind_addr; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_has_association(&addr->a_h, paddr)) { + if (sctp_has_association(&addr->a, paddr)) { sctp_read_unlock(&ep->base.addr_lock); return 1; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 2d660f8d94fd..33111873a488 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -872,11 +872,8 @@ int sctp_has_association(const union sctp_addr *laddr, { struct sctp_association *asoc; struct sctp_transport *transport; - union sctp_addr tmp, tmp2; - flip_to_n(&tmp, laddr); - flip_to_n(&tmp2, paddr); - if ((asoc = sctp_lookup_association(&tmp, &tmp2, &transport))) { + if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { sctp_association_put(asoc); return 1; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6beaa7821ca6..e118e3c1285e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1018,7 +1018,7 @@ static int __sctp_connect(struct sock* sk, * make sure that there is no peeled-off association matching * the peer address even on another socket. */ - if (sctp_endpoint_is_peeled_off(ep, &to)) { + if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { err = -EADDRNOTAVAIL; goto out_free; } @@ -1475,7 +1475,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, */ if ((sctp_style(sk, TCP) && sctp_sstate(sk, ESTABLISHED)) || - sctp_endpoint_is_peeled_off(ep, &to)) { + sctp_endpoint_is_peeled_off(ep, &tmp)) { err = -EADDRNOTAVAIL; goto out_unlock; } -- cgit v1.2.3-70-g09d2 From 02a8a4db3b38ad2dd8bcfcca41694e043e44d282 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:12:07 -0800 Subject: [SCTP]: sctp_copy_one_addr() switched to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index fd0f812f8a46..50f3697625fd 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -77,7 +77,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, /* Extract the addresses which are relevant for this scope. */ list_for_each(pos, &src->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - error = sctp_copy_one_addr(dest, &addr->a_h, scope, + error = sctp_copy_one_addr(dest, &addr->a, scope, gfp, flags); if (error < 0) goto out; @@ -91,7 +91,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, list_for_each(pos, &src->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - error = sctp_copy_one_addr(dest, &addr->a_h, + error = sctp_copy_one_addr(dest, &addr->a, SCTP_SCOPE_LINK, gfp, flags); if (error < 0) @@ -358,8 +358,6 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, int flags) { int error = 0; - union sctp_addr tmp; - flip_to_n(&tmp, addr); if (sctp_is_any(addr)) { error = sctp_copy_local_addr_list(dest, scope, gfp, flags); @@ -373,7 +371,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, (((AF_INET6 == addr->sa.sa_family) && (flags & SCTP_ADDR6_ALLOWED) && (flags & SCTP_ADDR6_PEERSUPP)))) - error = sctp_add_bind_addr(dest, &tmp, 1, gfp); + error = sctp_add_bind_addr(dest, addr, 1, gfp); } return error; -- cgit v1.2.3-70-g09d2 From 6a1e5f335461567f593e88b218f1c06817cbd323 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:12:25 -0800 Subject: [SCTP]: sctp_process_init() and sctp_source() switched to net-endian. both are done in one go since almost always we have result of the latter immediately passed to the former. Possibly non-obvious note: sctp_process_param() is endian-agnostic Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 4 +--- net/sctp/sm_make_chunk.c | 12 ++++-------- net/sctp/sm_statefuns.c | 8 ++------ 3 files changed, 7 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 4cca7792c961..33a42e90c32f 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -346,10 +346,8 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep) * COOKIE-ECHO chunk. */ if (NULL == chunk->asoc) { - union sctp_addr tmp; - flip_to_n(&tmp, sctp_source(chunk)); asoc = sctp_endpoint_lookup_assoc(ep, - &tmp, + sctp_source(chunk), &transport); chunk->asoc = asoc; chunk->transport = transport; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b367ad59ed4a..44ddec90995e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1041,10 +1041,10 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) { /* If we have a known transport, use that. */ if (chunk->transport) { - return &chunk->transport->ipaddr_h; + return &chunk->transport->ipaddr; } else { /* Otherwise, extract it from the IP header. */ - return &chunk->source_h; + return &chunk->source; } } @@ -1844,7 +1844,6 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, struct sctp_transport *transport; struct list_head *pos, *temp; char *cookie; - union sctp_addr tmp; /* We must include the address that the INIT packet came from. * This is the only address that matters for an INIT packet. @@ -1857,8 +1856,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * be a a better choice than any of the embedded addresses. */ if (peer_addr) { - flip_to_n(&tmp, peer_addr); - if(!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_ACTIVE)) + if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) goto nomem; } @@ -2419,7 +2417,6 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, union sctp_addr addr; struct list_head *pos; union sctp_addr_param *addr_param; - union sctp_addr tmp; addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); @@ -2463,8 +2460,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * an Error Cause TLV set to the new error code 'Request to * Delete Source IP Address' */ - flip_to_n(&tmp, sctp_source(asconf)); - if (sctp_cmp_addr_exact(&tmp, &addr)) + if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) return SCTP_ERROR_DEL_SRC_IP; sctp_assoc_del_peer(asoc, &addr); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index c5362638d672..0848309773a5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -598,7 +598,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, struct sctp_ulpevent *ev, *ai_ev = NULL; int error = 0; struct sctp_chunk *err_chk_p; - union sctp_addr tmp; /* If the packet is an OOTB packet which is temporarily on the * control endpoint, respond with an ABORT. @@ -666,9 +665,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - flip_to_h(&tmp, &chunk->subh.cookie_hdr->c.peer_addr); if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - &tmp, + &chunk->subh.cookie_hdr->c.peer_addr, peer_init, GFP_ATOMIC)) goto nomem_init; @@ -5105,7 +5103,6 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc __u16 sport; __u16 dport; __u32 vtag; - union sctp_addr tmp; /* Get the source and destination port from the inbound packet. */ sport = ntohs(chunk->sctp_hdr->dest); @@ -5136,8 +5133,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc } /* Make a transport for the bucket, Eliza... */ - flip_to_n(&tmp, sctp_source(chunk)); - transport = sctp_transport_new(&tmp, GFP_ATOMIC); + transport = sctp_transport_new(sctp_source(chunk), GFP_ATOMIC); if (!transport) goto nomem; -- cgit v1.2.3-70-g09d2 From d3f7a54a295f2ffc9033b425c6538a7e9d7fbe8a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:12:41 -0800 Subject: [SCTP]: ->get_saddr() switched to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 4 ++-- net/sctp/protocol.c | 2 +- net/sctp/transport.c | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 566cdc9977c4..7f4c5bafea14 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -292,9 +292,9 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, if ((laddr->use_as_src) && (laddr->a_h.sa.sa_family == AF_INET6) && (scope <= sctp_scope(&laddr->a_h))) { - bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a_h); + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); if (!baddr || (matchlen < bmatchlen)) { - baddr = &laddr->a_h; + baddr = &laddr->a; matchlen = bmatchlen; } } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 87d36f440d1d..5b8b7f3598e0 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -539,7 +539,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc, if (rt) { saddr->v4.sin_family = AF_INET; - saddr->v4.sin_port = asoc->base.bind_addr.port; + saddr->v4.sin_port = htons(asoc->base.bind_addr.port); saddr->v4.sin_addr.s_addr = rt->rt_src; } } diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e1448addcd93..74faa1b6dbfe 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -256,11 +256,13 @@ void sctp_transport_route(struct sctp_transport *transport, dst = af->get_dst(asoc, daddr, saddr); - if (saddr) + if (saddr) { memcpy(&transport->saddr_h, saddr, sizeof(union sctp_addr)); - else - af->get_saddr(asoc, dst, daddr, &transport->saddr_h); - flip_to_n(&transport->saddr, &transport->saddr_h); + flip_to_n(&transport->saddr, &transport->saddr_h); + } else { + af->get_saddr(asoc, dst, &transport->ipaddr, &transport->saddr); + flip_to_h(&transport->saddr_h, &transport->saddr); + } transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { -- cgit v1.2.3-70-g09d2 From cb7b4a0dcf67ae747406b58b1cdc875916019739 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:13:01 -0800 Subject: [SCTP]: Pass net-endian to ->get_dst(). all instances are actually endian-agnostic... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/transport.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 74faa1b6dbfe..33e7d85f1119 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -234,7 +234,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport) { struct dst_entry *dst; - dst = transport->af_specific->get_dst(NULL, &transport->ipaddr_h, NULL); + dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); if (dst) { transport->pathmtu = dst_mtu(dst); @@ -251,16 +251,18 @@ void sctp_transport_route(struct sctp_transport *transport, { struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; - union sctp_addr *daddr = &transport->ipaddr_h; + union sctp_addr *daddr = &transport->ipaddr; struct dst_entry *dst; + union sctp_addr tmp; + flip_to_n(&tmp, saddr); - dst = af->get_dst(asoc, daddr, saddr); + dst = af->get_dst(asoc, daddr, &tmp); if (saddr) { memcpy(&transport->saddr_h, saddr, sizeof(union sctp_addr)); flip_to_n(&transport->saddr, &transport->saddr_h); } else { - af->get_saddr(asoc, dst, &transport->ipaddr, &transport->saddr); + af->get_saddr(asoc, dst, daddr, &transport->saddr); flip_to_h(&transport->saddr_h, &transport->saddr); } -- cgit v1.2.3-70-g09d2 From d448388bdaca946aa2b07973cb72a9b834e530bf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:13:21 -0800 Subject: [SCTP]: sctp_transport_route() switched to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 4 +++- net/sctp/transport.c | 14 +++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 0848309773a5..42377f75ee1c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5103,6 +5103,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc __u16 sport; __u16 dport; __u32 vtag; + union sctp_addr tmp; /* Get the source and destination port from the inbound packet. */ sport = ntohs(chunk->sctp_hdr->dest); @@ -5140,7 +5141,8 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc /* Cache a route for the transport with the chunk's destination as * the source address. */ - sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, + flip_to_n(&tmp, &chunk->dest); + sctp_transport_route(transport, &tmp, sctp_sk(sctp_get_ctl_sock())); packet = sctp_packet_init(&transport->packet, transport, sport, dport); diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 33e7d85f1119..d1b6834a3a47 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -253,19 +253,15 @@ void sctp_transport_route(struct sctp_transport *transport, struct sctp_af *af = transport->af_specific; union sctp_addr *daddr = &transport->ipaddr; struct dst_entry *dst; - union sctp_addr tmp; - flip_to_n(&tmp, saddr); - dst = af->get_dst(asoc, daddr, &tmp); + dst = af->get_dst(asoc, daddr, saddr); - if (saddr) { - memcpy(&transport->saddr_h, saddr, sizeof(union sctp_addr)); - flip_to_n(&transport->saddr, &transport->saddr_h); - } else { + if (saddr) + memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); + else af->get_saddr(asoc, dst, daddr, &transport->saddr); - flip_to_h(&transport->saddr_h, &transport->saddr); - } + flip_to_h(&transport->saddr_h, &transport->saddr); transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; -- cgit v1.2.3-70-g09d2 From 16b0a030330d179427edffbeddaa5b7dc5b31196 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:13:38 -0800 Subject: [SCTP]: Switch sctp_chunk ->dest to net-endian. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 6 ++---- net/sctp/sm_statefuns.c | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 44ddec90995e..beee1aa09e7a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1033,7 +1033,7 @@ void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, { memcpy(&chunk->source, src, sizeof(union sctp_addr)); flip_to_h(&chunk->source_h, &chunk->source); - flip_to_h(&chunk->dest, dest); + memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); } /* Extract the source address from a chunk. */ @@ -1507,9 +1507,7 @@ no_hmac: /* Also, add the destination address. */ if (list_empty(&retval->base.bind_addr.address_list)) { - union sctp_addr tmp; - flip_to_n(&tmp, &chunk->dest); - sctp_add_bind_addr(&retval->base.bind_addr, &tmp, 1, + sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1, GFP_ATOMIC); } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 42377f75ee1c..0848309773a5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5103,7 +5103,6 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc __u16 sport; __u16 dport; __u32 vtag; - union sctp_addr tmp; /* Get the source and destination port from the inbound packet. */ sport = ntohs(chunk->sctp_hdr->dest); @@ -5141,8 +5140,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc /* Cache a route for the transport with the chunk's destination as * the source address. */ - flip_to_n(&tmp, &chunk->dest); - sctp_transport_route(transport, &tmp, + sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, sctp_sk(sctp_get_ctl_sock())); packet = sctp_packet_init(&transport->packet, transport, sport, dport); -- cgit v1.2.3-70-g09d2 From a926626893aca20567f27af1c5edc830e1c51b2b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:13:58 -0800 Subject: [SCTP]: Switch all remaining users of ->saddr_h to ->saddr. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 - net/sctp/ipv6.c | 4 ++-- net/sctp/transport.c | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 8f6619dbb666..275195620145 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -904,7 +904,6 @@ struct sctp_transport { struct dst_entry *dst; /* Source address. */ union sctp_addr saddr; - union sctp_addr saddr_h; /* When was the last time(in jiffies) that a data packet was sent on * this transport? This is used to adjust the cwnd when the transport diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 7f4c5bafea14..3dc8ed143521 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -162,12 +162,12 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, * and the source address from the transport. */ ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr_h.v6.sin6_addr); - ipv6_addr_copy(&fl.fl6_src, &transport->saddr_h.v6.sin6_addr); + ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr); fl.fl6_flowlabel = np->flow_label; IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); if (ipv6_addr_type(&fl.fl6_src) & IPV6_ADDR_LINKLOCAL) - fl.oif = transport->saddr_h.v6.sin6_scope_id; + fl.oif = transport->saddr.v6.sin6_scope_id; else fl.oif = sk->sk_bound_dev_if; fl.fl_ip_sport = inet_sk(sk)->sport; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d1b6834a3a47..05ab5e9c7c47 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -68,7 +68,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, peer->dst = NULL; memset(&peer->saddr, 0, sizeof(union sctp_addr)); - memset(&peer->saddr_h, 0, sizeof(union sctp_addr)); /* From 6.3.1 RTO Calculation: * @@ -261,7 +260,6 @@ void sctp_transport_route(struct sctp_transport *transport, else af->get_saddr(asoc, dst, daddr, &transport->saddr); - flip_to_h(&transport->saddr_h, &transport->saddr); transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; @@ -273,7 +271,7 @@ void sctp_transport_route(struct sctp_transport *transport, * association's active path for getsockname(). */ if (asoc && (transport == asoc->peer.active_path)) - opt->pf->af->to_sk_saddr(&transport->saddr_h, + opt->pf->af->to_sk_saddr(&transport->saddr, asoc->base.sk); } else transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; -- cgit v1.2.3-70-g09d2 From 80f15d62418040e78849f5fc3a4a5af9c9d1fec7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:14:23 -0800 Subject: [SCTP]: ->source_h is not used anymore. kill it Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 - net/sctp/sm_make_chunk.c | 1 - 2 files changed, 2 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 275195620145..9bb5c038b95a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -714,7 +714,6 @@ struct sctp_chunk { /* What is the origin IP address for this chunk? */ union sctp_addr source; - union sctp_addr source_h; /* Destination address for this chunk. */ union sctp_addr dest; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index beee1aa09e7a..9d55497627f6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1032,7 +1032,6 @@ void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src, union sctp_addr *dest) { memcpy(&chunk->source, src, sizeof(union sctp_addr)); - flip_to_h(&chunk->source_h, &chunk->source); memcpy(&chunk->dest, dest, sizeof(union sctp_addr)); } -- cgit v1.2.3-70-g09d2 From 6244be4e063075f6077f05e70f8fa1bf7f4a968e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:21:44 -0800 Subject: [SCTP]: Trivial parts of a_h -> a switch. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 4 ++-- net/sctp/ipv6.c | 4 ++-- net/sctp/protocol.c | 10 +++++----- net/sctp/socket.c | 24 ++++++++++-------------- 4 files changed, 19 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 50f3697625fd..f201df66180d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -239,8 +239,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - af = sctp_get_af_specific(addr->a_h.v4.sin_family); - len = af->to_addr_param(&addr->a_h, &rawaddr); + af = sctp_get_af_specific(addr->a.v4.sin_family); + len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3dc8ed143521..b3fa426bd1dc 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -290,8 +290,8 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((laddr->use_as_src) && - (laddr->a_h.sa.sa_family == AF_INET6) && - (scope <= sctp_scope(&laddr->a_h))) { + (laddr->a.sa.sa_family == AF_INET6) && + (scope <= sctp_scope(&laddr->a))) { bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); if (!baddr || (matchlen < bmatchlen)) { baddr = &laddr->a; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5b8b7f3598e0..c20f05b3308f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -224,14 +224,14 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (sctp_in_scope(&addr->a_h, scope)) { + if (sctp_in_scope(&addr->a, scope)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local * sock as well as the remote peer. */ - if ((((AF_INET == addr->a_h.sa.sa_family) && + if ((((AF_INET == addr->a.sa.sa_family) && (copy_flags & SCTP_ADDR4_PEERSUPP))) || - (((AF_INET6 == addr->a_h.sa.sa_family) && + (((AF_INET6 == addr->a.sa.sa_family) && (copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_PEERSUPP)))) { error = sctp_add_bind_addr(bp, &addr->a, 1, @@ -503,8 +503,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, laddr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((laddr->use_as_src) && - (AF_INET == laddr->a_h.sa.sa_family)) { - fl.fl4_src = laddr->a_h.v4.sin_addr.s_addr; + (AF_INET == laddr->a.sa.sa_family)) { + fl.fl4_src = laddr->a.v4.sin_addr.s_addr; if (!ip_route_output_key(&rt, &fl)) { dst = &rt->u.dst; goto out_unlock; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e118e3c1285e..a3e1ca2c3cb7 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3867,14 +3867,14 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a_h)) { + if (sctp_is_any(&addr->a)) { sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a_h.sa.sa_family)) + (AF_INET6 == addr->a.sa.sa_family)) continue; cnt++; } @@ -3912,13 +3912,12 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a_h.sa.sa_family)) + (AF_INET6 == addr->a.sa.sa_family)) continue; - memcpy(&temp, &addr->a_h, sizeof(temp)); + memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - temp.v4.sin_port = htons(port); if (copy_to_user(to, &temp, addrlen)) { sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); @@ -3947,15 +3946,14 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if ((PF_INET == sk->sk_family) && - (AF_INET6 == addr->a_h.sa.sa_family)) + (AF_INET6 == addr->a.sa.sa_family)) continue; - memcpy(&temp, &addr->a_h, sizeof(temp)); + memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if(space_leftaddress_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a_h)) { + if (sctp_is_any(&addr->a)) { cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, getaddrs.addr_num, to); @@ -4037,10 +4035,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - memcpy(&temp, &addr->a_h, sizeof(temp)); + memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - temp.v4.sin_port = htons(temp.v4.sin_port); if (copy_to_user(to, &temp, addrlen)) { err = -EFAULT; goto unlock; @@ -4113,7 +4110,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a_h)) { + if (sctp_is_any(&addr->a)) { cnt = sctp_copy_laddrs_to_user(sk, bp->port, &to, space_left); if (cnt < 0) { @@ -4126,12 +4123,11 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - memcpy(&temp, &addr->a_h, sizeof(temp)); + memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if(space_left < addrlen) return -ENOMEM; /*fixme: right error?*/ - temp.v4.sin_port = htons(temp.v4.sin_port); if (copy_to_user(to, &temp, addrlen)) { err = -EFAULT; goto unlock; -- cgit v1.2.3-70-g09d2 From 5ae955cffdb96190c2bd4f57313f5f147f87854b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:22:08 -0800 Subject: [SCTP]: sctp_make_asconf_update_ip() and sctp_find_unmatch_addr(). ... switched to taking and returning pointers to net-endian sctp_addr resp. Together, since the only user of sctp_find_unmatch_addr() just passes its value to sctp_make_asconf_update_ip(). sctp_make_asconf_update_ip() is actually endian-agnostic. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 2 +- net/sctp/socket.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f201df66180d..d6664dd30e56 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -345,7 +345,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, addr_buf += af->sockaddr_len; } if (i == addrcnt) - return &laddr->a_h; + return &laddr->a; } return NULL; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a3e1ca2c3cb7..d049b2ce5cf2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -547,7 +547,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, laddr = list_entry(p, struct sctp_sockaddr_entry, list); sctp_read_unlock(&asoc->base.addr_lock); - chunk = sctp_make_asconf_update_ip(asoc, &laddr->a_h, addrs, + chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs, addrcnt, SCTP_PARAM_ADD_IP); if (!chunk) { retval = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 74af924ab6562717ef9aab1061ec05bbbf31d979 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:22:26 -0800 Subject: [SCTP]: ->a_h is gone now. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 - net/sctp/bind_addr.c | 2 -- net/sctp/ipv6.c | 1 - net/sctp/protocol.c | 1 - 4 files changed, 5 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 9bb5c038b95a..bb857957a88a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -757,7 +757,6 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk); struct sctp_sockaddr_entry { struct list_head list; union sctp_addr a; - union sctp_addr a_h; __u8 use_as_src; }; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index d6664dd30e56..00994158e496 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -163,8 +163,6 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, if (!addr->a.v4.sin_port) addr->a.v4.sin_port = htons(bp->port); - flip_to_h(&addr->a_h, &addr->a); - addr->use_as_src = use_as_src; INIT_LIST_HEAD(&addr->list); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index b3fa426bd1dc..04d5e13e9183 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -336,7 +336,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, addr->a.v6.sin6_port = 0; addr->a.v6.sin6_addr = ifp->addr; addr->a.v6.sin6_scope_id = dev->ifindex; - addr->a_h = addr->a; INIT_LIST_HEAD(&addr->list); list_add_tail(&addr->list, addrlist); } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index c20f05b3308f..807c97da33a5 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -153,7 +153,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, addr->a.v4.sin_family = AF_INET; addr->a.v4.sin_port = 0; addr->a.v4.sin_addr.s_addr = ifa->ifa_local; - addr->a_h = addr->a; list_add_tail(&addr->list, addrlist); } } -- cgit v1.2.3-70-g09d2 From b3f5b3b6654422bb0a6ef745fe4d11a4f01d006a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:22:43 -0800 Subject: [SCTP]: Trivial ->ipaddr_h -> ->ipaddr conversions. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 14 +++++++------- net/sctp/ipv6.c | 2 +- net/sctp/sm_sideeffect.c | 4 ++-- net/sctp/socket.c | 6 ++---- 4 files changed, 12 insertions(+), 14 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5b8971be9775..fa7cda4b1813 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -487,8 +487,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", " port: %d\n", asoc, - (&peer->ipaddr_h), - peer->ipaddr_h.v4.sin_port); + (&peer->ipaddr), + ntohs(peer->ipaddr.v4.sin_port)); /* If we are to remove the current retran_path, update it * to the next peer before removing this peer from the list. @@ -1136,8 +1136,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) " %p addr: ", " port: %d\n", asoc, - (&t->ipaddr_h), - t->ipaddr_h.v4.sin_port); + (&t->ipaddr), + ntohs(t->ipaddr.v4.sin_port)); } /* Choose the transport for sending a INIT packet. */ @@ -1161,8 +1161,8 @@ struct sctp_transport *sctp_assoc_choose_init_transport( " %p addr: ", " port: %d\n", asoc, - (&t->ipaddr_h), - t->ipaddr_h.v4.sin_port); + (&t->ipaddr), + ntohs(t->ipaddr.v4.sin_port)); return t; } @@ -1307,7 +1307,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, /* Use scoping rules to determine the subset of addresses from * the endpoint. */ - scope = sctp_scope(&asoc->peer.active_path->ipaddr_h); + scope = sctp_scope(&asoc->peer.active_path->ipaddr); flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; if (asoc->peer.ipv4_address) flags |= SCTP_ADDR4_PEERSUPP; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 04d5e13e9183..a76ffc143894 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -161,7 +161,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, /* Fill in the dest address from the route entry passed with the skb * and the source address from the transport. */ - ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr_h.v6.sin6_addr); + ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr.v6.sin6_addr); ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr); fl.fl6_flowlabel = np->flow_label; diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index a11bd4ff9303..c512ce491834 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -441,8 +441,8 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", " transport IP: port:%d failed.\n", asoc, - (&transport->ipaddr_h), - transport->ipaddr_h.v4.sin_port); + (&transport->ipaddr), + ntohs(transport->ipaddr.v4.sin_port)); sctp_assoc_control_transport(asoc, transport, SCTP_TRANSPORT_DOWN, SCTP_FAILED_THRESHOLD); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d049b2ce5cf2..e527267a0536 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3752,10 +3752,9 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, to = (void __user *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); - memcpy(&temp, &from->ipaddr_h, sizeof(temp)); + memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; - temp.v4.sin_port = htons(temp.v4.sin_port); if (copy_to_user(to, &temp, addrlen)) return -EFAULT; to += addrlen ; @@ -3801,12 +3800,11 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); - memcpy(&temp, &from->ipaddr_h, sizeof(temp)); + memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; if(space_left < addrlen) return -ENOMEM; - temp.v4.sin_port = htons(temp.v4.sin_port); if (copy_to_user(to, &temp, addrlen)) return -EFAULT; to += addrlen; -- cgit v1.2.3-70-g09d2 From 8cec6b80664eb20b0c033fd20d2c7ed15621437f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:23:01 -0800 Subject: [SCTP]: We need to be careful when copying to sockaddr_storage. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/associola.c | 2 +- net/sctp/socket.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index fa7cda4b1813..39471d3b31b9 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -733,7 +733,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, * user. */ memset(&addr, 0, sizeof(struct sockaddr_storage)); - flip_to_n((union sctp_addr *)&addr, &transport->ipaddr_h); + memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len); event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 0, spc_state, error, GFP_ATOMIC); if (event) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e527267a0536..adbe531fdedc 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3202,8 +3202,8 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, status.sstat_outstrms = asoc->c.sinit_num_ostreams; status.sstat_fragmentation_point = asoc->frag_point; status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); - flip_to_n((union sctp_addr *)&status.sstat_primary.spinfo_address, - &transport->ipaddr_h); + memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr, + transport->af_specific->sockaddr_len); /* Map ipv4 address into v4-mapped-on-v6 address. */ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), (union sctp_addr *)&status.sstat_primary.spinfo_address); @@ -4173,8 +4173,8 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, if (!asoc->peer.primary_path) return -ENOTCONN; - flip_to_n((union sctp_addr *)&prim.ssp_addr, - &asoc->peer.primary_path->ipaddr_h); + memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, + asoc->peer.primary_path->af_specific->sockaddr_len); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, (union sctp_addr *)&prim.ssp_addr); -- cgit v1.2.3-70-g09d2 From 7dd8a5821dd4991916c4eedf84e10fc2d0b47555 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:23:25 -0800 Subject: [SCTP]: sctp_sf_send_restart_abort() is endian-agnostic. ... so caller can use ->ipaddr instead of ->ipaddr_h Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 0848309773a5..b70e3258b6d3 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1179,7 +1179,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, /* If a new address was added, ABORT the sender. */ if (!found && new_addr) { - sctp_sf_send_restart_abort(&new_addr->ipaddr_h, init, commands); + sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); } /* Return success if all addresses were found. */ -- cgit v1.2.3-70-g09d2 From 9fd76494855c974e9079e9812ba5ecf88dedab38 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:23:46 -0800 Subject: [SCTP]: ip6_send() doesn't need fl_ip_[sd]port. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net') diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a76ffc143894..e6bb08767b83 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -170,8 +170,6 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, fl.oif = transport->saddr.v6.sin6_scope_id; else fl.oif = sk->sk_bound_dev_if; - fl.fl_ip_sport = inet_sk(sk)->sport; - fl.fl_ip_dport = transport->ipaddr_h.v6.sin6_port; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -- cgit v1.2.3-70-g09d2 From 516b20ee2d4df76e7f76332e161a25c70e8f7bea Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:24:02 -0800 Subject: [SCTP]: ->a_h is gone now. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 - net/sctp/transport.c | 1 - 2 files changed, 2 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bb857957a88a..02f1fd5de4be 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -843,7 +843,6 @@ struct sctp_transport { /* This is the peer's IP address and port. */ union sctp_addr ipaddr; - union sctp_addr ipaddr_h; /* These are the functions we call to handle LLP stuff. */ struct sctp_af *af_specific; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 05ab5e9c7c47..3e5936a5f671 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -62,7 +62,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, { /* Copy in the address. */ peer->ipaddr = *addr; - flip_to_h(&peer->ipaddr_h, &peer->ipaddr); peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); peer->asoc = NULL; -- cgit v1.2.3-70-g09d2 From 7dcdbd9579c944bb833f95a7f276d01f49161734 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:24:21 -0800 Subject: [SCTP]: Don't bother setting sin_port in ->from_sk(). ... the only caller will overwrite immediately Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index e6bb08767b83..8e2b1e4ec66e 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -371,7 +371,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) { addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = inet_sk(sk)->num; + addr->v6.sin6_port = 0; addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr; } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 807c97da33a5..c6297744a4ed 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -272,7 +272,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) { addr->v4.sin_family = AF_INET; - addr->v4.sin_port = inet_sk(sk)->num; + addr->v4.sin_port = 0; addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr; } -- cgit v1.2.3-70-g09d2 From 6fbfa9f951878ab489147d9e459191d4aacfa819 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:24:53 -0800 Subject: [SCTP]: Annotate ->inaddr_any(). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- net/sctp/socket.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d44202b0487d..3a6b8745538c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -560,7 +560,7 @@ struct sctp_af { struct sctp_sock *, const struct sk_buff *); sctp_scope_t (*scope) (union sctp_addr *); - void (*inaddr_any) (union sctp_addr *, unsigned short); + void (*inaddr_any) (union sctp_addr *, __be16); int (*is_any) (const union sctp_addr *); int (*available) (union sctp_addr *, struct sctp_sock *); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 8e2b1e4ec66e..268d32c89594 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -478,7 +478,7 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1, } /* Initialize addr struct to INADDR_ANY. */ -static void sctp_v6_inaddr_any(union sctp_addr *addr, unsigned short port) +static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port) { memset(addr, 0x00, sizeof(union sctp_addr)); addr->v6.sin6_family = AF_INET6; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index c6297744a4ed..5da887528bf1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -338,7 +338,7 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1, } /* Initialize addr struct to INADDR_ANY. */ -static void sctp_v4_inaddr_any(union sctp_addr *addr, unsigned short port) +static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) { addr->v4.sin_family = AF_INET; addr->v4.sin_addr.s_addr = INADDR_ANY; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index adbe531fdedc..56f77d35a8e1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5055,7 +5055,7 @@ static int sctp_autobind(struct sock *sk) { union sctp_addr autoaddr; struct sctp_af *af; - unsigned short port; + __be16 port; /* Initialize a local sockaddr structure to INADDR_ANY. */ af = sctp_sk(sk)->pf->af; -- cgit v1.2.3-70-g09d2 From dce116ae86cb224a9dad787e91fb552dae67b2e8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:25:15 -0800 Subject: [SCTP]: Get rid of the last remnants of sin_port flipping. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/socket.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 56f77d35a8e1..02b27145b279 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1000,7 +1000,6 @@ static int __sctp_connect(struct sock* sk, goto out_free; memcpy(&to, sa_addr, af->sockaddr_len); - to.v4.sin_port = ntohs(to.v4.sin_port); /* Check if there already is a matching association on the * endpoint (other than the one created here). @@ -1049,7 +1048,7 @@ static int __sctp_connect(struct sock* sk, } } - scope = sctp_scope(&to); + scope = sctp_scope(sa_addr); asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); if (!asoc) { err = -ENOMEM; @@ -1357,7 +1356,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, struct sctp_association *new_asoc=NULL, *asoc=NULL; struct sctp_transport *transport, *chunk_tp; struct sctp_chunk *chunk; - union sctp_addr to, tmp; + union sctp_addr to; struct sockaddr *msg_name = NULL; struct sctp_sndrcvinfo default_sinfo = { 0 }; struct sctp_sndrcvinfo *sinfo; @@ -1411,12 +1410,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, if (msg_namelen > sizeof(to)) msg_namelen = sizeof(to); memcpy(&to, msg->msg_name, msg_namelen); - memcpy(&tmp, msg->msg_name, msg_namelen); - SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is " - "0x%x:%u.\n", - to.v4.sin_addr.s_addr, to.v4.sin_port); - - to.v4.sin_port = ntohs(to.v4.sin_port); msg_name = msg->msg_name; } @@ -1466,7 +1459,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* If a msg_name has been specified, assume this is to be used. */ if (msg_name) { /* Look for a matching association on the endpoint. */ - asoc = sctp_endpoint_lookup_assoc(ep, &tmp, &transport); + asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); if (!asoc) { /* If we could not find a matching association on the * endpoint, make sure that it is not a TCP-style @@ -1475,7 +1468,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, */ if ((sctp_style(sk, TCP) && sctp_sstate(sk, ESTABLISHED)) || - sctp_endpoint_is_peeled_off(ep, &tmp)) { + sctp_endpoint_is_peeled_off(ep, &to)) { err = -EADDRNOTAVAIL; goto out_unlock; } @@ -1612,7 +1605,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, &tmp, GFP_KERNEL, SCTP_UNKNOWN); + transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; goto out_free; @@ -1679,7 +1672,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, */ if ((sctp_style(sk, TCP) && msg_name) || (sinfo_flags & SCTP_ADDR_OVER)) { - chunk_tp = sctp_assoc_lookup_paddr(asoc, &tmp); + chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); if (!chunk_tp) { err = -EINVAL; goto out_free; -- cgit v1.2.3-70-g09d2 From 3dbe86566ed262dae3b5472b9360cb5b65d42716 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:25:49 -0800 Subject: [SCTP]: Annotate ->supported_addrs(). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- net/sctp/sm_make_chunk.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 2db4a1bdd1a7..f8cbe40f52c0 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -587,7 +587,7 @@ struct sctp_pf { struct sctp_sock *); int (*bind_verify) (struct sctp_sock *, union sctp_addr *); int (*send_verify) (struct sctp_sock *, union sctp_addr *); - int (*supported_addrs)(const struct sctp_sock *, __u16 *); + int (*supported_addrs)(const struct sctp_sock *, __be16 *); struct sock *(*create_accept_sk) (struct sock *sk, struct sctp_association *asoc); void (*addr_v4map) (struct sctp_sock *, union sctp_addr *); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 268d32c89594..3c3e560087ca 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -853,7 +853,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) * Returns number of addresses supported. */ static int sctp_inet6_supported_addrs(const struct sctp_sock *opt, - __u16 *types) + __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; types[1] = SCTP_PARAM_IPV6_ADDRESS; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5da887528bf1..11f3b549f4a4 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -791,7 +791,7 @@ static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr) * chunks. Returns number of addresses supported. */ static int sctp_inet_supported_addrs(const struct sctp_sock *opt, - __u16 *types) + __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; return 1; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9d55497627f6..9674e6e3205b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -183,7 +183,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, int num_types, addrs_len = 0; struct sctp_sock *sp; sctp_supported_addrs_param_t sat; - __u16 types[2]; + __be16 types[2]; sctp_adaption_ind_param_t aiparam; /* RFC 2960 3.3.2 Initiation (INIT) (1) -- cgit v1.2.3-70-g09d2 From 962c837275e8a8c1df41f1882e971636093cdee4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:26:08 -0800 Subject: [SCTP]: Netfilter sctp annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_sctp.h | 2 +- net/netfilter/xt_sctp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_sctp.h b/include/linux/netfilter/nf_conntrack_sctp.h index b8994d9fd1a9..5cf2c115cce4 100644 --- a/include/linux/netfilter/nf_conntrack_sctp.h +++ b/include/linux/netfilter/nf_conntrack_sctp.h @@ -20,7 +20,7 @@ struct ip_ct_sctp { enum sctp_conntrack state; - u_int32_t vtag[IP_CT_DIR_MAX]; + __be32 vtag[IP_CT_DIR_MAX]; u_int32_t ttag[IP_CT_DIR_MAX]; }; diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index 7956acaaa24b..71bf036f833c 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -71,7 +71,7 @@ match_packet(const struct sk_buff *skb, duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", ++i, offset, sch->type, htons(sch->length), sch->flags); - offset += (htons(sch->length) + 3) & ~3; + offset += (ntohs(sch->length) + 3) & ~3; duprintf("skb->len: %d\toffset: %d\n", skb->len, offset); -- cgit v1.2.3-70-g09d2 From 9f81bcd9429e9bb4006eb9b7df276706c5df926d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:26:34 -0800 Subject: [SCTP]: More trivial sctp annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 2 +- net/sctp/sm_make_chunk.c | 11 +++++------ net/sctp/tsnmap.c | 9 +++++---- net/sctp/ulpevent.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 739582415bf6..c9148484b2ff 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1632,7 +1632,7 @@ pass: } static inline int sctp_get_skip_pos(struct sctp_fwdtsn_skip *skiplist, - int nskips, __u16 stream) + int nskips, __be16 stream) { int i; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9674e6e3205b..51cab806abd8 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -775,7 +775,7 @@ struct sctp_chunk *sctp_make_abort_no_data( const struct sctp_chunk *chunk, __u32 tsn) { struct sctp_chunk *retval; - __u32 payload; + __be32 payload; retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + sizeof(tsn)); @@ -1195,10 +1195,9 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid); else ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid); - ssn = htons(ssn); } - chunk->subh.data_hdr->ssn = ssn; + chunk->subh.data_hdr->ssn = htons(ssn); chunk->has_ssn = 1; } @@ -1539,8 +1538,8 @@ malformed: ********************************************************************/ struct __sctp_missing { - __u32 num_missing; - __u16 type; + __be32 num_missing; + __be16 type; } __attribute__((packed)); /* @@ -2364,7 +2363,7 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as } /* Add response parameters to an ASCONF_ACK chunk. */ -static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id, +static void sctp_add_asconf_response(struct sctp_chunk *chunk, __be32 crr_id, __be16 err_code, sctp_addip_param_t *asconf_param) { sctp_addip_param_t ack_param; diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index ac4fae161bc7..42d9498c64fa 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -401,13 +401,14 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map) /* Refresh the gap ack information. */ if (sctp_tsnmap_has_gap(map)) { + __u16 start, end; sctp_tsnmap_iter_init(map, &iter); while (sctp_tsnmap_next_gap_ack(map, &iter, - &map->gabs[gabs].start, - &map->gabs[gabs].end)) { + &start, + &end)) { - map->gabs[gabs].start = htons(map->gabs[gabs].start); - map->gabs[gabs].end = htons(map->gabs[gabs].end); + map->gabs[gabs].start = htons(start); + map->gabs[gabs].end = htons(end); gabs++; if (gabs >= SCTP_MAX_GABS) break; diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index a015283a9087..e255a709f1b7 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -351,7 +351,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error( struct sctp_remote_error *sre; struct sk_buff *skb; sctp_errhdr_t *ch; - __u16 cause; + __be16 cause; int elen; ch = (sctp_errhdr_t *)(chunk->skb->data); -- cgit v1.2.3-70-g09d2 From 2178eda82616566b7397791afa6e5487990bac8e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:26:53 -0800 Subject: [SCTP]: SCTP_CMD_PROCESS_CTSN annotations. argument passed as __be32 Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sctp/command.h | 2 ++ net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index dfe5d44b61ab..6114c4f54b0a 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -116,6 +116,7 @@ typedef enum { typedef union { __s32 i32; __u32 u32; + __be32 be32; __u16 u16; __u8 u8; int error; @@ -165,6 +166,7 @@ SCTP_## name (type arg) \ SCTP_ARG_CONSTRUCTOR(I32, __s32, i32) SCTP_ARG_CONSTRUCTOR(U32, __u32, u32) +SCTP_ARG_CONSTRUCTOR(BE32, __be32, be32) SCTP_ARG_CONSTRUCTOR(U16, __u16, u16) SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) SCTP_ARG_CONSTRUCTOR(ERROR, int, error) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c512ce491834..7bbc6156e455 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1420,7 +1420,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_PROCESS_CTSN: /* Dummy up a SACK for processing. */ - sackh.cum_tsn_ack = cmd->obj.u32; + sackh.cum_tsn_ack = cmd->obj.be32; sackh.a_rwnd = 0; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b70e3258b6d3..c136d991da6d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2466,7 +2466,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, * received by the SHUTDOWN sender. */ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, - SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack)); + SCTP_BE32(chunk->subh.shutdown_hdr->cum_tsn_ack)); out: return disposition; -- cgit v1.2.3-70-g09d2 From 34bcca28335977e969338c98c6c43a1e08f592b2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 17:27:15 -0800 Subject: [SCTP]: Even more trivial sctp annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 2 +- net/sctp/sm_make_chunk.c | 4 ++-- net/sctp/sm_statefuns.c | 9 +++++---- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index c9148484b2ff..fba567a7cb64 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1065,7 +1065,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) * A) Initialize the cacc_saw_newack to 0 for all destination * addresses. */ - if (sack->num_gap_ack_blocks > 0 && + if (sack->num_gap_ack_blocks && primary->cacc.changeover_active) { list_for_each(pos, transport_list) { transport = list_entry(pos, struct sctp_transport, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 51cab806abd8..988745272458 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1472,10 +1472,10 @@ no_hmac: suseconds_t usecs = (tv.tv_sec - bear_cookie->expiration.tv_sec) * 1000000L + tv.tv_usec - bear_cookie->expiration.tv_usec; + __be32 n = htonl(usecs); - usecs = htonl(usecs); sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, - &usecs, sizeof(usecs)); + &n, sizeof(n)); *error = -SCTP_IERROR_STALE_COOKIE; } else *error = -SCTP_IERROR_NOMEM; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index c136d991da6d..27cc444aaf11 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2158,7 +2158,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, * to give ample time to retransmit the new cookie and thus * yield a higher probability of success on the reattempt. */ - stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t))); + stale = ntohl(*(__be32 *)((u8 *)err + sizeof(sctp_errhdr_t))); stale = (stale * 2) / 1000; bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE; @@ -2545,6 +2545,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep, { sctp_cwrhdr_t *cwr; struct sctp_chunk *chunk = arg; + u32 lowest_tsn; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -2556,14 +2557,14 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep, cwr = (sctp_cwrhdr_t *) chunk->skb->data; skb_pull(chunk->skb, sizeof(sctp_cwrhdr_t)); - cwr->lowest_tsn = ntohl(cwr->lowest_tsn); + lowest_tsn = ntohl(cwr->lowest_tsn); /* Does this CWR ack the last sent congestion notification? */ - if (TSN_lte(asoc->last_ecne_tsn, cwr->lowest_tsn)) { + if (TSN_lte(asoc->last_ecne_tsn, lowest_tsn)) { /* Stop sending ECNE. */ sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CWR, - SCTP_U32(cwr->lowest_tsn)); + SCTP_U32(lowest_tsn)); } return SCTP_DISPOSITION_CONSUME; } -- cgit v1.2.3-70-g09d2 From 8e5200f54062b8af0ed1d186ea0f113854786d89 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:06:37 -0800 Subject: [NET]: Fix assorted misannotations (from md5 and udplite merges). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- include/net/udp.h | 2 +- include/net/udplite.h | 4 ++-- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 4 ++-- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/udp.c | 2 +- net/ipv6/udplite.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/net/tcp.h b/include/net/tcp.h index aa7989c53791..c99774f15eba 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1154,7 +1154,7 @@ extern int tcp_v4_md5_do_add(struct sock *sk, u8 newkeylen); extern int tcp_v4_md5_do_del(struct sock *sk, - u32 addr); + __be32 addr); extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); extern void tcp_free_md5sig_pool(void); diff --git a/include/net/udp.h b/include/net/udp.h index c5ccd9a3387b..eac69ff0582c 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -77,7 +77,7 @@ static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) skb->csum)); } -static inline __sum16 udp_lib_checksum_complete(struct sk_buff *skb) +static inline int udp_lib_checksum_complete(struct sk_buff *skb) { return skb->ip_summed != CHECKSUM_UNNECESSARY && __udp_lib_checksum_complete(skb); diff --git a/include/net/udplite.h b/include/net/udplite.h index 3abaab7b78c6..67ac51424307 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -90,9 +90,9 @@ static __inline__ int udplite6_csum_init(struct sk_buff *skb, struct udphdr *uh) int rc = udplite_checksum_init(skb, uh); if (!rc) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len, IPPROTO_UDPLITE, 0); + skb->len, IPPROTO_UDPLITE, 0)); return rc; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index b7d5522092eb..e9d467124c4d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1020,7 +1020,7 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, #ifdef CONFIG_TCP_MD5SIG_DEBUG int i; #endif - __u16 old_checksum; + __sum16 old_checksum; struct tcp_md5sig_pool *hp; struct tcp4_pseudohdr *bp; struct hash_desc *desc; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7eb76fbf1b4b..28e4cf662ce0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -114,7 +114,7 @@ DEFINE_RWLOCK(udp_hash_lock); static int udp_port_rover; -static inline int __udp_lib_lport_inuse(__be16 num, struct hlist_head udptable[]) +static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[]) { struct sock *sk; struct hlist_node *node; @@ -455,7 +455,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) struct sk_buff *skb; struct udphdr *uh; int err = 0; - u32 csum = 0; + __wsum csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d2170da77e5b..0adb337c4b7e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -739,7 +739,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, struct scatterlist sg[4]; __u16 data_len; int block = 0; - __u16 cksum; + __sum16 cksum; struct tcp_md5sig_pool *hp; struct tcp6_pseudohdr *bp; struct hash_desc *desc; @@ -1032,7 +1032,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_TCP_MD5SIG if (key) { - u32 *opt = (u32*)(t1 + 1); + __be32 *opt = (__be32*)(t1 + 1); opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | (TCPOPT_MD5SIG << 8) | diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index efa8950ddd30..b3ea8af50a9b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -248,7 +248,7 @@ out: static __inline__ void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, - int code, int offset, __u32 info ) + int code, int offset, __be32 info ) { return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash); } diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index e0ec5e63004a..d4cafacc235b 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -24,7 +24,7 @@ static __inline__ int udplitev6_rcv(struct sk_buff **pskb) static __inline__ void udplitev6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); } -- cgit v1.2.3-70-g09d2 From 5b14027bf2132c0631ea9f3be11ced89a5057220 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:06:59 -0800 Subject: [NETFILTER]: ip_nat_snmp_basic annotations. ... and switch the damn checksum update to something saner Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_snmp_basic.c | 85 ++++++++++++++-------------------- 1 file changed, 34 insertions(+), 51 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index 168f45fa1898..c3d9f3b090c4 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -64,7 +64,7 @@ MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway"); #define SNMP_PORT 161 #define SNMP_TRAP_PORT 162 -#define NOCT1(n) (u_int8_t )((n) & 0xff) +#define NOCT1(n) (*(u8 *)n) static int debug; static DEFINE_SPINLOCK(snmp_lock); @@ -613,7 +613,7 @@ struct snmp_v1_trap static inline void mangle_address(unsigned char *begin, unsigned char *addr, const struct oct1_map *map, - u_int16_t *check); + __sum16 *check); struct snmp_cnv { unsigned int class; @@ -873,38 +873,24 @@ static unsigned char snmp_request_decode(struct asn1_ctx *ctx, * Fast checksum update for possibly oddly-aligned UDP byte, from the * code example in the draft. */ -static void fast_csum(unsigned char *csum, +static void fast_csum(__sum16 *csum, const unsigned char *optr, const unsigned char *nptr, - int odd) + int offset) { - long x, old, new; - - x = csum[0] * 256 + csum[1]; - - x =~ x & 0xFFFF; - - if (odd) old = optr[0] * 256; - else old = optr[0]; - - x -= old & 0xFFFF; - if (x <= 0) { - x--; - x &= 0xFFFF; - } - - if (odd) new = nptr[0] * 256; - else new = nptr[0]; - - x += new & 0xFFFF; - if (x & 0x10000) { - x++; - x &= 0xFFFF; + unsigned char s[4]; + + if (offset & 1) { + s[0] = s[2] = 0; + s[1] = ~*optr; + s[3] = *nptr; + } else { + s[1] = s[3] = 0; + s[0] = ~*optr; + s[2] = *nptr; } - - x =~ x & 0xFFFF; - csum[0] = x / 256; - csum[1] = x & 0xFF; + + *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum))); } /* @@ -915,9 +901,9 @@ static void fast_csum(unsigned char *csum, static inline void mangle_address(unsigned char *begin, unsigned char *addr, const struct oct1_map *map, - u_int16_t *check) + __sum16 *check) { - if (map->from == NOCT1(*addr)) { + if (map->from == NOCT1(addr)) { u_int32_t old; if (debug) @@ -927,11 +913,8 @@ static inline void mangle_address(unsigned char *begin, /* Update UDP checksum if being used */ if (*check) { - unsigned char odd = !((addr - begin) % 2); - - fast_csum((unsigned char *)check, - &map->from, &map->to, odd); - + fast_csum(check, + &map->from, &map->to, addr - begin); } if (debug) @@ -943,7 +926,7 @@ static inline void mangle_address(unsigned char *begin, static unsigned char snmp_trap_decode(struct asn1_ctx *ctx, struct snmp_v1_trap *trap, const struct oct1_map *map, - u_int16_t *check) + __sum16 *check) { unsigned int cls, con, tag, len; unsigned char *end; @@ -1037,7 +1020,7 @@ static void hex_dump(unsigned char *buf, size_t len) static int snmp_parse_mangle(unsigned char *msg, u_int16_t len, const struct oct1_map *map, - u_int16_t *check) + __sum16 *check) { unsigned char *eoc, *end; unsigned int cls, con, tag, vers, pdutype; @@ -1223,12 +1206,12 @@ static int snmp_translate(struct ip_conntrack *ct, */ if (dir == IP_CT_DIR_ORIGINAL) { /* SNAT traps */ - map.from = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip); - map.to = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip); + map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip); + map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip); } else { /* DNAT replies */ - map.from = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); - map.to = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip); + map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); + map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip); } if (map.from == map.to) @@ -1294,11 +1277,11 @@ static struct ip_conntrack_helper snmp_helper = { .help = help, .name = "snmp", - .tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } }, - .dst = { .protonum = IPPROTO_UDP }, + .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_PORT)}}}, + .dst = {.protonum = IPPROTO_UDP}, }, - .mask = { .src = { .u = { 0xFFFF } }, - .dst = { .protonum = 0xFF }, + .mask = {.src = {.u = {0xFFFF}}, + .dst = {.protonum = 0xFF}, }, }; @@ -1309,11 +1292,11 @@ static struct ip_conntrack_helper snmp_trap_helper = { .help = help, .name = "snmp_trap", - .tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } }, - .dst = { .protonum = IPPROTO_UDP }, + .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_TRAP_PORT)}}}, + .dst = {.protonum = IPPROTO_UDP}, }, - .mask = { .src = { .u = { 0xFFFF } }, - .dst = { .protonum = 0xFF }, + .mask = {.src = {.u = {0xFFFF}}, + .dst = {.protonum = 0xFF}, }, }; -- cgit v1.2.3-70-g09d2 From ff1dcadb1b55dbf471c5ed109dbbdf06bd19ef3b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:07:29 -0800 Subject: [NET]: Split skb->csum ... into anonymous union of __wsum and __u32 (csum and csum_offset resp.) Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/cassini.c | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/sk98lin/skge.c | 4 ++-- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.c | 2 +- include/linux/skbuff.h | 5 ++++- net/core/dev.c | 4 ++-- net/core/skbuff.c | 2 +- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/udp.c | 2 +- net/ipv6/tcp_ipv6.c | 4 ++-- 15 files changed, 22 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 521c5b71023c..fd2cc13f7d97 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2825,7 +2825,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = TX_DESC_CSUM_EN | CAS_BASE(TX_DESC_CSUM_START, csum_start_off) | diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7a0828869ecf..32dde0adb683 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2826,7 +2826,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, context_desc = E1000_CONTEXT_DESC(*tx_ring, i); context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e09f575a3a38..7b127212e62b 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1249,7 +1249,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) { struct ixgb_buffer *buffer_info; css = skb->h.raw - skb->data; - cso = (skb->h.raw + skb->csum) - skb->data; + cso = css + skb->csum_offset; i = adapter->tx_ring.next_to_use; context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 806081b59733..36350e6db1c1 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1955,7 +1955,7 @@ again: flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { cksum_offset = (skb->h.raw - skb->data); - pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; + pseudo_hdr_offset = cksum_offset + skb->csum_offset; /* If the headers are excessively large, then we must * fall back to a software checksum */ if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index a5d41ebc9fb4..12cbfd190dd7 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1562,7 +1562,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && @@ -1681,7 +1681,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; Control = BMU_STFWD; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 27b537c8d5e3..5513907e8393 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2565,7 +2565,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) td->csum_offs = 0; td->csum_start = offset; - td->csum_write = offset + skb->csum; + td->csum_write = offset + skb->csum_offset; } else control = BMU_CHECK; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0ef1848b9761..842abd9396c6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1350,7 +1350,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) u32 tcpsum; tcpsum = offset << 16; /* sum start */ - tcpsum |= offset + skb->csum; /* sum write */ + tcpsum |= offset + skb->csum_offset; /* sum write */ ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; if (skb->nh.iph->protocol == IPPROTO_UDP) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 253e96e7ad20..334c6cfd6595 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1030,7 +1030,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = (TXDCTRL_CENAB | (csum_start_off << 15) | diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9d7cd130c19d..ec432ea879fb 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2272,7 +2272,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 csum_start_off, csum_stuff_off; csum_start_off = (u32) (skb->h.raw - skb->data); - csum_stuff_off = (u32) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; tx_flags = (TXFLAG_OWN | TXFLAG_CSENABLE | ((csum_start_off << 14) & TXFLAG_CSBUFBEGIN) | diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index fcab543d79ac..14ec16d2d9ba 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -274,7 +274,10 @@ struct sk_buff { unsigned int len, data_len, mac_len; - __wsum csum; + union { + __wsum csum; + __u32 csum_offset; + }; __u32 priority; __u8 local_df:1, cloned:1, diff --git a/net/core/dev.c b/net/core/dev.c index 1a36b17f4b51..59d058a3b504 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1191,9 +1191,9 @@ int skb_checksum_help(struct sk_buff *skb) offset = skb->tail - skb->h.raw; BUG_ON(offset <= 0); - BUG_ON(skb->csum + 2 > offset); + BUG_ON(skb->csum_offset + 2 > offset); - *(__sum16*)(skb->h.raw + skb->csum) = csum_fold(csum); + *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum); out_set_summed: skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 07c25d601922..a90bc439488e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1414,7 +1414,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) skb->len - csstart, 0); if (skb->ip_summed == CHECKSUM_PARTIAL) { - long csstuff = csstart + skb->csum; + long csstuff = csstart + skb->csum_offset; *((__sum16 *)(to + csstuff)) = csum_fold(csum); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e9d467124c4d..4913f25e5ad5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -504,7 +504,7 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, csum_partial((char *)th, @@ -526,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 28e4cf662ce0..1807a30694d9 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -422,7 +422,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, /* * Only one fragment on the socket. */ - skb->csum = offsetof(struct udphdr, check); + skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); } else { /* diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0adb337c4b7e..517c50024bfc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -948,7 +948,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, csum_partial((char *)th, th->doff<<2, @@ -970,7 +970,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } -- cgit v1.2.3-70-g09d2 From 66c6f529c31e2886536aad4b2320d566deb1f150 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:07:51 -0800 Subject: [NET]: net/sched annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 +- net/sched/cls_rsvp.h | 16 ++++++++-------- net/sched/sch_api.c | 2 +- net/sched/sch_dsmark.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index b0e9108a4e18..6b3829480b3a 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -144,7 +144,7 @@ struct tcf_proto void *root; int (*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *); - u32 protocol; + __be16 protocol; /* All the rest */ u32 prio; diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 6e230ecfba05..587b9adab38c 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -77,7 +77,7 @@ struct rsvp_head struct rsvp_session { struct rsvp_session *next; - u32 dst[RSVP_DST_LEN]; + __be32 dst[RSVP_DST_LEN]; struct tc_rsvp_gpi dpi; u8 protocol; u8 tunnelid; @@ -89,7 +89,7 @@ struct rsvp_session struct rsvp_filter { struct rsvp_filter *next; - u32 src[RSVP_DST_LEN]; + __be32 src[RSVP_DST_LEN]; struct tc_rsvp_gpi spi; u8 tunnelhdr; @@ -100,17 +100,17 @@ struct rsvp_filter struct rsvp_session *sess; }; -static __inline__ unsigned hash_dst(u32 *dst, u8 protocol, u8 tunnelid) +static __inline__ unsigned hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) { - unsigned h = dst[RSVP_DST_LEN-1]; + unsigned h = (__force __u32)dst[RSVP_DST_LEN-1]; h ^= h>>16; h ^= h>>8; return (h ^ protocol ^ tunnelid) & 0xFF; } -static __inline__ unsigned hash_src(u32 *src) +static __inline__ unsigned hash_src(__be32 *src) { - unsigned h = src[RSVP_DST_LEN-1]; + unsigned h = (__force __u32)src[RSVP_DST_LEN-1]; h ^= h>>16; h ^= h>>8; h ^= h>>4; @@ -138,7 +138,7 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, struct rsvp_session *s; struct rsvp_filter *f; unsigned h1, h2; - u32 *dst, *src; + __be32 *dst, *src; u8 protocol; u8 tunnelid = 0; u8 *xprt; @@ -410,7 +410,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, struct rtattr *tb[TCA_RSVP_MAX]; struct tcf_exts e; unsigned h1, h2; - u32 *dst; + __be32 *dst; int err; if (opt == NULL) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0b6489291140..d99802f3023d 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1112,7 +1112,7 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { int err = 0; - u32 protocol = skb->protocol; + __be16 protocol = skb->protocol; #ifdef CONFIG_NET_CLS_ACT struct tcf_proto *otp = tp; reclassify: diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 11c8a2119b96..0b7c0e82d600 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -307,7 +307,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) if (p->mask[index] != 0xff || p->value[index]) printk(KERN_WARNING "dsmark_dequeue: " "unsupported protocol %d\n", - htons(skb->protocol)); + ntohs(skb->protocol)); break; }; -- cgit v1.2.3-70-g09d2 From 5e57dff2c49956e24f27f9b6d2ec0db967680c39 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:08:13 -0800 Subject: [NETPOLL]: Another udp checksum mangling. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 8be3681d3d80..3c58846fcaa5 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -296,7 +296,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) udp_len, IPPROTO_UDP, csum_partial((unsigned char *)udph, udp_len, 0)); if (udph->check == 0) - udph->check = -1; + udph->check = CSUM_MANGLED_0; skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); -- cgit v1.2.3-70-g09d2 From 66625984ca94552f75836596e0e83f3e5594bd58 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:08:37 -0800 Subject: [CIPSO]: Missing annotation in cipso_ipv4 update. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv4/cipso_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index a60af8304073..f3957cfaed42 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1135,7 +1135,7 @@ int cipso_v4_validate(unsigned char **option) } rcu_read_lock(); - doi_def = cipso_v4_doi_search(ntohl(*((u32 *)&opt[2]))); + doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2]))); if (doi_def == NULL) { err_offset = 2; goto validate_return_locked; -- cgit v1.2.3-70-g09d2 From 2afe37cdffa96f69c9096e6d4a10a275c9c7d2c9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:14:33 -0200 Subject: [ATM]: Use kmemdup & kzalloc where applicable Signed-off-by: Arnaldo Carvalho de Melo --- net/atm/lec.c | 10 +++------- net/atm/mpc.c | 3 +-- net/atm/mpoa_caches.c | 6 ++---- 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/atm/lec.c b/net/atm/lec.c index 9f5f931743bd..5946ec63724f 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1321,11 +1321,10 @@ static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, if (table == NULL) return -1; - *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC); + *tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC); if (*tlvs == NULL) return -1; - memcpy(*tlvs, table->tlvs, table->sizeoftlvs); *sizeoftlvs = table->sizeoftlvs; return 0; @@ -1364,11 +1363,10 @@ static int lane2_associate_req(struct net_device *dev, u8 *lan_dst, kfree(priv->tlvs); /* NULL if there was no previous association */ - priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); + priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL); if (priv->tlvs == NULL) return (0); priv->sizeoftlvs = sizeoftlvs; - memcpy(priv->tlvs, tlvs, sizeoftlvs); skb = alloc_skb(sizeoftlvs, GFP_ATOMIC); if (skb == NULL) @@ -1409,12 +1407,10 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr, kfree(entry->tlvs); - entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); + entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL); if (entry->tlvs == NULL) return; - entry->sizeoftlvs = sizeoftlvs; - memcpy(entry->tlvs, tlvs, sizeoftlvs); #endif #if 0 printk("lec.c: lane2_associate_ind()\n"); diff --git a/net/atm/mpc.c b/net/atm/mpc.c index f15f5d847860..c18f73715ef9 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -1322,13 +1322,12 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *cli if(client->number_of_mps_macs) kfree(client->mps_macs); client->number_of_mps_macs = 0; - client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL); + client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL); if (client->mps_macs == NULL) { printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n"); return; } client->number_of_mps_macs = 1; - memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN); return; } diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index f3b99b38c91b..697a081533b5 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -87,7 +87,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc, static in_cache_entry *in_cache_add_entry(__be32 dst_ip, struct mpoa_client *client) { - in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL); + in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL); if (entry == NULL) { printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n"); @@ -95,7 +95,6 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip, } dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip)); - memset(entry,0,sizeof(in_cache_entry)); atomic_set(&entry->use, 1); dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n"); @@ -447,7 +446,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client) { - eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL); + eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL); if (entry == NULL) { printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n"); @@ -455,7 +454,6 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli } dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip)); - memset(entry, 0, sizeof(eg_cache_entry)); atomic_set(&entry->use, 1); dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n"); -- cgit v1.2.3-70-g09d2 From b1a98bf685e26f1a0b509d6f0f6bd8f7764303a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:15:32 -0200 Subject: [NET] neighbour: Use kmemdup where applicable Signed-off-by: Arnaldo Carvalho de Melo --- net/core/neighbour.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0e097ba14d73..ba509a4a8e92 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1266,10 +1266,9 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl) { - struct neigh_parms *p = kmalloc(sizeof(*p), GFP_KERNEL); + struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL); if (p) { - memcpy(p, &tbl->parms, sizeof(*p)); p->tbl = tbl; atomic_set(&p->refcnt, 1); INIT_RCU_HEAD(&p->rcu_head); @@ -2625,14 +2624,14 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, int p_id, int pdev_id, char *p_name, proc_handler *handler, ctl_handler *strategy) { - struct neigh_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL); + struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template, + sizeof(*t), GFP_KERNEL); const char *dev_name_source = NULL; char *dev_name = NULL; int err = 0; if (!t) return -ENOBUFS; - memcpy(t, &neigh_sysctl_template, sizeof(*t)); t->neigh_vars[0].data = &p->mcast_probes; t->neigh_vars[1].data = &p->ucast_probes; t->neigh_vars[2].data = &p->app_probes; -- cgit v1.2.3-70-g09d2 From e6b61105f6b06a1d6bb35d2a0978cf91106808b8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:16:24 -0200 Subject: [DECNET]: Use kzalloc where applicable Signed-off-by: Arnaldo Carvalho de Melo --- net/decnet/dn_table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 9ce58c24a8d3..bdbc3f431668 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -831,10 +831,11 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); return NULL; } - if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL) - return NULL; - memset(t, 0, sizeof(struct dn_fib_table)); + t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), + GFP_KERNEL); + if (t == NULL) + return NULL; t->n = n; t->insert = dn_fib_table_insert; @@ -842,7 +843,6 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) t->lookup = dn_fib_table_lookup; t->flush = dn_fib_table_flush; t->dump = dn_fib_table_dump; - memset(t->data, 0, sizeof(struct dn_hash)); hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]); return t; -- cgit v1.2.3-70-g09d2 From 8b2ed4bba45b7ca8e378d45f82f3f32f651e0a42 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:17:18 -0200 Subject: [IPVS]: Use kmemdup where appropriate Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/ipvs/ip_vs_app.c | 3 +-- net/ipv4/ipvs/ip_vs_proto.c | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index e7752334d296..6c40899aa161 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -80,10 +80,9 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port) if (!pp->unregister_app) return -EOPNOTSUPP; - inc = kmalloc(sizeof(struct ip_vs_app), GFP_KERNEL); + inc = kmemdup(app, sizeof(*inc), GFP_KERNEL); if (!inc) return -ENOMEM; - memcpy(inc, app, sizeof(*inc)); INIT_LIST_HEAD(&inc->p_list); INIT_LIST_HEAD(&inc->incs_list); inc->app = app; diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c index c4528b5c800d..e844ddb82b9a 100644 --- a/net/ipv4/ipvs/ip_vs_proto.c +++ b/net/ipv4/ipvs/ip_vs_proto.c @@ -118,13 +118,7 @@ void ip_vs_protocol_timeout_change(int flags) int * ip_vs_create_timeout_table(int *table, int size) { - int *t; - - t = kmalloc(size, GFP_ATOMIC); - if (t == NULL) - return NULL; - memcpy(t, table, size); - return t; + return kmemdup(table, size, GFP_ATOMIC); } -- cgit v1.2.3-70-g09d2 From b3ab09f9e1681916df349d54232fbb3f8a79bfa5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:18:33 -0200 Subject: [IRDA]: Use kmemdup where applicable Signed-off-by: Arnaldo Carvalho de Melo --- net/irda/iriap.c | 3 +-- net/irda/irias_object.c | 4 +--- net/irda/irlmp.c | 4 +--- net/irda/irqueue.c | 3 +-- 4 files changed, 4 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/irda/iriap.c b/net/irda/iriap.c index ab86d70393ea..8cfd076c4c12 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -172,7 +172,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, IRDA_DEBUG(2, "%s()\n", __FUNCTION__); - self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC); + self = kzalloc(sizeof(*self), GFP_ATOMIC); if (!self) { IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__); return NULL; @@ -181,7 +181,6 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, /* * Initialize instance */ - memset(self, 0, sizeof(struct iriap_cb)); self->magic = IAS_MAGIC; self->mode = mode; diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c index 56292ab7d652..b1ee99a59c0c 100644 --- a/net/irda/irias_object.c +++ b/net/irda/irias_object.c @@ -501,13 +501,12 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len) len = IAS_MAX_OCTET_STRING; value->len = len; - value->t.oct_seq = kmalloc(len, GFP_ATOMIC); + value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC); if (value->t.oct_seq == NULL){ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__); kfree(value); return NULL; } - memcpy(value->t.oct_seq, octseq , len); return value; } @@ -522,7 +521,6 @@ struct ias_value *irias_new_missing_value(void) } value->type = IAS_MISSING; - value->len = 0; return value; } diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index fede83763095..7e5d12ab3b90 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -641,15 +641,13 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) } /* Allocate a new instance */ - new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC); + new = kmemdup(orig, sizeof(*new), GFP_ATOMIC); if (!new) { IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__); spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags); return NULL; } - /* Dup */ - memcpy(new, orig, sizeof(struct lsap_cb)); /* new->lap = orig->lap; => done in the memcpy() */ /* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */ new->conn_skb = NULL; diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 1ba8c7106639..1d26cd33ea13 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c @@ -356,14 +356,13 @@ hashbin_t *hashbin_new(int type) /* * Allocate new hashbin */ - hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC); + hashbin = kzalloc(sizeof(*hashbin), GFP_ATOMIC); if (!hashbin) return NULL; /* * Initialize structure */ - memset(hashbin, 0, sizeof(hashbin_t)); hashbin->hb_type = type; hashbin->magic = HB_MAGIC; //hashbin->hb_current = NULL; -- cgit v1.2.3-70-g09d2 From c7b1b24978d89efab7d420bbdc9557dbe6259c89 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:19:40 -0200 Subject: [SCHED]: Use kmemdup & kzalloc where appropriate Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/act_ipt.c | 6 ++---- net/sched/act_simple.c | 3 +-- net/sched/cls_api.c | 3 +-- net/sched/em_meta.c | 3 +-- net/sched/em_nbyte.c | 4 +--- net/sched/ematch.c | 3 +-- 6 files changed, 7 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index d8c9310da6e5..a9608064a4c3 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -156,10 +156,9 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) strcpy(tname, "mangle"); - t = kmalloc(td->u.target_size, GFP_KERNEL); + t = kmemdup(td, td->u.target_size, GFP_KERNEL); if (unlikely(!t)) goto err2; - memcpy(t, td, td->u.target_size); if ((err = ipt_init_target(t, tname, hook)) < 0) goto err3; @@ -256,13 +255,12 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ** for foolproof you need to not assume this */ - t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); + t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); if (unlikely(!t)) goto rtattr_failure; c.bindcnt = ipt->tcf_bindcnt - bind; c.refcnt = ipt->tcf_refcnt - ref; - memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size); strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 901571a67707..5fe80854ca91 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -71,11 +71,10 @@ static int tcf_simp_release(struct tcf_defact *d, int bind) static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) { - d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL); + d->tcfd_defdata = kmemdup(defdata, datalen, GFP_KERNEL); if (unlikely(!d->tcfd_defdata)) return -ENOMEM; d->tcfd_datalen = datalen; - memcpy(d->tcfd_defdata, defdata, datalen); return 0; } diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 37a184021647..edb8fc97ae11 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -217,7 +217,7 @@ replay: /* Create new proto tcf */ err = -ENOBUFS; - if ((tp = kmalloc(sizeof(*tp), GFP_KERNEL)) == NULL) + if ((tp = kzalloc(sizeof(*tp), GFP_KERNEL)) == NULL) goto errout; err = -EINVAL; tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]); @@ -247,7 +247,6 @@ replay: kfree(tp); goto errout; } - memset(tp, 0, sizeof(*tp)); tp->ops = tp_ops; tp->protocol = protocol; tp->prio = nprio ? : tcf_auto_prio(*back); diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index d3ff3503326a..45d47d37155e 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -546,10 +546,9 @@ static int meta_var_change(struct meta_value *dst, struct rtattr *rta) { int len = RTA_PAYLOAD(rta); - dst->val = (unsigned long) kmalloc(len, GFP_KERNEL); + dst->val = (unsigned long)kmemdup(RTA_DATA(rta), len, GFP_KERNEL); if (dst->val == 0UL) return -ENOMEM; - memcpy((void *) dst->val, RTA_DATA(rta), len); dst->len = len; return 0; } diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c index cc80babfd79f..005db409be64 100644 --- a/net/sched/em_nbyte.c +++ b/net/sched/em_nbyte.c @@ -34,12 +34,10 @@ static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len, return -EINVAL; em->datalen = sizeof(*nbyte) + nbyte->len; - em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL); + em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL); if (em->data == 0UL) return -ENOBUFS; - memcpy((void *) em->data, data, em->datalen); - return 0; } diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 0fd0768a17c6..8f8a16da72a8 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -251,12 +251,11 @@ static int tcf_em_validate(struct tcf_proto *tp, goto errout; em->data = *(u32 *) data; } else { - void *v = kmalloc(data_len, GFP_KERNEL); + void *v = kmemdup(data, data_len, GFP_KERNEL); if (v == NULL) { err = -ENOBUFS; goto errout; } - memcpy(v, data, data_len); em->data = (unsigned long) v; } } -- cgit v1.2.3-70-g09d2 From af997d8c9568d556cd0a362d56de9fb14a6a012a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:20:33 -0200 Subject: [SCTP]: Use kzalloc where appropriate Signed-off-by: Arnaldo Carvalho de Melo --- net/sctp/sm_make_chunk.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 988745272458..04954e5f6846 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1279,15 +1279,13 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, - (bodysize % SCTP_COOKIE_MULTIPLE); *cookie_len = headersize + bodysize; - retval = kmalloc(*cookie_len, GFP_ATOMIC); - - if (!retval) - goto nodata; - /* Clear this memory since we are sending this data structure * out on the network. */ - memset(retval, 0x00, *cookie_len); + retval = kzalloc(*cookie_len, GFP_ATOMIC); + if (!retval) + goto nodata; + cookie = (struct sctp_signed_cookie *) retval->body; /* Set up the parameter header. */ @@ -1910,10 +1908,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, /* Copy cookie in case we need to resend COOKIE-ECHO. */ cookie = asoc->peer.cookie; if (cookie) { - asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, gfp); + asoc->peer.cookie = kmemdup(cookie, asoc->peer.cookie_len, gfp); if (!asoc->peer.cookie) goto clean_up; - memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len); } /* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily -- cgit v1.2.3-70-g09d2 From e69062b4f728dca01ec1a9eb4ed55b73a374f164 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:21:34 -0200 Subject: [SUNRPC]: Use k{mem,str}dup where applicable Signed-off-by: Arnaldo Carvalho de Melo --- net/sunrpc/auth_gss/auth_gss.c | 3 +-- net/sunrpc/auth_gss/gss_krb5_mech.c | 3 +-- net/sunrpc/auth_gss/gss_spkm3_mech.c | 3 +-- net/sunrpc/auth_gss/svcauth_gss.c | 7 ++----- net/sunrpc/clnt.c | 3 +-- 5 files changed, 6 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index b36b9463f5a4..e5a84a482e57 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -198,11 +198,10 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - dest->data = kmalloc(len, GFP_KERNEL); + dest->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(dest->data == NULL)) return ERR_PTR(-ENOMEM); dest->len = len; - memcpy(dest->data, p, len); return q; } diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 325e72e4fd31..754b8cd6439f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -70,10 +70,9 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - res->data = kmalloc(len, GFP_KERNEL); + res->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(res->data == NULL)) return ERR_PTR(-ENOMEM); - memcpy(res->data, p, len); res->len = len; return q; } diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index bdedf456bc17..d57f60838895 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -76,10 +76,9 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - res->data = kmalloc(len, GFP_KERNEL); + res->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(res->data == NULL)) return ERR_PTR(-ENOMEM); - memcpy(res->data, p, len); return q; } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 1f0f079ffa65..700353b330fd 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -113,9 +113,7 @@ static int rsi_match(struct cache_head *a, struct cache_head *b) static int dup_to_netobj(struct xdr_netobj *dst, char *src, int len) { dst->len = len; - dst->data = (len ? kmalloc(len, GFP_KERNEL) : NULL); - if (dst->data) - memcpy(dst->data, src, len); + dst->data = (len ? kmemdup(src, len, GFP_KERNEL) : NULL); if (len && !dst->data) return -ENOMEM; return 0; @@ -756,10 +754,9 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) if (!new) goto out; kref_init(&new->h.ref); - new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); + new->h.name = kstrdup(name, GFP_KERNEL); if (!new->h.name) goto out_free_dom; - strcpy(new->h.name, name); new->h.flavour = &svcauthops_gss; new->pseudoflavor = pseudoflavor; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 78696f2dc7d6..dfeea4fea95a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -253,10 +253,9 @@ rpc_clone_client(struct rpc_clnt *clnt) { struct rpc_clnt *new; - new = kmalloc(sizeof(*new), GFP_KERNEL); + new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); if (!new) goto out_no_clnt; - memcpy(new, clnt, sizeof(*new)); atomic_set(&new->cl_count, 1); atomic_set(&new->cl_users, 0); new->cl_parent = clnt; -- cgit v1.2.3-70-g09d2 From 2710b57ff9b1437cfbe96b23ae86fedf3239f1ca Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:22:12 -0200 Subject: [TIPC]: Use kzalloc where appropriate Signed-off-by: Arnaldo Carvalho de Melo --- net/tipc/bcast.c | 6 ++---- net/tipc/node.c | 3 +-- net/tipc/subscr.c | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 1bb75703f384..730c5c47ed8d 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -774,8 +774,8 @@ int tipc_bclink_set_queue_limits(u32 limit) int tipc_bclink_init(void) { - bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC); - bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); + bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); + bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC); if (!bcbearer || !bclink) { nomem: warn("Multicast link creation failed, no memory\n"); @@ -786,14 +786,12 @@ int tipc_bclink_init(void) return -ENOMEM; } - memset(bcbearer, 0, sizeof(struct bcbearer)); INIT_LIST_HEAD(&bcbearer->bearer.cong_links); bcbearer->bearer.media = &bcbearer->media; bcbearer->media.send_msg = tipc_bcbearer_send; sprintf(bcbearer->media.name, "tipc-multicast"); bcl = &bclink->link; - memset(bclink, 0, sizeof(struct bclink)); INIT_LIST_HEAD(&bcl->waiting_ports); bcl->next_out_no = 1; spin_lock_init(&bclink->node.lock); diff --git a/net/tipc/node.c b/net/tipc/node.c index 106cd0dfac78..4111a31def79 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -60,7 +60,7 @@ struct node *tipc_node_create(u32 addr) struct node *n_ptr; struct node **curr_node; - n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC); + n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); if (!n_ptr) { warn("Node creation failed, no memory\n"); return NULL; @@ -75,7 +75,6 @@ struct node *tipc_node_create(u32 addr) return NULL; } - memset(n_ptr, 0, sizeof(*n_ptr)); n_ptr->addr = addr; spin_lock_init(&n_ptr->lock); INIT_LIST_HEAD(&n_ptr->nsub); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7a918f12a5df..ddade7388aa0 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -350,7 +350,7 @@ static void subscr_subscribe(struct tipc_subscr *s, /* Allocate subscription object */ - sub = kmalloc(sizeof(*sub), GFP_ATOMIC); + sub = kzalloc(sizeof(*sub), GFP_ATOMIC); if (!sub) { warn("Subscription rejected, no memory\n"); subscr_terminate(subscriber); @@ -359,7 +359,6 @@ static void subscr_subscribe(struct tipc_subscr *s, /* Initialize subscription object */ - memset(sub, 0, sizeof(*sub)); sub->seq.type = htohl(s->seq.type, subscriber->swap); sub->seq.lower = htohl(s->seq.lower, subscriber->swap); sub->seq.upper = htohl(s->seq.upper, subscriber->swap); -- cgit v1.2.3-70-g09d2 From cdbc6dae5cc90d7d9e109e7d0568979d5355b653 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:22:51 -0200 Subject: [XFRM]: Use kmemdup where appropriate Signed-off-by: Arnaldo Carvalho de Melo --- net/xfrm/xfrm_user.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6ddb49367c13..6c4d2f49d9e5 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -244,11 +244,10 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, *props = algo->desc.sadb_alg_id; len = sizeof(*ualg) + (ualg->alg_key_len + 7U) / 8; - p = kmalloc(len, GFP_KERNEL); + p = kmemdup(ualg, len, GFP_KERNEL); if (!p) return -ENOMEM; - memcpy(p, ualg, len); strcpy(p->alg_name, algo->name); *algpp = p; return 0; @@ -263,11 +262,10 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a return 0; uencap = RTA_DATA(rta); - p = kmalloc(sizeof(*p), GFP_KERNEL); + p = kmemdup(uencap, sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; - memcpy(p, uencap, sizeof(*p)); *encapp = p; return 0; } @@ -305,11 +303,10 @@ static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg) return 0; uaddrp = RTA_DATA(rta); - p = kmalloc(sizeof(*p), GFP_KERNEL); + p = kmemdup(uaddrp, sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; - memcpy(p, uaddrp, sizeof(*p)); *addrpp = p; return 0; } -- cgit v1.2.3-70-g09d2 From e94ef682053a6eeca91aefdaecf8efe7fd7e33a5 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 23 Nov 2006 11:44:37 -0800 Subject: [GENETLINK] ctrl: Avoid empty CTRL_ATTR_OPS attribute when dumping Based on Jamal's patch but compiled and even tested. :-) Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/netlink/genetlink.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 8903ef93db5b..cc874f0fcbdb 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -394,10 +394,7 @@ static struct genl_family genl_ctrl = { static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, u32 flags, struct sk_buff *skb, u8 cmd) { - struct nlattr *nla_ops; - struct genl_ops *ops; void *hdr; - int idx = 1; hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd); if (hdr == NULL) @@ -409,33 +406,39 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); - nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); - if (nla_ops == NULL) - goto nla_put_failure; - - list_for_each_entry(ops, &family->ops_list, ops_list) { - struct nlattr *nest; + if (!list_empty(&family->ops_list)) { + struct nlattr *nla_ops; + struct genl_ops *ops; + int idx = 1; - nest = nla_nest_start(skb, idx++); - if (nest == NULL) + nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); + if (nla_ops == NULL) goto nla_put_failure; - NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); - NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); + list_for_each_entry(ops, &family->ops_list, ops_list) { + struct nlattr *nest; - if (ops->policy) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY); + nest = nla_nest_start(skb, idx++); + if (nest == NULL) + goto nla_put_failure; - if (ops->doit) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT); + NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); + NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); - if (ops->dumpit) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT); + if (ops->policy) + NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY); - nla_nest_end(skb, nest); - } + if (ops->doit) + NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT); + + if (ops->dumpit) + NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT); - nla_nest_end(skb, nla_ops); + nla_nest_end(skb, nest); + } + + nla_nest_end(skb, nla_ops); + } return genlmsg_end(skb, hdr); -- cgit v1.2.3-70-g09d2 From 567131a722ca064c917c0b06e4bcf07d47602103 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Fri, 24 Nov 2006 17:05:41 -0800 Subject: [IPV6]: Fix SIOCCHGTUNNEL bug in IPv6 tunnels A logic bug in tunnel lookup could result in duplicate tunnels when changing an existing device. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 111 +++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 65 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 25bc5ed49104..fdf1a2fa3a3d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -215,11 +215,10 @@ ip6ip6_tnl_unlink(struct ip6_tnl *t) * Create tunnel matching given parameters. * * Return: - * 0 on success + * created tunnel or NULL **/ -static int -ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) +static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) { struct net_device *dev; struct ip6_tnl *t; @@ -236,11 +235,11 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) break; } if (i == IP6_TNL_MAX) - return -ENOBUFS; + goto failed; } dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup); if (dev == NULL) - return -ENOMEM; + goto failed; t = netdev_priv(dev); dev->init = ip6ip6_tnl_dev_init; @@ -248,13 +247,13 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) if ((err = register_netdevice(dev)) < 0) { free_netdev(dev); - return err; + goto failed; } dev_hold(dev); - ip6ip6_tnl_link(t); - *pt = t; - return 0; + return t; +failed: + return NULL; } /** @@ -268,32 +267,23 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) * tunnel device is created and registered for use. * * Return: - * 0 if tunnel located or created, - * -EINVAL if parameters incorrect, - * -ENODEV if no matching tunnel available + * matching tunnel or NULL **/ -static int -ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create) +static struct ip6_tnl *ip6ip6_tnl_locate(struct ip6_tnl_parm *p, int create) { struct in6_addr *remote = &p->raddr; struct in6_addr *local = &p->laddr; struct ip6_tnl *t; - if (p->proto != IPPROTO_IPV6) - return -EINVAL; - for (t = *ip6ip6_bucket(p); t; t = t->next) { if (ipv6_addr_equal(local, &t->parms.laddr) && - ipv6_addr_equal(remote, &t->parms.raddr)) { - *pt = t; - return (create ? -EEXIST : 0); - } + ipv6_addr_equal(remote, &t->parms.raddr)) + return t; } if (!create) - return -ENODEV; - - return ip6_tnl_create(p, pt); + return NULL; + return ip6_tnl_create(p); } /** @@ -920,26 +910,20 @@ static int ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int err = 0; - int create; struct ip6_tnl_parm p; struct ip6_tnl *t = NULL; switch (cmd) { case SIOCGETTUNNEL: if (dev == ip6ip6_fb_tnl_dev) { - if (copy_from_user(&p, - ifr->ifr_ifru.ifru_data, - sizeof (p))) { + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { err = -EFAULT; break; } - if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV) - t = netdev_priv(dev); - else if (err) - break; - } else + t = ip6ip6_tnl_locate(&p, 0); + } + if (t == NULL) t = netdev_priv(dev); - memcpy(&p, &t->parms, sizeof (p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { err = -EFAULT; @@ -948,35 +932,36 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCADDTUNNEL: case SIOCCHGTUNNEL: err = -EPERM; - create = (cmd == SIOCADDTUNNEL); if (!capable(CAP_NET_ADMIN)) break; - if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { - err = -EFAULT; + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) break; - } - if (!create && dev != ip6ip6_fb_tnl_dev) { - t = netdev_priv(dev); - } - if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) { + err = -EINVAL; + if (p.proto != IPPROTO_IPV6) break; - } - if (cmd == SIOCCHGTUNNEL) { - if (t->dev != dev) { - err = -EEXIST; - break; - } + t = ip6ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); + if (dev != ip6ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { + if (t != NULL) { + if (t->dev != dev) { + err = -EEXIST; + break; + } + } else + t = netdev_priv(dev); + ip6ip6_tnl_unlink(t); err = ip6ip6_tnl_change(t, &p); ip6ip6_tnl_link(t); netdev_state_change(dev); } - if (copy_to_user(ifr->ifr_ifru.ifru_data, - &t->parms, sizeof (p))) { - err = -EFAULT; - } else { + if (t) { err = 0; - } + if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof (p))) + err = -EFAULT; + + } else + err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); break; case SIOCDELTUNNEL: err = -EPERM; @@ -984,22 +969,18 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; if (dev == ip6ip6_fb_tnl_dev) { - if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, - sizeof (p))) { - err = -EFAULT; + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) break; - } - err = ip6ip6_tnl_locate(&p, &t, 0); - if (err) + err = -ENOENT; + if ((t = ip6ip6_tnl_locate(&p, 0)) == NULL) break; - if (t == netdev_priv(ip6ip6_fb_tnl_dev)) { - err = -EPERM; + err = -EPERM; + if (t->dev == ip6ip6_fb_tnl_dev) break; - } - } else { - t = netdev_priv(dev); + dev = t->dev; } - err = unregister_netdevice(t->dev); + err = unregister_netdevice(dev); break; default: err = -EINVAL; -- cgit v1.2.3-70-g09d2 From 09c6bbf090ecb52c8d670fa4d5730be134a8ec8b Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Fri, 24 Nov 2006 17:06:27 -0800 Subject: [IPV6]: Do mandatory IPv6 tunnel endpoint checks in realtime Doing the mandatory tunnel endpoint checks when the tunnel is set up isn't enough as interfaces can go up or down and addresses can be added or deleted after this. The checks need to be done realtime when the tunnel is processing a packet. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 96 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 34 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fdf1a2fa3a3d..22debbf28b8a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -494,6 +494,27 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) IP6_ECN_set_ce(inner_iph); } +static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) +{ + struct ip6_tnl_parm *p = &t->parms; + int ret = 0; + + if (p->flags & IP6_TNL_F_CAP_RCV) { + struct net_device *ldev = NULL; + + if (p->link) + ldev = dev_get_by_index(p->link); + + if ((ipv6_addr_is_multicast(&p->laddr) || + likely(ipv6_chk_addr(&p->laddr, ldev, 0))) && + likely(!ipv6_chk_addr(&p->raddr, NULL, 0))) + ret = 1; + + if (ldev) + dev_put(ldev); + } + return ret; +} /** * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally @@ -518,7 +539,7 @@ ip6ip6_rcv(struct sk_buff *skb) goto discard; } - if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { + if (!ip6_tnl_rcv_ctl(t)) { t->stat.rx_dropped++; read_unlock(&ip6ip6_lock); goto discard; @@ -597,6 +618,34 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); } +static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) +{ + struct ip6_tnl_parm *p = &t->parms; + int ret = 0; + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + struct net_device *ldev = NULL; + + if (p->link) + ldev = dev_get_by_index(p->link); + + if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0))) + printk(KERN_WARNING + "%s xmit: Local address not yet configured!\n", + p->name); + else if (!ipv6_addr_is_multicast(&p->raddr) && + unlikely(ipv6_chk_addr(&p->raddr, NULL, 0))) + printk(KERN_WARNING + "%s xmit: Routing loop! " + "Remote address found on this node!\n", + p->name); + else + ret = 1; + if (ldev) + dev_put(ldev); + } + return ret; +} /** * ip6ip6_tnl_xmit - encapsulate packet and send * @skb: the outgoing socket buffer @@ -634,10 +683,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_err; } if (skb->protocol != htons(ETH_P_IPV6) || - !(t->parms.flags & IP6_TNL_F_CAP_XMIT) || - ip6ip6_tnl_addr_conflict(t, ipv6h)) { + !ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h)) goto tx_err; - } + if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { struct ipv6_tlv_tnl_enc_lim *tel; tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; @@ -768,39 +816,19 @@ tx_err: static void ip6_tnl_set_cap(struct ip6_tnl *t) { struct ip6_tnl_parm *p = &t->parms; - struct in6_addr *laddr = &p->laddr; - struct in6_addr *raddr = &p->raddr; - int ltype = ipv6_addr_type(laddr); - int rtype = ipv6_addr_type(raddr); + int ltype = ipv6_addr_type(&p->laddr); + int rtype = ipv6_addr_type(&p->raddr); p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV); - if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY && - ((ltype|rtype) & - (IPV6_ADDR_UNICAST| - IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL| - IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) { - struct net_device *ldev = NULL; - int l_ok = 1; - int r_ok = 1; - - if (p->link) - ldev = dev_get_by_index(p->link); - - if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0)) - l_ok = 0; - - if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0)) - r_ok = 0; - - if (l_ok && r_ok) { - if (ltype&IPV6_ADDR_UNICAST) - p->flags |= IP6_TNL_F_CAP_XMIT; - if (rtype&IPV6_ADDR_UNICAST) - p->flags |= IP6_TNL_F_CAP_RCV; - } - if (ldev) - dev_put(ldev); + if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + !((ltype|rtype) & IPV6_ADDR_LOOPBACK) && + !((ltype|rtype) & IPV6_ADDR_LINKLOCAL)) { + if (ltype&IPV6_ADDR_UNICAST) + p->flags |= IP6_TNL_F_CAP_XMIT; + if (rtype&IPV6_ADDR_UNICAST) + p->flags |= IP6_TNL_F_CAP_RCV; } } -- cgit v1.2.3-70-g09d2 From 305d4b3ce8c2f00643edc3bb19f005f72e8f84fc Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Fri, 24 Nov 2006 17:06:53 -0800 Subject: [IPV6]: Allow link-local tunnel endpoints Allow link-local tunnel endpoints if the underlying link is defined. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 22debbf28b8a..3944ea24c38c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -460,6 +460,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) { struct rt6_info *rt; struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); + if (!skb2) goto out; @@ -824,7 +825,7 @@ static void ip6_tnl_set_cap(struct ip6_tnl *t) if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && !((ltype|rtype) & IPV6_ADDR_LOOPBACK) && - !((ltype|rtype) & IPV6_ADDR_LINKLOCAL)) { + (!((ltype|rtype) & IPV6_ADDR_LINKLOCAL) || p->link)) { if (ltype&IPV6_ADDR_UNICAST) p->flags |= IP6_TNL_F_CAP_XMIT; if (rtype&IPV6_ADDR_UNICAST) @@ -862,8 +863,11 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t) dev->iflink = p->link; if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); + struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, - p->link, 0); + p->link, strict); if (rt == NULL) return; -- cgit v1.2.3-70-g09d2 From 6fb32ddeb2502292bb89e17f58600ce265598ed7 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Fri, 24 Nov 2006 17:08:32 -0800 Subject: [IPV6]: Don't allocate memory for Tunnel Encapsulation Limit Option Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 58 +++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3944ea24c38c..daad1e5a2a85 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -572,31 +572,23 @@ discard: return 0; } -static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) -{ - struct ipv6_tlv_tnl_enc_lim *tel; - struct ipv6_txoptions *opt; - __u8 *raw; - - int opt_len = sizeof(*opt) + 8; - - if (!(opt = kzalloc(opt_len, GFP_ATOMIC))) { - return NULL; - } - opt->tot_len = opt_len; - opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1); - opt->opt_nflen = 8; +struct ipv6_tel_txoption { + struct ipv6_txoptions ops; + __u8 dst_opt[8]; +}; - tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1); - tel->type = IPV6_TLV_TNL_ENCAP_LIMIT; - tel->length = 1; - tel->encap_limit = encap_limit; +static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) +{ + memset(opt, 0, sizeof(struct ipv6_tel_txoption)); - raw = (__u8 *) opt->dst0opt; - raw[5] = IPV6_TLV_PADN; - raw[6] = 1; + opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT; + opt->dst_opt[3] = 1; + opt->dst_opt[4] = encap_limit; + opt->dst_opt[5] = IPV6_TLV_PADN; + opt->dst_opt[6] = 1; - return opt; + opt->ops.dst0opt = (struct ipv6_opt_hdr *) opt->dst_opt; + opt->ops.opt_nflen = 8; } /** @@ -666,8 +658,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) struct ip6_tnl *t = netdev_priv(dev); struct net_device_stats *stats = &t->stat; struct ipv6hdr *ipv6h = skb->nh.ipv6h; - struct ipv6_txoptions *opt = NULL; int encap_limit = -1; + struct ipv6_tel_txoption opt; __u16 offset; struct flowi fl; struct dst_entry *dst; @@ -696,9 +688,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_err; } encap_limit = tel->encap_limit - 1; - } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { + } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) encap_limit = t->parms.encap_limit; - } + memcpy(&fl, &t->fl, sizeof (fl)); proto = fl.proto; @@ -708,9 +700,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); - if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL) - goto tx_err; - if ((dst = ip6_tnl_dst_check(t)) != NULL) dst_hold(dst); else { @@ -731,7 +720,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_err_dst_release; } mtu = dst_mtu(dst) - sizeof (*ipv6h); - if (opt) { + if (encap_limit >= 0) { max_headroom += 8; mtu -= 8; } @@ -769,9 +758,10 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) skb->h.raw = skb->nh.raw; - if (opt) - ipv6_push_nfrag_opts(skb, opt, &proto, NULL); - + if (encap_limit >= 0) { + init_tel_txopt(&opt, encap_limit); + ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); + } skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr)); ipv6h = skb->nh.ipv6h; *(__be32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); @@ -795,9 +785,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) stats->tx_aborted_errors++; } ip6_tnl_dst_store(t, dst); - - kfree(opt); - t->recursion--; return 0; tx_err_link_failure: @@ -805,7 +792,6 @@ tx_err_link_failure: dst_link_failure(skb); tx_err_dst_release: dst_release(dst); - kfree(opt); tx_err: stats->tx_errors++; stats->tx_dropped++; -- cgit v1.2.3-70-g09d2 From 107a5fe6191249878de0de42bb64d3c35be1a986 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Fri, 24 Nov 2006 17:08:58 -0800 Subject: [IPV6]: Improve IPv6 tunnel error reporting Log an error if the remote tunnel endpoint is unable to handle tunneled packets. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index daad1e5a2a85..8d918348f5bb 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -424,12 +424,9 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } break; case ICMPV6_PARAMPROB: - /* ignore if parameter problem not caused by a tunnel - encapsulation limit sub-option */ - if (code != ICMPV6_HDR_FIELD) { - break; - } - teli = parse_tlv_tnl_enc_lim(skb, skb->data); + teli = 0; + if (code == ICMPV6_HDR_FIELD) + teli = parse_tlv_tnl_enc_lim(skb, skb->data); if (teli && teli == ntohl(info) - 2) { tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; @@ -441,6 +438,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, "tunnel!\n", t->parms.name); rel_msg = 1; } + } else if (net_ratelimit()) { + printk(KERN_WARNING + "%s: Recipient unable to parse tunneled " + "packet!\n ", t->parms.name); } break; case ICMPV6_PKT_TOOBIG: -- cgit v1.2.3-70-g09d2 From a6f01cace3a6532c6f22d8e2fdefed3632ea61b2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 24 Nov 2006 17:14:07 -0800 Subject: [DECNET] address: Calculate accurate message size for netlink notifications Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 5b451e196fb9..2459a8d236a0 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -711,6 +711,14 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a return rv; } +static inline size_t dn_ifaddr_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ + + nla_total_size(2) /* IFA_ADDRESS */ + + nla_total_size(2); /* IFA_LOCAL */ +} + static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, u32 pid, u32 seq, int event, unsigned int flags) { @@ -744,18 +752,15 @@ rtattr_failure: static void rtmsg_ifa(int event, struct dn_ifaddr *ifa) { struct sk_buff *skb; - int payload = sizeof(struct ifaddrmsg) + 128; int err = -ENOBUFS; - skb = alloc_skb(nlmsg_total_size(payload), GFP_KERNEL); + skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL); if (skb == NULL) goto errout; err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in dn_ifaddr_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL); errout: -- cgit v1.2.3-70-g09d2 From b020b942cdc238e9761cb38598eda6691c366d68 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 24 Nov 2006 17:14:31 -0800 Subject: [DECNET] address: Rename rtmsg_ifa() to dn_ifaddr_notify() The name rtmsg_ifa is heavly overused and confusing. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 2459a8d236a0..309b2c7a4c6c 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -73,7 +73,7 @@ static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); static void dn_dev_delete(struct net_device *dev); -static void rtmsg_ifa(int event, struct dn_ifaddr *ifa); +static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa); static int dn_eth_up(struct net_device *); static void dn_eth_down(struct net_device *); @@ -440,7 +440,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de } } - rtmsg_ifa(RTM_DELADDR, ifa1); + dn_ifaddr_notify(RTM_DELADDR, ifa1); blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); if (destroy) { dn_dev_free_ifa(ifa1); @@ -475,7 +475,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) ifa->ifa_next = dn_db->ifa_list; dn_db->ifa_list = ifa; - rtmsg_ifa(RTM_NEWADDR, ifa); + dn_ifaddr_notify(RTM_NEWADDR, ifa); blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); return 0; @@ -749,7 +749,7 @@ rtattr_failure: return -1; } -static void rtmsg_ifa(int event, struct dn_ifaddr *ifa) +static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa) { struct sk_buff *skb; int err = -ENOBUFS; -- cgit v1.2.3-70-g09d2 From 4a89c2562cb81c24c515b9de041aced4d21cb6d1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 24 Nov 2006 17:14:51 -0800 Subject: [DECNET] address: Convert to new netlink interface Extends the netlink interface to support the __le16 type and converts address addition, deletion and, dumping to use the new netlink interface. Fixes multiple occasions of possible illegal memory references due to not validated netlink attributes. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/netlink.h | 12 +++++ net/decnet/dn_dev.c | 142 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 97 insertions(+), 57 deletions(-) (limited to 'net') diff --git a/include/net/netlink.h b/include/net/netlink.h index 30021339157c..fd75fd65d59e 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -829,6 +829,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, #define NLA_PUT_U16(skb, attrtype, value) \ NLA_PUT_TYPE(skb, u16, attrtype, value) +#define NLA_PUT_LE16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, __le16, attrtype, value) + #define NLA_PUT_U32(skb, attrtype, value) \ NLA_PUT_TYPE(skb, u32, attrtype, value) @@ -874,6 +877,15 @@ static inline u16 nla_get_u16(struct nlattr *nla) return *(u16 *) nla_data(nla); } +/** + * nla_get_le16 - return payload of __le16 attribute + * @nla: __le16 netlink attribute + */ +static inline __le16 nla_get_le16(struct nlattr *nla) +{ + return *(__le16 *) nla_data(nla); +} + /** * nla_get_u8 - return payload of u8 attribute * @nla: u8 netlink attribute diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 309b2c7a4c6c..0b9d4c955154 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -645,41 +645,62 @@ static struct dn_dev *dn_dev_by_index(int ifindex) return dn_dev; } -static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = { + [IFA_ADDRESS] = { .type = NLA_U16 }, + [IFA_LOCAL] = { .type = NLA_U16 }, + [IFA_LABEL] = { .type = NLA_STRING, + .len = IFNAMSIZ - 1 }, +}; + +static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct rtattr **rta = arg; + struct nlattr *tb[IFA_MAX+1]; struct dn_dev *dn_db; - struct ifaddrmsg *ifm = NLMSG_DATA(nlh); + struct ifaddrmsg *ifm; struct dn_ifaddr *ifa, **ifap; + int err = -EADDRNOTAVAIL; + + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); + if (err < 0) + goto errout; + ifm = nlmsg_data(nlh); if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL) - return -EADDRNOTAVAIL; + goto errout; + + for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) { + if (tb[IFA_LOCAL] && + nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2)) + continue; - for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) { - void *tmp = rta[IFA_LOCAL-1]; - if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) || - (rta[IFA_LABEL-1] && rtattr_strcmp(rta[IFA_LABEL-1], ifa->ifa_label))) + if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) continue; dn_dev_del_ifa(dn_db, ifap, 1); return 0; } - return -EADDRNOTAVAIL; +errout: + return err; } -static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct rtattr **rta = arg; + struct nlattr *tb[IFA_MAX+1]; struct net_device *dev; struct dn_dev *dn_db; - struct ifaddrmsg *ifm = NLMSG_DATA(nlh); + struct ifaddrmsg *ifm; struct dn_ifaddr *ifa; - int rv; + int err; + + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); + if (err < 0) + return err; - if (rta[IFA_LOCAL-1] == NULL) + if (tb[IFA_LOCAL] == NULL) return -EINVAL; + ifm = nlmsg_data(nlh); if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) return -ENODEV; @@ -693,22 +714,25 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a if ((ifa = dn_dev_alloc_ifa()) == NULL) return -ENOBUFS; - if (!rta[IFA_ADDRESS - 1]) - rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; - memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2); - memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2); + if (tb[IFA_ADDRESS] == NULL) + tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + + ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]); + ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; ifa->ifa_dev = dn_db; - if (rta[IFA_LABEL-1]) - rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL-1], IFNAMSIZ); + + if (tb[IFA_LABEL]) + nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); - rv = dn_dev_insert_ifa(dn_db, ifa); - if (rv) + err = dn_dev_insert_ifa(dn_db, ifa); + if (err) dn_dev_free_ifa(ifa); - return rv; + + return err; } static inline size_t dn_ifaddr_nlmsg_size(void) @@ -719,34 +743,34 @@ static inline size_t dn_ifaddr_nlmsg_size(void) + nla_total_size(2); /* IFA_LOCAL */ } -static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, - u32 pid, u32 seq, int event, unsigned int flags) +static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, + u32 pid, u32 seq, int event, unsigned int flags) { struct ifaddrmsg *ifm; struct nlmsghdr *nlh; - unsigned char *b = skb->tail; - nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); - ifm = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); + if (nlh == NULL) + return -ENOBUFS; + ifm = nlmsg_data(nlh); ifm->ifa_family = AF_DECnet; ifm->ifa_prefixlen = 16; ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT; ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; + if (ifa->ifa_address) - RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address); + NLA_PUT_LE16(skb, IFA_ADDRESS, ifa->ifa_address); if (ifa->ifa_local) - RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local); + NLA_PUT_LE16(skb, IFA_LOCAL, ifa->ifa_local); if (ifa->ifa_label[0]) - RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); - nlh->nlmsg_len = skb->tail - b; - return skb->len; + NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); -nlmsg_failure: -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; + return nlmsg_end(skb, nlh); + +nla_put_failure: + return nlmsg_cancel(skb, nlh); } static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa) @@ -758,7 +782,7 @@ static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa) if (skb == NULL) goto errout; - err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0); + err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0); /* failure implies BUG in dn_ifaddr_nlmsg_size() */ BUG_ON(err < 0); @@ -768,39 +792,43 @@ errout: rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err); } -static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) +static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) { - int idx, dn_idx; - int s_idx, s_dn_idx; + int idx, dn_idx = 0, skip_ndevs, skip_naddr; struct net_device *dev; struct dn_dev *dn_db; struct dn_ifaddr *ifa; - s_idx = cb->args[0]; - s_dn_idx = dn_idx = cb->args[1]; + skip_ndevs = cb->args[0]; + skip_naddr = cb->args[1]; + read_lock(&dev_base_lock); - for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { - if (idx < s_idx) + for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { + if (idx < skip_ndevs) continue; - if (idx > s_idx) - s_dn_idx = 0; + else if (idx > skip_ndevs) { + /* Only skip over addresses for first dev dumped + * in this iteration (idx == skip_ndevs) */ + skip_naddr = 0; + } + if ((dn_db = dev->dn_ptr) == NULL) continue; - for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) { - if (dn_idx < s_dn_idx) + for (ifa = dn_db->ifa_list, dn_idx = 0; ifa; + ifa = ifa->ifa_next, dn_idx++) { + if (dn_idx < skip_naddr) continue; - if (dn_dev_fill_ifaddr(skb, ifa, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWADDR, - NLM_F_MULTI) <= 0) + if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, RTM_NEWADDR, + NLM_F_MULTI) < 0) goto done; } } done: read_unlock(&dev_base_lock); + cb->args[0] = idx; cb->args[1] = dn_idx; @@ -1417,9 +1445,9 @@ static struct file_operations dn_dev_seq_fops = { static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_NEWADDR - RTM_BASE] = { .doit = dn_dev_rtm_newaddr, }, - [RTM_DELADDR - RTM_BASE] = { .doit = dn_dev_rtm_deladdr, }, - [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_dev_dump_ifaddr, }, + [RTM_NEWADDR - RTM_BASE] = { .doit = dn_nl_newaddr, }, + [RTM_DELADDR - RTM_BASE] = { .doit = dn_nl_deladdr, }, + [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_nl_dump_ifaddr, }, #ifdef CONFIG_DECNET_ROUTER [RTM_NEWROUTE - RTM_BASE] = { .doit = dn_fib_rtm_newroute, }, [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, }, -- cgit v1.2.3-70-g09d2 From 0bd4ff1b1528a39b07aab6c744ac37e053740ad0 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Tue, 21 Nov 2006 16:17:10 -0200 Subject: [DCCP] ackvec: Remove unused dccpav_ack_ptr field from dccp_ackvec Commiter note: original patch was splitted. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ackvec.c | 1 - net/dccp/ackvec.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'net') diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 1b4b60d8bdec..215355d993de 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -141,7 +141,6 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1; av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1; av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; - av->dccpav_ack_ptr = 0; av->dccpav_time.tv_sec = 0; av->dccpav_time.tv_usec = 0; av->dccpav_vec_len = 0; diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index cf8f20ce23a9..d6a58db5fb13 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h @@ -41,7 +41,6 @@ * Ack Vectors it has recently sent. For each packet sent carrying an * Ack Vector, it remembers four variables: * - * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement. * @dccpav_records - list of dccp_ackvec_record * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. * @@ -53,7 +52,6 @@ struct dccp_ackvec { struct list_head dccpav_records; struct timeval dccpav_time; u8 dccpav_buf_head; - u8 dccpav_ack_ptr; u8 dccpav_vec_len; u8 dccpav_buf_nonce; u8 dccpav_ack_nonce; -- cgit v1.2.3-70-g09d2 From bdf13d208dee4ada6d2b422536a12b45d5831aa3 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Fri, 24 Nov 2006 13:02:42 -0200 Subject: [DCCP] ackvec: infrastructure for sending more than one ackvec per packet Commiter note: This was split from Andrea's original patch, in the process I changed the type of the ackvec index fields to u16 instead of to int and haven't folded dccp_ackvec_parse with dccp_ackvec_check_rcv_ackno. Next patch will actually do the insertion of more than one ackvec per packet, using, initially, up to a max of 2 ackvecs as per Andrea's original patch, then I'll work on support for larger ackvecs, be it using a sysctl or using setsockopt. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ackvec.c | 23 +++++++++++------------ net/dccp/ackvec.h | 18 +++++++++++------- net/dccp/options.c | 3 ++- 3 files changed, 24 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 215355d993de..41d34d1babc1 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -169,13 +169,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av) } static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, - const u8 index) + const u32 index) { return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; } static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, - const u8 index) + const u32 index) { return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; } @@ -275,7 +275,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, * could reduce the complexity of this scan.) */ u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); - u8 index = av->dccpav_buf_head; + u32 index = av->dccpav_buf_head; while (1) { const u8 len = dccp_ackvec_len(av, index); @@ -385,7 +385,7 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, } static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, - struct sock *sk, u64 ackno, + struct sock *sk, u64 *ackno, const unsigned char len, const unsigned char *vector) { @@ -408,7 +408,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; u64 ackno_end_rl; - dccp_set_seqno(&ackno_end_rl, ackno - rl); + dccp_set_seqno(&ackno_end_rl, *ackno - rl); /* * If our AVR sequence number is greater than the ack, go @@ -416,13 +416,13 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, */ list_for_each_entry_from(avr, &av->dccpav_records, dccpavr_node) { - if (!after48(avr->dccpavr_ack_seqno, ackno)) + if (!after48(avr->dccpavr_ack_seqno, *ackno)) goto found; } /* End of the dccpav_records list, not found, exit */ break; found: - if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { + if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, *ackno)) { const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { dccp_pr_debug("%s ACK vector 0, len=%d, " @@ -442,21 +442,20 @@ found: */ } - dccp_set_seqno(&ackno, ackno_end_rl - 1); + dccp_set_seqno(ackno, ackno_end_rl - 1); ++vector; } } int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, - const u8 opt, const u8 *value, const u8 len) + u64 *ackno, const u8 opt, const u8 *value, const u8 len) { - if (len > DCCP_MAX_ACKVEC_LEN) + if (len > DCCP_MAX_ACKVEC_OPT_LEN) return -1; /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq, - len, value); + ackno, len, value); return 0; } diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index d6a58db5fb13..96504a3b16e4 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h @@ -17,7 +17,9 @@ #include /* Read about the ECN nonce to see why it is 253 */ -#define DCCP_MAX_ACKVEC_LEN 253 +#define DCCP_MAX_ACKVEC_OPT_LEN 253 +/* We can spread an ack vector across multiple options */ +#define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2) #define DCCP_ACKVEC_STATE_RECEIVED 0 #define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) @@ -51,8 +53,8 @@ struct dccp_ackvec { u64 dccpav_buf_ackno; struct list_head dccpav_records; struct timeval dccpav_time; - u8 dccpav_buf_head; - u8 dccpav_vec_len; + u16 dccpav_buf_head; + u16 dccpav_vec_len; u8 dccpav_buf_nonce; u8 dccpav_ack_nonce; u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN]; @@ -75,9 +77,9 @@ struct dccp_ackvec_record { struct list_head dccpavr_node; u64 dccpavr_ack_seqno; u64 dccpavr_ack_ackno; - u8 dccpavr_ack_ptr; + u16 dccpavr_ack_ptr; + u16 dccpavr_sent_len; u8 dccpavr_ack_nonce; - u8 dccpavr_sent_len; }; struct sock; @@ -96,7 +98,8 @@ extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, const u64 ackno); extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, - const u8 opt, const u8 *value, const u8 len); + u64 *ackno, const u8 opt, + const u8 *value, const u8 len); extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); @@ -135,7 +138,8 @@ static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, } static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, - const u8 opt, const u8 *value, const u8 len) + const u64 *ackno, const u8 opt, + const u8 *value, const u8 len) { return -1; } diff --git a/net/dccp/options.c b/net/dccp/options.c index ee709ae0a97f..f398b43bc055 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -62,6 +62,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) struct dccp_sock *dp = dccp_sk(sk); const struct dccp_hdr *dh = dccp_hdr(skb); const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; + u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); unsigned char *opt_ptr = options; const unsigned char *opt_end = (unsigned char *)dh + @@ -149,7 +150,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) break; if (dccp_msk(sk)->dccpms_send_ack_vector && - dccp_ackvec_parse(sk, skb, opt, value, len)) + dccp_ackvec_parse(sk, skb, &ackno, opt, value, len)) goto out_invalid_option; break; case DCCPO_TIMESTAMP: -- cgit v1.2.3-70-g09d2 From 522f1d095bf76dbe2430fb9a9a257c0f27033f31 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Sun, 26 Nov 2006 01:04:40 -0200 Subject: [DCCP] ackvec: Split long ack vectors across multiple options Ack vectors grow proportional to the window size. If an ack vector does not fit into a single option, it must be spread across multiple options. This patch will allow for windows to grow larger. Committer note: Simplified the patch a bit, original algorithm kept. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ackvec.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'net') diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 41d34d1babc1..bdf1bb7a82c0 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -68,10 +68,15 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; - int len = av->dccpav_vec_len + 2; + /* Figure out how many options do we need to represent the ackvec */ + const u16 nr_opts = (av->dccpav_vec_len + + DCCP_MAX_ACKVEC_OPT_LEN - 1) / + DCCP_MAX_ACKVEC_OPT_LEN; + u16 len = av->dccpav_vec_len + 2 * nr_opts, i; struct timeval now; u32 elapsed_time; - unsigned char *to, *from; + const unsigned char *tail, *from; + unsigned char *to; struct dccp_ackvec_record *avr; if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) @@ -90,24 +95,37 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) DCCP_SKB_CB(skb)->dccpd_opt_len += len; - to = skb_push(skb, len); - *to++ = DCCPO_ACK_VECTOR_0; - *to++ = len; - + to = skb_push(skb, len); len = av->dccpav_vec_len; from = av->dccpav_buf + av->dccpav_buf_head; + tail = av->dccpav_buf + DCCP_MAX_ACKVEC_LEN; + + for (i = 0; i < nr_opts; ++i) { + int copylen = len; + + if (len > DCCP_MAX_ACKVEC_OPT_LEN) + copylen = DCCP_MAX_ACKVEC_OPT_LEN; - /* Check if buf_head wraps */ - if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) { - const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head; + *to++ = DCCPO_ACK_VECTOR_0; + *to++ = copylen + 2; + + /* Check if buf_head wraps */ + if (from + copylen > tail) { + const u16 tailsize = tail - from; + + memcpy(to, from, tailsize); + to += tailsize; + len -= tailsize; + copylen -= tailsize; + from = av->dccpav_buf; + } - memcpy(to, from, tailsize); - to += tailsize; - len -= tailsize; - from = av->dccpav_buf; + memcpy(to, from, copylen); + from += copylen; + to += copylen; + len -= copylen; } - memcpy(to, from, len); /* * From RFC 4340, A.2: * -- cgit v1.2.3-70-g09d2 From 6472c051fcc5e571a9abee7f7a1ac58cc6e7bafa Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Sun, 26 Nov 2006 01:07:50 -0200 Subject: [DCCP] ccid2: Allow window to grow larger Now that we can stuff bigger ack vectors into options. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index a97a89927308..ebd79499c85a 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -35,7 +35,7 @@ struct ccid2_seq { struct ccid2_seq *ccid2s_next; }; -#define CCID2_SEQBUF_LEN 256 +#define CCID2_SEQBUF_LEN 1024 #define CCID2_SEQBUF_MAX 128 /** struct ccid2_hc_tx_sock - CCID2 TX half connection -- cgit v1.2.3-70-g09d2 From 90feeb951f61a80d3a8f8e5ced25b9ec78867eaf Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:13:38 -0200 Subject: [DCCP] ccid3: Fix bug in calculation of first t_nom and first t_ipi Problem: --- net/dccp/ccids/ccid3.c | 11 ++++++----- net/dccp/ccids/ccid3.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index fb21f2d9ffc6..d7b688e9f983 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -298,13 +298,14 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, hctx->ccid3hctx_last_win_count = 0; hctx->ccid3hctx_t_last_win_count = now; ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); - hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI; - /* Set nominal send time for initial packet */ + /* First timeout, according to [RFC 3448, 4.2], is 1 second */ + hctx->ccid3hctx_t_ipi = USEC_PER_SEC; + /* Initial delta: minimum of 0.5 sec and t_gran/2 */ + hctx->ccid3hctx_delta = TFRC_OPSYS_HALF_TIME_GRAN; + + /* Set t_0 for initial packet */ hctx->ccid3hctx_t_nom = now; - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_delta(hctx); rc = 0; break; case TFRC_SSTATE_NO_FBACK: diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index e2e43c1a4726..462165234ff6 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -49,8 +49,6 @@ /* Two seconds as per CCID3 spec */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) -#define TFRC_INITIAL_IPI (USEC_PER_SEC / 4) - /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ #define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) -- cgit v1.2.3-70-g09d2 From f5c2d6367b04fd5ba98a5f9846b5fb870423968a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:22:48 -0200 Subject: [DCCP] ccid3: Simplify control flow in the calculation of t_ipi This patch performs a simplifying (performance) optimisation: In each call of the inline function ccid3_calc_new_t_ipi(), the state is tested against TFRC_SSTATE_NO_FBACK. This is expensive when the function is called very often. A simpler solution, implemented by this patch, is to adapt the control flow. Background: --- net/dccp/ccids/ccid3.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index d7b688e9f983..df88c54b2ec5 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -103,13 +103,7 @@ static void ccid3_hc_tx_set_state(struct sock *sk, /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) { - /* - * If no feedback spec says t_ipi is 1 second (set elsewhere and then - * doubles after every no feedback timer (separate function) - */ - if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) - hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x); + hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); } /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ @@ -395,6 +389,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) "as a data packet", dccp_role(sk)); return; case TFRC_SSTATE_NO_FBACK: + /* t_nom, t_ipi, delta do not change until feedback arrives */ + return; case TFRC_SSTATE_FBACK: if (len > 0) { timeval_sub_usecs(&hctx->ccid3hctx_t_nom, -- cgit v1.2.3-70-g09d2 From 91cf5a17257e1d2ef936fbf0223c3436ca583af9 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:25:10 -0200 Subject: [DCCP] ccid3: Fix calculation of t_ipi time of scheduled transmission Problem: --- net/dccp/ccids/ccid3.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index df88c54b2ec5..fb1a5e89c023 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -304,11 +304,19 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, break; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: - delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - - hctx->ccid3hctx_delta); - delay /= -1000; - /* divide by -1000 is to convert to ms and get sign right */ - rc = delay > 0 ? delay : 0; + delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); + /* + * Scheduling of packet transmissions [RFC 3448, 4.6] + * + * if (t_now > t_nom - delta) + * // send the packet now + * else + * // send the packet in (t_nom - t_now) milliseconds. + */ + if (delay < hctx->ccid3hctx_delta) + rc = 0; + else + rc = delay/1000L; break; case TFRC_SSTATE_TERM: DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); -- cgit v1.2.3-70-g09d2 From 7da7f456d7bc0e52009f882e8af0ac910293e157 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:26:03 -0200 Subject: [DCCP] ccid3: Simplify control flow of ccid3_hc_tx_send_packet This makes some logically equivalent simplifications, by replacing rc - values plus goto's with direct return statements. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index fb1a5e89c023..2745d835f037 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -247,6 +247,12 @@ out: sock_put(sk); } +/* + * returns + * > 0: delay (in msecs) that should pass before actually sending + * = 0: can send immediately + * < 0: error condition; do not send packet + */ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, int len) { @@ -255,7 +261,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct dccp_tx_hist_entry *new_packet; struct timeval now; long delay; - int rc = -ENOTCONN; BUG_ON(hctx == NULL); @@ -265,7 +270,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * packets can have zero length, but why the comment about "pure ACK"? */ if (unlikely(len == 0)) - goto out; + return -ENOTCONN; /* See if last packet allocated was not sent */ new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); @@ -273,11 +278,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, SLAB_ATOMIC); - rc = -ENOBUFS; if (unlikely(new_packet == NULL)) { DCCP_WARN("%s, sk=%p, not enough mem to add to history," "send refused\n", dccp_role(sk), sk); - goto out; + return -ENOBUFS; } dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); @@ -300,7 +304,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, /* Set t_0 for initial packet */ hctx->ccid3hctx_t_nom = now; - rc = 0; break; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: @@ -313,28 +316,21 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * else * // send the packet in (t_nom - t_now) milliseconds. */ - if (delay < hctx->ccid3hctx_delta) - rc = 0; - else - rc = delay/1000L; + if (delay >= hctx->ccid3hctx_delta) + return delay / 1000L; break; case TFRC_SSTATE_TERM: DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); - rc = -EINVAL; - break; + return -EINVAL; } - /* Can we send? if so add options and add to packet history */ - if (rc == 0) { - dp->dccps_hc_tx_insert_options = 1; - new_packet->dccphtx_ccval = - DCCP_SKB_CB(skb)->dccpd_ccval = - hctx->ccid3hctx_last_win_count; - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - } -out: - return rc; + /* prepare to send now (add options etc.) */ + dp->dccps_hc_tx_insert_options = 1; + new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval = + hctx->ccid3hctx_last_win_count; + timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); + + return 0; } static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) -- cgit v1.2.3-70-g09d2 From da335baf9e788edfb00ee3b96f7b9526b6b2f8a9 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:26:57 -0200 Subject: [DCCP] ccid3: Avoid congestion control on zero-sized data packets This resolves an `XXX' in ccid3_hc_tx_send_packet(). The function is only called on Data and DataAck packets and returns a negative result on zero-sized messages. This is a reasonable policy since CCID 3 is a congestion-control module and congestion control on zero-sized Data(Ack) packets is in a way pathological. The patch uses a more suitable error code for this case, it returns the Posix.1 code `EBADMSG' ("Not a data message") instead of `ENOTCONN'. As a result of ignoring zero-sized packets, a the condition for a warning "First packet is data" in ccid3_hc_tx_packet_sent is always satisfied; this message has been removed since it will always be printed. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 2745d835f037..62c304200eda 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -264,13 +264,13 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, BUG_ON(hctx == NULL); - /* Check if pure ACK or Terminating*/ /* - * XXX: We only call this function for DATA and DATAACK, on, these - * packets can have zero length, but why the comment about "pure ACK"? + * This function is called only for Data and DataAck packets. Sending + * zero-sized Data(Ack)s is theoretically possible, but for congestion + * control this case is pathological - ignore it. */ if (unlikely(len == 0)) - return -ENOTCONN; + return -EBADMSG; /* See if last packet allocated was not sent */ new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); @@ -387,11 +387,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_SENT: - /* if first wasn't pure ack */ - if (len != 0) - DCCP_CRIT("%s, First packet sent is noted " - "as a data packet", dccp_role(sk)); - return; + /* fall through */ case TFRC_SSTATE_NO_FBACK: /* t_nom, t_ipi, delta do not change until feedback arrives */ return; -- cgit v1.2.3-70-g09d2 From 70dbd5b0ef3915f1e018e6437c8db9e999b0d701 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:27:55 -0200 Subject: [DCCP] ccid3: Remove redundant statements in ccid3_hc_tx_packet_sent This patch removes a switch statement which is redundant since, * nothing is done in states TFRC_SSTATE_NO_SENT/TFRC_SSTATE_NO_FBACK * it is impossible that the function is called in the state TFRC_SSTATE_TERM, since --the function is called, in dccp_write_xmit, after ccid3_hc_tx_send_packet --if ccid3_hc_tx_send_packet is called in state TFRC_SSTATE_TERM, it returns -EINVAL, which means that ccid3_hc_tx_packet_sent will not be called (compare dccp_write_xmit) --> therefore, this case is logically impossible * the remaining state is TFRC_SSTATE_FBACK which conditionally updates t_ipi, t_nom, and t_delta. This is a no-op, since --t_ipi only changes when feedback is received --however, when feedback arrives via ccid3_hc_tx_packet_recv, there is an identical code block which performs the same set of operations --performing the same set of operations again in ccid3_hc_tx_packet_sent therefore does not change anything, since between the time of receiving the last feedback (and therefore update of t_ipi, t_nom, and t_delta), the value of t_ipi has not changed --since t_ipi has not changed, the values of t_delta and t_nom also do not change, they depend fully on t_ipi Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 62c304200eda..58f7cac6aa3d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -384,27 +384,6 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) } else ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", dccp_role(sk), sk, dp->dccps_gss); - - switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_NO_SENT: - /* fall through */ - case TFRC_SSTATE_NO_FBACK: - /* t_nom, t_ipi, delta do not change until feedback arrives */ - return; - case TFRC_SSTATE_FBACK: - if (len > 0) { - timeval_sub_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_t_ipi(hctx); - ccid3_calc_new_delta(hctx); - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - } - break; - case TFRC_SSTATE_TERM: - DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); - break; - } } static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) -- cgit v1.2.3-70-g09d2 From 5e19e3fcd7351de1ca87c4797cca27ba55c7e55e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:28:48 -0200 Subject: [DCCP] ccid3: Resolve small FIXME This considers the case - ACK received while no packet has been sent so far. Resolved by printing a (rate-limited) warning message. Further removes an unnecessary BUG_ON in ccid3_hc_tx_packet_recv, received feedback on a terminating connection is simply ignored. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 58f7cac6aa3d..6777a7f33a9a 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -413,9 +413,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) pinv = opt_recv->ccid3or_loss_event_rate; switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_NO_SENT: - /* FIXME: what to do here? */ - return; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: /* Calculate new round trip sample by @@ -521,8 +518,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - case TFRC_SSTATE_TERM: - DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); + case TFRC_SSTATE_NO_SENT: + DCCP_WARN("Illegal ACK received - no packet has been sent\n"); + /* fall through */ + case TFRC_SSTATE_TERM: /* ignore feedback when closing */ break; } } -- cgit v1.2.3-70-g09d2 From 4e9b82693542003b028c8494e9e3c49615b91ce7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 27 Nov 2006 09:25:58 -0800 Subject: [NETLINK]: Remove unused dst_pid field in netlink_skb_parms The destination PID is passed directly to netlink_unicast() respectively netlink_multicast(). Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/netlink.h | 1 - net/decnet/dn_route.c | 2 -- net/ipv4/fib_frontend.c | 1 - net/ipv4/netfilter/ip_conntrack_netlink.c | 4 +--- net/netfilter/nf_conntrack_netlink.c | 4 +--- net/netlink/af_netlink.c | 1 - net/xfrm/xfrm_user.c | 2 -- 7 files changed, 2 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/include/linux/netlink.h b/include/linux/netlink.h index e61e1e138421..b3b9b609ee89 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -141,7 +141,6 @@ struct netlink_skb_parms { struct ucred creds; /* Skb credentials */ __u32 pid; - __u32 dst_pid; __u32 dst_group; kernel_cap_t eff_cap; __u32 loginuid; /* Login (audit) uid */ diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index f759d6f422ea..4eb985236aee 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1592,8 +1592,6 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; - NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; - err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0); if (err == 0) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 14025345cc56..d47b72af89ed 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -811,7 +811,6 @@ static void nl_fib_input(struct sock *sk, int len) pid = nlh->nlmsg_pid; /*pid of sending process */ NETLINK_CB(skb).pid = 0; /* from kernel */ - NETLINK_CB(skb).dst_pid = pid; NETLINK_CB(skb).dst_group = 0; /* unicast */ netlink_unicast(sk, skb, pid, MSG_DONTWAIT); } diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 55f0ae641081..1bb8ed33c5bc 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -743,7 +743,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ip_conntrack_put(ct); return -ENOMEM; } - NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, IPCTNL_MSG_CT_NEW, 1, ct); @@ -1273,8 +1272,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) goto out; - NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; - + err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, 1, exp); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ab67c2be2b5d..cfb35fd8d9b9 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -752,7 +752,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, nf_ct_put(ct); return -ENOMEM; } - NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, IPCTNL_MSG_CT_NEW, 1, ct); @@ -1300,8 +1299,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) goto out; - NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; - + err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, 1, exp); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index f61d81b3c61c..3baafb10f8f3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1153,7 +1153,6 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, goto out; NETLINK_CB(skb).pid = nlk->pid; - NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); selinux_get_task_sid(current, &(NETLINK_CB(skb).sid)); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6c4d2f49d9e5..8dbb38b91de2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -650,7 +650,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, if (!skb) return ERR_PTR(-ENOMEM); - NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; info.in_skb = in_skb; info.out_skb = skb; info.nlmsg_seq = seq; @@ -1168,7 +1167,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, if (!skb) return ERR_PTR(-ENOMEM); - NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; info.in_skb = in_skb; info.out_skb = skb; info.nlmsg_seq = seq; -- cgit v1.2.3-70-g09d2 From e3703b3de1f049b38733ba520e5038f23063068e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 27 Nov 2006 09:27:07 -0800 Subject: [RTNETLINK]: Add rtnl_put_cacheinfo() to unify some code IPv4, IPv6, and DECNet all use struct rta_cacheinfo in a similiar way, therefore rtnl_put_cacheinfo() is added to reuse code. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 3 +++ net/core/rtnetlink.c | 20 ++++++++++++++++++++ net/decnet/dn_route.c | 16 +++++----------- net/ipv4/route.c | 26 +++++++++++--------------- net/ipv6/route.c | 19 ++++++------------- 5 files changed, 45 insertions(+), 39 deletions(-) (limited to 'net') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 33b3d0ab3a91..493297acdae8 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -585,6 +585,9 @@ extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, struct nlmsghdr *nlh, gfp_t flags); extern void rtnl_set_sk_err(u32 group, int error); extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); +extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, + u32 id, u32 ts, u32 tsage, long expires, + u32 error); extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 0cb4d9e53a07..e76539a5eb5e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -212,6 +212,26 @@ nla_put_failure: return nla_nest_cancel(skb, mx); } +int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, + u32 ts, u32 tsage, long expires, u32 error) +{ + struct rta_cacheinfo ci = { + .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), + .rta_used = dst->__use, + .rta_clntref = atomic_read(&(dst->__refcnt)), + .rta_error = error, + .rta_id = id, + .rta_ts = ts, + .rta_tsage = tsage, + }; + + if (expires) + ci.rta_expires = jiffies_to_clock_t(expires); + + return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); +} + +EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); static void set_operstate(struct net_device *dev, unsigned char transition) { diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 4eb985236aee..9881933167bd 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1469,7 +1469,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, struct rtmsg *r; struct nlmsghdr *nlh; unsigned char *b = skb->tail; - struct rta_cacheinfo ci; + long expires; nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); r = NLMSG_DATA(nlh); @@ -1502,16 +1502,10 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) goto rtattr_failure; - ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); - ci.rta_used = rt->u.dst.__use; - ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); - if (rt->u.dst.expires) - ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies); - else - ci.rta_expires = 0; - ci.rta_error = rt->u.dst.error; - ci.rta_id = ci.rta_ts = ci.rta_tsage = 0; - RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0; + if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, expires, + rt->u.dst.error) < 0) + goto rtattr_failure; if (rt->fl.iif) RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ee00b6506ab4..9f3924c4905e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2629,7 +2629,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, struct rtable *rt = (struct rtable*)skb->dst; struct rtmsg *r; struct nlmsghdr *nlh; - struct rta_cacheinfo ci; + long expires; + u32 id = 0, ts = 0, tsage = 0, error; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); if (nlh == NULL) @@ -2676,20 +2677,13 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) goto nla_put_failure; - ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); - ci.rta_used = rt->u.dst.__use; - ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); - if (rt->u.dst.expires) - ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies); - else - ci.rta_expires = 0; - ci.rta_error = rt->u.dst.error; - ci.rta_id = ci.rta_ts = ci.rta_tsage = 0; + error = rt->u.dst.error; + expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0; if (rt->peer) { - ci.rta_id = rt->peer->ip_id_count; + id = rt->peer->ip_id_count; if (rt->peer->tcp_ts_stamp) { - ci.rta_ts = rt->peer->tcp_ts; - ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; + ts = rt->peer->tcp_ts; + tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; } } @@ -2708,7 +2702,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, } else { if (err == -EMSGSIZE) goto nla_put_failure; - ci.rta_error = err; + error = err; } } } else @@ -2716,7 +2710,9 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif); } - NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + if (rtnl_put_cacheinfo(skb, &rt->u.dst, id, ts, tsage, + expires, error) < 0) + goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0bf17a3cf085..9f80518aacbd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2027,7 +2027,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, { struct rtmsg *rtm; struct nlmsghdr *nlh; - struct rta_cacheinfo ci; + long expires; u32 table; if (prefix) { /* user wants prefix routes only */ @@ -2101,18 +2101,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); - ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); - if (rt->rt6i_expires) - ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); - else - ci.rta_expires = 0; - ci.rta_used = rt->u.dst.__use; - ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); - ci.rta_error = rt->u.dst.error; - ci.rta_id = 0; - ci.rta_ts = 0; - ci.rta_tsage = 0; - NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + + expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0; + if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, + expires, rt->u.dst.error) < 0) + goto nla_put_failure; return nlmsg_end(skb, nlh); -- cgit v1.2.3-70-g09d2 From 4c0a6cb0db19de411c4bf7fcdc79d4c7c4ccafb1 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 09:29:59 -0800 Subject: [UDP(-Lite)]: consolidate v4 and v6 get|setsockopt code This patch consolidates set/getsockopt code between UDP(-Lite) v4 and 6. The justification is that UDP(-Lite) is a transport-layer protocol and therefore the socket option code (at least in theory) should be AF-independent. Furthermore, there is the following code reduplication: * do_udp{,v6}_getsockopt is 100% identical between v4 and v6 * do_udp{,v6}_setsockopt is identical up to the following differerence --v4 in contrast to v4 additionally allows the experimental encapsulation types UDP_ENCAP_ESPINUDP and UDP_ENCAP_ESPINUDP_NON_IKE --the remainder is identical between v4 and v6 I believe that this difference is of little relevance. The advantages in not duplicating twice almost completely identical code. The patch further simplifies the interface of udp{,v6}_push_pending_frames, since for the second argument (struct udp_sock *up) it always holds that up = udp_sk(sk); where sk is the first function argument. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- include/net/udp.h | 5 +++ net/ipv4/udp.c | 30 ++++++++------ net/ipv6/udp.c | 118 +++++------------------------------------------------- 3 files changed, 32 insertions(+), 121 deletions(-) (limited to 'net') diff --git a/include/net/udp.h b/include/net/udp.h index eac69ff0582c..1548d68d45da 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -134,6 +134,11 @@ extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int udp_disconnect(struct sock *sk, int flags); extern unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); +extern int udp_lib_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen, + int (*push_pending_frames)(struct sock *)); DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); /* diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1807a30694d9..035915fc9ed3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -448,8 +448,9 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, /* * Push out all pending data as one UDP datagram. Socket is locked. */ -static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) +static int udp_push_pending_frames(struct sock *sk) { + struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; struct sk_buff *skb; @@ -673,7 +674,7 @@ do_append_data: if (err) udp_flush_pending_frames(sk); else if (!corkreq) - err = udp_push_pending_frames(sk, up); + err = udp_push_pending_frames(sk); else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) up->pending = 0; release_sock(sk); @@ -746,7 +747,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, up->len += size; if (!(up->corkflag || (flags&MSG_MORE))) - ret = udp_push_pending_frames(sk, up); + ret = udp_push_pending_frames(sk); if (!ret) ret = size; out: @@ -1299,8 +1300,9 @@ int udp_destroy_sock(struct sock *sk) /* * Socket option code for UDP */ -static int do_udp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +int udp_lib_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen, + int (*push_pending_frames)(struct sock *)) { struct udp_sock *up = udp_sk(sk); int val; @@ -1319,7 +1321,7 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname, } else { up->corkflag = 0; lock_sock(sk); - udp_push_pending_frames(sk, up); + (*push_pending_frames)(sk); release_sock(sk); } break; @@ -1375,7 +1377,8 @@ int udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udp_setsockopt(sk, level, optname, optval, optlen); + return udp_lib_setsockopt(sk, level, optname, optval, optlen, + udp_push_pending_frames); return ip_setsockopt(sk, level, optname, optval, optlen); } @@ -1384,13 +1387,14 @@ int compat_udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udp_setsockopt(sk, level, optname, optval, optlen); + return udp_lib_setsockopt(sk, level, optname, optval, optlen, + udp_push_pending_frames); return compat_ip_setsockopt(sk, level, optname, optval, optlen); } #endif -static int do_udp_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +int udp_lib_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { struct udp_sock *up = udp_sk(sk); int val, len; @@ -1437,7 +1441,7 @@ int udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udp_getsockopt(sk, level, optname, optval, optlen); + return udp_lib_getsockopt(sk, level, optname, optval, optlen); return ip_getsockopt(sk, level, optname, optval, optlen); } @@ -1446,7 +1450,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udp_getsockopt(sk, level, optname, optval, optlen); + return udp_lib_getsockopt(sk, level, optname, optval, optlen); return compat_ip_getsockopt(sk, level, optname, optval, optlen); } #endif @@ -1716,6 +1720,8 @@ EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_get_port); EXPORT_SYMBOL(udp_prot); EXPORT_SYMBOL(udp_sendmsg); +EXPORT_SYMBOL(udp_lib_getsockopt); +EXPORT_SYMBOL(udp_lib_setsockopt); EXPORT_SYMBOL(udp_poll); #ifdef CONFIG_PROC_FS diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b3ea8af50a9b..f52a5c3cc0a3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -505,10 +505,11 @@ static void udp_v6_flush_pending_frames(struct sock *sk) * Sending */ -static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) +static int udp_v6_push_pending_frames(struct sock *sk) { struct sk_buff *skb; struct udphdr *uh; + struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; int err = 0; @@ -782,7 +783,7 @@ do_append_data: if (err) udp_v6_flush_pending_frames(sk); else if (!corkreq) - err = udp_v6_push_pending_frames(sk, up); + err = udp_v6_push_pending_frames(sk); else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) up->pending = 0; @@ -844,72 +845,12 @@ int udpv6_destroy_sock(struct sock *sk) /* * Socket option code for UDP */ -static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) -{ - struct udp_sock *up = udp_sk(sk); - int val; - int err = 0; - - if(optlencorkflag = 1; - } else { - up->corkflag = 0; - lock_sock(sk); - udp_v6_push_pending_frames(sk, up); - release_sock(sk); - } - break; - case UDP_ENCAP: - switch (val) { - case 0: - up->encap_type = val; - break; - default: - err = -ENOPROTOOPT; - break; - } - break; - - case UDPLITE_SEND_CSCOV: - if (!up->pcflag) /* Disable the option on UDP sockets */ - return -ENOPROTOOPT; - if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ - val = 8; - up->pcslen = val; - up->pcflag |= UDPLITE_SEND_CC; - break; - - case UDPLITE_RECV_CSCOV: - if (!up->pcflag) /* Disable the option on UDP sockets */ - return -ENOPROTOOPT; - if (val != 0 && val < 8) /* Avoid silly minimal values. */ - val = 8; - up->pcrlen = val; - up->pcflag |= UDPLITE_RECV_CC; - break; - - default: - err = -ENOPROTOOPT; - break; - }; - - return err; -} - int udpv6_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + return udp_lib_setsockopt(sk, level, optname, optval, optlen, + udp_v6_push_pending_frames); return ipv6_setsockopt(sk, level, optname, optval, optlen); } @@ -918,58 +859,17 @@ int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udpv6_setsockopt(sk, level, optname, optval, optlen); + return udp_lib_setsockopt(sk, level, optname, optval, optlen, + udp_v6_push_pending_frames); return compat_ipv6_setsockopt(sk, level, optname, optval, optlen); } #endif -static int do_udpv6_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) -{ - struct udp_sock *up = udp_sk(sk); - int val, len; - - if(get_user(len,optlen)) - return -EFAULT; - - len = min_t(unsigned int, len, sizeof(int)); - - if(len < 0) - return -EINVAL; - - switch(optname) { - case UDP_CORK: - val = up->corkflag; - break; - - case UDP_ENCAP: - val = up->encap_type; - break; - - case UDPLITE_SEND_CSCOV: - val = up->pcslen; - break; - - case UDPLITE_RECV_CSCOV: - val = up->pcrlen; - break; - - default: - return -ENOPROTOOPT; - }; - - if(put_user(len, optlen)) - return -EFAULT; - if(copy_to_user(optval, &val,len)) - return -EFAULT; - return 0; -} - int udpv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + return udp_lib_getsockopt(sk, level, optname, optval, optlen); return ipv6_getsockopt(sk, level, optname, optval, optlen); } @@ -978,7 +878,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) - return do_udpv6_getsockopt(sk, level, optname, optval, optlen); + return udp_lib_getsockopt(sk, level, optname, optval, optlen); return compat_ipv6_getsockopt(sk, level, optname, optval, optlen); } #endif -- cgit v1.2.3-70-g09d2 From 0c51f53c57c5584508dfae7110db5caccfd499c6 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 27 Nov 2006 12:58:20 -0800 Subject: [XFRM]: Make flush notifier prettier when subpolicy used Might as well make flush notifier prettier when subpolicy used Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 8dbb38b91de2..006c88c163e0 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2113,7 +2113,6 @@ static int xfrm_notify_policy_flush(struct km_event *c) unsigned char *b; int len = 0; #ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_userpolicy_type upt; len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); #endif len += NLMSG_LENGTH(0); @@ -2126,12 +2125,8 @@ static int xfrm_notify_policy_flush(struct km_event *c) nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0); nlh->nlmsg_flags = 0; - -#ifdef CONFIG_XFRM_SUB_POLICY - memset(&upt, 0, sizeof(upt)); - upt.type = c->data.type; - RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); -#endif + if (copy_to_user_policy_type(c->data.type, skb) < 0) + goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; @@ -2139,9 +2134,6 @@ static int xfrm_notify_policy_flush(struct km_event *c) return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); nlmsg_failure: -#ifdef CONFIG_XFRM_SUB_POLICY -rtattr_failure: -#endif kfree_skb(skb); return -1; } -- cgit v1.2.3-70-g09d2 From b798a9ede2b2434b9cbf0f3aee3e8598586fa89c Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 27 Nov 2006 12:59:30 -0800 Subject: [XFRM]: Convert a few __u8 to proper u8 Caught by the EyeBalls(tm) of Thomas Graf Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 006c88c163e0..6b461da0b51c 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -769,7 +769,7 @@ out_noput: return err; } -static int verify_policy_dir(__u8 dir) +static int verify_policy_dir(u8 dir) { switch (dir) { case XFRM_POLICY_IN: @@ -784,7 +784,7 @@ static int verify_policy_dir(__u8 dir) return 0; } -static int verify_policy_type(__u8 type) +static int verify_policy_type(u8 type) { switch (type) { case XFRM_POLICY_TYPE_MAIN: @@ -897,7 +897,7 @@ static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma) { struct rtattr *rt = xfrma[XFRMA_POLICY_TYPE-1]; struct xfrm_userpolicy_type *upt; - __u8 type = XFRM_POLICY_TYPE_MAIN; + u8 type = XFRM_POLICY_TYPE_MAIN; int err; if (rt) { @@ -1079,7 +1079,7 @@ static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *s } #ifdef CONFIG_XFRM_SUB_POLICY -static int copy_to_user_policy_type(__u8 type, struct sk_buff *skb) +static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) { struct xfrm_userpolicy_type upt; @@ -1095,7 +1095,7 @@ rtattr_failure: } #else -static inline int copy_to_user_policy_type(__u8 type, struct sk_buff *skb) +static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb) { return 0; } @@ -1185,7 +1185,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr { struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; - __u8 type = XFRM_POLICY_TYPE_MAIN; + u8 type = XFRM_POLICY_TYPE_MAIN; int err; struct km_event c; int delete; @@ -1403,7 +1403,7 @@ out: static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct km_event c; - __u8 type = XFRM_POLICY_TYPE_MAIN; + u8 type = XFRM_POLICY_TYPE_MAIN; int err; err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); @@ -1424,7 +1424,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * struct xfrm_policy *xp; struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); struct xfrm_userpolicy_info *p = &up->pol; - __u8 type = XFRM_POLICY_TYPE_MAIN; + u8 type = XFRM_POLICY_TYPE_MAIN; int err = -ENOENT; err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); -- cgit v1.2.3-70-g09d2 From 48e03eee715b9e19df03153f2bcce6413632afcb Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:29:27 -0200 Subject: [DCCP] ccid3: Consolidate timer resets This patch concerns updating the value of the nofeedback timer when no feedback has been received so far. Since in this case the value of R is still undefined according to [RFC 3448, 4.2], we can not perform step (3) of [RFC 3448, 4.3]. A clarification is provided in [RFC 4342, sec. 5], which states that in these cases the nofeedback timer (still) expires "after two seconds". Many thanks to Ian McDonald for pointing this out and providing the clarification. The patch * implements [RFC 4342, sec. 5] with regard to the above case * consolidates handling timer restart by - adding an appropriate jump label and - initialising the timeout value Acked-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 18 +++++++++--------- net/dccp/ccids/ccid3.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 6777a7f33a9a..9297fca78683 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -154,16 +154,14 @@ static void ccid3_hc_tx_update_x(struct sock *sk) static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; - unsigned long next_tmout = 0; struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + unsigned long next_tmout = USEC_PER_SEC / 5; bh_lock_sock(sk); if (sock_owned_by_user(sk)) { /* Try again later. */ /* XXX: set some sensible MIB */ - sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + HZ / 5); - goto out; + goto restart_timer; } ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, @@ -183,9 +181,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) dccp_role(sk), sk, ccid3_tx_state_name(hctx->ccid3hctx_state), hctx->ccid3hctx_x); - next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x), - TFRC_INITIAL_TIMEOUT); + /* The value of R is still undefined and so we can not recompute + * the timout value. Keep initial value as per [RFC 4342, 5]. */ + next_tmout = TFRC_INITIAL_TIMEOUT; /* * FIXME - not sure above calculation is correct. See section * 5 of CCID3 11 should adjust tx_t_ipi and double that to @@ -239,9 +237,11 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) goto out; } - sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); hctx->ccid3hctx_idle = 1; + +restart_timer: + sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, + jiffies + usecs_to_jiffies(next_tmout)); out: bh_unlock_sock(sk); sock_put(sk); diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 462165234ff6..970921700ce3 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -46,7 +46,7 @@ #define TFRC_STD_PACKET_SIZE 256 #define TFRC_MAX_PACKET_SIZE 65535 -/* Two seconds as per CCID3 spec */ +/* Two seconds as per RFC 3448 4.2 */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ -- cgit v1.2.3-70-g09d2 From 17893bc1a632e195574dc0dd9751243f0d5993d2 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:31:33 -0200 Subject: [DCCP] ccid3: Consistently update t_nom, t_ipi, t_delta This patch: * consolidates updating of parameters (t_nom, t_ipi, t_delta) which need to be updated at the same time, since they are inter-dependent * removes two inline functions which are no longer needed as a result of the above consolidation * resolves a FIXME regarding the re-calculation of t_ipi within the nofeedback timer, in the state where no feedback has previously been received * ties updating these parameters to updating the sending rate X, exploiting that all three parameters in turn depend on X; and using a small optimisation which can reduce the number of required instructions: only update the three parameters when X really changes Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 9297fca78683..4342caf53251 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -100,19 +100,24 @@ static void ccid3_hc_tx_set_state(struct sock *sk, hctx->ccid3hctx_state = state; } -/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ -static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) +/* + * Recalculate scheduled nominal send time t_nom, inter-packet interval + * t_ipi, and delta value. Should be called after each change to X. + */ +static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) { + timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); + + /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); -} -/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ -static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) -{ + /* Update nominal send time with regard to the new t_ipi */ + timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); + + /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN); } - /* * Update X by * If (p > 0) @@ -126,6 +131,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) static void ccid3_hc_tx_update_x(struct sock *sk) { struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + const __u32 old_x = hctx->ccid3hctx_x; /* To avoid large error in calcX */ if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { @@ -149,6 +155,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk) hctx->ccid3hctx_t_ld = now; } } + if (hctx->ccid3hctx_x != old_x) + ccid3_update_send_time(hctx); } static void ccid3_hc_tx_no_feedback_timer(unsigned long data) @@ -184,11 +192,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) /* The value of R is still undefined and so we can not recompute * the timout value. Keep initial value as per [RFC 4342, 5]. */ next_tmout = TFRC_INITIAL_TIMEOUT; - /* - * FIXME - not sure above calculation is correct. See section - * 5 of CCID3 11 should adjust tx_t_ipi and double that to - * achieve it really - */ + ccid3_update_send_time(hctx); break; case TFRC_SSTATE_FBACK: /* @@ -479,17 +483,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); - /* Update sending rate */ + /* Update sending rate (and likely t_ipi, t_nom, and delta) */ ccid3_hc_tx_update_x(sk); - /* Update next send time */ - timeval_sub_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_t_ipi(hctx); - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_delta(hctx); - /* remove all packets older than the one acked from history */ dccp_tx_hist_purge_older(ccid3_tx_hist, &hctx->ccid3hctx_hist, packet); -- cgit v1.2.3-70-g09d2 From 5d0dbc4a9b2d325458dcbf9a8329bd1d2cc7bd7e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:32:37 -0200 Subject: [DCCP] ccid3: Consolidate handling of t_RTO This patch * removes setting t_RTO in ccid3_hc_tx_init (per [RFC 3448, 4.2], t_RTO is undefined until feedback has been received); * makes some trivial changes (updates of comments); * performs a small optimisation by exploiting that the feedback timeout uses the value of t_ipi. The way it is done is safe, because the timeouts appear after the changes to t_ipi, ensuring that up-to-date values are used; * in ccid3_hc_tx_packet_recv, moves the t_rto statement closer to the calculation of the next_tmout. This makes the code clearer to read and is also safe, since t_rto is not updated until the next call of ccid3_hc_tx_packet_recv, and is not read by the functions called via ccid_wait_for_ccid(); * removes a `max' statement in sk_reset_timer, this is not needed since the timeout value is always greater than 1E6 microseconds. * adds `XXX'es to highlight that currently the nofeedback timer is set in a non-standard way Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 4342caf53251..f0ed67c84a55 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -228,11 +228,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) } /* * Schedule no feedback timer to expire in - * max(4 * R, 2 * s / X) + * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) + * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R */ - next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, - 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x)); + next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); break; case TFRC_SSTATE_NO_SENT: DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); @@ -460,10 +459,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) "r_sample=%us\n", dccp_role(sk), sk, hctx->ccid3hctx_rtt, r_sample); - /* Update timeout interval */ - hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, - USEC_PER_SEC); - /* Update receive rate */ hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ @@ -491,17 +486,22 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) &hctx->ccid3hctx_hist, packet); /* * As we have calculated new ipi, delta, t_nom it is possible that - * we now can send a packet, so wake up dccp_wait_for_ccids. + * we now can send a packet, so wake up dccp_wait_for_ccid */ sk->sk_write_space(sk); + + /* Update timeout interval. We use the alternative variant of + * [RFC 3448, 3.1] which sets the upper bound of t_rto to one + * second, as it is suggested for TCP (see RFC 2988, 2.4). */ + hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, + USEC_PER_SEC ); /* * Schedule no feedback timer to expire in - * max(4 * R, 2 * s / X) + * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) + * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R */ - next_tmout = max(hctx->ccid3hctx_t_rto, - 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x)); + next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " "expire in %lu jiffies (%luus)\n", @@ -509,7 +509,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) usecs_to_jiffies(next_tmout), next_tmout); sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); + jiffies + usecs_to_jiffies(next_tmout)); /* set idle flag */ hctx->ccid3hctx_idle = 1; @@ -607,7 +607,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) /* Set transmission rate to 1 packet per second */ hctx->ccid3hctx_x = hctx->ccid3hctx_s; - hctx->ccid3hctx_t_rto = USEC_PER_SEC; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); -- cgit v1.2.3-70-g09d2 From 4384260443efe90a2ec0d907568dbc58ae792cd0 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 18:14:10 -0200 Subject: [DCCP]: Remove allocation of sysctl numbers This is in response to a request sent earlier by Eric W. Biederman and replaces all sysctl numbers for net.dccp.default with CTL_UNNUMBERED. It has been tested to compile and to work. Commiter note: I've removed the use of CTL_UNNUMBERED, not setting .ctl_name sets it to 0, that is the what CTL_UNNUMBERED is, reason is to avoid unneeded source code cluttering. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/sysctl.h | 14 -------------- net/dccp/sysctl.c | 10 ---------- 2 files changed, 24 deletions(-) (limited to 'net') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 61dd99c6c2a5..94316a98e0d0 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -606,20 +606,6 @@ enum { NET_DCCP_DEFAULT=1, }; -/* /proc/sys/net/dccp/default */ -enum { - NET_DCCP_DEFAULT_SEQ_WINDOW = 1, - NET_DCCP_DEFAULT_RX_CCID = 2, - NET_DCCP_DEFAULT_TX_CCID = 3, - NET_DCCP_DEFAULT_ACK_RATIO = 4, - NET_DCCP_DEFAULT_SEND_ACKVEC = 5, - NET_DCCP_DEFAULT_SEND_NDP = 6, - NET_DCCP_DEFAULT_REQ_RETRIES = 7, - NET_DCCP_DEFAULT_RETRIES1 = 8, - NET_DCCP_DEFAULT_RETRIES2 = 9, - NET_DCCP_DEFAULT_TX_QLEN = 10, -}; - /* /proc/sys/net/ipx */ enum { NET_IPX_PPROP_BROADCASTING=1, diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 4775ba3faa04..fdcfca3e9208 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -20,7 +20,6 @@ static struct ctl_table dccp_default_table[] = { { - .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW, .procname = "seq_window", .data = &sysctl_dccp_feat_sequence_window, .maxlen = sizeof(sysctl_dccp_feat_sequence_window), @@ -28,7 +27,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_RX_CCID, .procname = "rx_ccid", .data = &sysctl_dccp_feat_rx_ccid, .maxlen = sizeof(sysctl_dccp_feat_rx_ccid), @@ -36,7 +34,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_TX_CCID, .procname = "tx_ccid", .data = &sysctl_dccp_feat_tx_ccid, .maxlen = sizeof(sysctl_dccp_feat_tx_ccid), @@ -44,7 +41,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_ACK_RATIO, .procname = "ack_ratio", .data = &sysctl_dccp_feat_ack_ratio, .maxlen = sizeof(sysctl_dccp_feat_ack_ratio), @@ -52,7 +48,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_SEND_ACKVEC, .procname = "send_ackvec", .data = &sysctl_dccp_feat_send_ack_vector, .maxlen = sizeof(sysctl_dccp_feat_send_ack_vector), @@ -60,7 +55,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_SEND_NDP, .procname = "send_ndp", .data = &sysctl_dccp_feat_send_ndp_count, .maxlen = sizeof(sysctl_dccp_feat_send_ndp_count), @@ -68,7 +62,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_REQ_RETRIES, .procname = "request_retries", .data = &sysctl_dccp_request_retries, .maxlen = sizeof(sysctl_dccp_request_retries), @@ -76,7 +69,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_RETRIES1, .procname = "retries1", .data = &sysctl_dccp_retries1, .maxlen = sizeof(sysctl_dccp_retries1), @@ -84,7 +76,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_RETRIES2, .procname = "retries2", .data = &sysctl_dccp_retries2, .maxlen = sizeof(sysctl_dccp_retries2), @@ -92,7 +83,6 @@ static struct ctl_table dccp_default_table[] = { .proc_handler = proc_dointvec, }, { - .ctl_name = NET_DCCP_DEFAULT_TX_QLEN, .procname = "tx_qlen", .data = &sysctl_dccp_tx_qlen, .maxlen = sizeof(sysctl_dccp_tx_qlen), -- cgit v1.2.3-70-g09d2 From 2a1fda6f6c01d7ac195c040f14edcf9f64a5451e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 18:34:34 -0200 Subject: [DCCP] ccid3: Set NoFeedback Timeout according to RFC 3448 This corrects the setting of the nofeedback timer with regard to RFC 3448 - previously it was not set to max(4*R, 2*s/X) as specified. Using the maximum of 1 second as upper bound (as it was done before) can have detrimental effects, especially if R is small. Signed-off-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index f0ed67c84a55..577fd0ef84e5 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -163,7 +163,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); - unsigned long next_tmout = USEC_PER_SEC / 5; + unsigned long t_nfb = USEC_PER_SEC / 5; bh_lock_sock(sk); if (sock_owned_by_user(sk)) { @@ -191,7 +191,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) hctx->ccid3hctx_x); /* The value of R is still undefined and so we can not recompute * the timout value. Keep initial value as per [RFC 4342, 5]. */ - next_tmout = TFRC_INITIAL_TIMEOUT; + t_nfb = TFRC_INITIAL_TIMEOUT; ccid3_update_send_time(hctx); break; case TFRC_SSTATE_FBACK: @@ -228,10 +228,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) } /* * Schedule no feedback timer to expire in - * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) - * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R + * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) */ - next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); + t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); break; case TFRC_SSTATE_NO_SENT: DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); @@ -244,7 +243,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) restart_timer: sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + usecs_to_jiffies(next_tmout)); + jiffies + usecs_to_jiffies(t_nfb)); out: bh_unlock_sock(sk); sock_put(sk); @@ -396,7 +395,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) struct ccid3_options_received *opt_recv; struct dccp_tx_hist_entry *packet; struct timeval now; - unsigned long next_tmout; + unsigned long t_nfb; u32 t_elapsed; u32 pinv; u32 x_recv; @@ -498,18 +497,17 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) USEC_PER_SEC ); /* * Schedule no feedback timer to expire in - * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) - * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R + * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) */ - next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); + t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " "expire in %lu jiffies (%luus)\n", dccp_role(sk), sk, - usecs_to_jiffies(next_tmout), next_tmout); + usecs_to_jiffies(t_nfb), t_nfb); sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + usecs_to_jiffies(next_tmout)); + jiffies + usecs_to_jiffies(t_nfb)); /* set idle flag */ hctx->ccid3hctx_idle = 1; -- cgit v1.2.3-70-g09d2 From 78ad713da673a2977763521c347176137f3e493f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:22:33 -0200 Subject: [DCCP] ccid3: Track RX/TX packet size `s' using moving-average Problem: --- net/dccp/ccids/ccid3.c | 60 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 577fd0ef84e5..05513f3df652 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -159,6 +159,25 @@ static void ccid3_hc_tx_update_x(struct sock *sk) ccid3_update_send_time(hctx); } +/* + * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) + * @len: DCCP packet payload size in bytes + */ +static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) +{ + if (unlikely(len == 0)) + ccid3_pr_debug("Packet payload length is 0 - not updating\n"); + else + hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len : + (9 * hctx->ccid3hctx_s + len) / 10; + /* + * Note: We could do a potential optimisation here - when `s' changes, + * recalculate sending rate and consequently t_ipi, t_delta, and + * t_now. This is however non-standard, and the benefits are not + * clear, so it is currently left out. + */ +} + static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; @@ -299,6 +318,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, hctx->ccid3hctx_t_last_win_count = now; ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); + /* Set initial sending rate to 1 packet per second */ + ccid3_hc_tx_update_s(hctx, len); + hctx->ccid3hctx_x = hctx->ccid3hctx_s; + /* First timeout, according to [RFC 3448, 4.2], is 1 second */ hctx->ccid3hctx_t_ipi = USEC_PER_SEC; /* Initial delta: minimum of 0.5 sec and t_gran/2 */ @@ -350,6 +373,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) unsigned long quarter_rtt; struct dccp_tx_hist_entry *packet; + ccid3_hc_tx_update_s(hctx, len); + packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); if (unlikely(packet == NULL)) { DCCP_WARN("packet doesn't exist in history!\n"); @@ -594,17 +619,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && - dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) - hctx->ccid3hctx_s = dp->dccps_packet_size; - else - hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE; - - /* Set transmission rate to 1 packet per second */ - hctx->ccid3hctx_x = hctx->ccid3hctx_s; + hctx->ccid3hctx_s = 0; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); @@ -658,6 +675,15 @@ static void ccid3_hc_rx_set_state(struct sock *sk, hcrx->ccid3hcrx_state = state; } +static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len) +{ + if (unlikely(len == 0)) /* don't update on empty packets (e.g. ACKs) */ + ccid3_pr_debug("Packet payload length is 0 - not updating\n"); + else + hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len : + (9 * hcrx->ccid3hcrx_s + len) / 10; +} + static void ccid3_hc_rx_send_feedback(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); @@ -934,7 +960,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) struct dccp_rx_hist_entry *packet; struct timeval now; u32 p_prev, rtt_prev, r_sample, t_elapsed; - int loss; + int loss, payload_size; BUG_ON(hcrx == NULL); @@ -989,6 +1015,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) return; + payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4; + ccid3_hc_rx_update_s(hcrx, payload_size); + switch (hcrx->ccid3hcrx_state) { case TFRC_RSTATE_NO_DATA: ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " @@ -999,8 +1028,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); return; case TFRC_RSTATE_DATA: - hcrx->ccid3hcrx_bytes_recv += skb->len - - dccp_hdr(skb)->dccph_doff * 4; + hcrx->ccid3hcrx_bytes_recv += payload_size; if (loss) break; @@ -1040,22 +1068,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && - dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) - hcrx->ccid3hcrx_s = dp->dccps_packet_size; - else - hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE; - hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; + hcrx->ccid3hcrx_s = 0; hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ return 0; } -- cgit v1.2.3-70-g09d2 From 5aed324369c94a2c38469c8288e42eb1a9fac400 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:33:36 -0200 Subject: [DCCP]: Tidy up unused structures This removes and cleans up unused variables and structures which have become unnecessary following the introduction of the EWMA patch to automatically track the CCID 3 receiver/sender packet sizes `s'. It deprecates the PACKET_SIZE socket option by returning an error code and printing a deprecation warning if an application tries to read or write this socket option. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 4 +--- net/dccp/ccids/ccid3.h | 4 ---- net/dccp/proto.c | 8 ++++---- 3 files changed, 5 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 72cc355d7a03..ed6cc8962d87 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -200,7 +200,7 @@ struct dccp_so_feat { }; /* DCCP socket options */ -#define DCCP_SOCKOPT_PACKET_SIZE 1 +#define DCCP_SOCKOPT_PACKET_SIZE 1 /* XXX deprecated, without effect */ #define DCCP_SOCKOPT_SERVICE 2 #define DCCP_SOCKOPT_CHANGE_L 3 #define DCCP_SOCKOPT_CHANGE_R 4 @@ -460,7 +460,6 @@ struct dccp_ackvec; * @dccps_service_list - second .. last service code on passive socket * @dccps_timestamp_time - time of latest TIMESTAMP option * @dccps_timestamp_echo - latest timestamp received on a TIMESTAMP option - * @dccps_packet_size - Set thru setsockopt * @dccps_l_ack_ratio - * @dccps_r_ack_ratio - * @dccps_pcslen - sender partial checksum coverage (via sockopt) @@ -495,7 +494,6 @@ struct dccp_sock { struct dccp_service_list *dccps_service_list; struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; - __u32 dccps_packet_size; __u16 dccps_l_ack_ratio; __u16 dccps_r_ack_ratio; __u16 dccps_pcslen; diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 970921700ce3..dbb884426dfa 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -42,10 +42,6 @@ #include #include "../ccid.h" -#define TFRC_MIN_PACKET_SIZE 16 -#define TFRC_STD_PACKET_SIZE 256 -#define TFRC_MAX_PACKET_SIZE 65535 - /* Two seconds as per RFC 3448 4.2 */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 3c44d502e5c1..2604e34d8f38 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -470,7 +470,8 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, lock_sock(sk); switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: - dp->dccps_packet_size = val; + DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n"); + err = -EINVAL; break; case DCCP_SOCKOPT_CHANGE_L: if (optlen != sizeof(struct dccp_so_feat)) @@ -581,9 +582,8 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: - val = dp->dccps_packet_size; - len = sizeof(dp->dccps_packet_size); - break; + DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n"); + return -EINVAL; case DCCP_SOCKOPT_SERVICE: return dccp_getsockopt_service(sk, len, (__be32 __user *)optval, optlen); -- cgit v1.2.3-70-g09d2 From 841bac1d607d8bf2e068e4b24393fb77372814e3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 28 Nov 2006 19:42:03 -0200 Subject: [DCCP]: Make {set,get}sockopt(DCCP_SOCKOPT_PACKET_SIZE) return 0 To reflect the fact that this now is of no effect, not making apps stop working, just be warned in the system log. Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/proto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 2604e34d8f38..5ec47d9ee447 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -471,7 +471,7 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n"); - err = -EINVAL; + err = 0; break; case DCCP_SOCKOPT_CHANGE_L: if (optlen != sizeof(struct dccp_so_feat)) @@ -583,7 +583,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n"); - return -EINVAL; + return 0; case DCCP_SOCKOPT_SERVICE: return dccp_getsockopt_service(sk, len, (__be32 __user *)optval, optlen); -- cgit v1.2.3-70-g09d2 From a79ef76f4d8424324c2f108824a7398571193f43 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:51:42 -0200 Subject: [DCCP] ccid3: Larger initial windows This implements the larger-initial-windows feature for CCID 3, as described in section 5 of RFC 4342. When the first feedback packet arrives, the sender can send up to 2..4 packets per RTT, instead of just one. The patch further * reduces the number of timestamping calls by passing the timestamp value (which is computed in one of the calling functions anyway) as argument * renames one constant with a very long name into one which is shorter and resembles the one in RFC 3448 (t_mbi) * simplifies some of the min_t/max_t cases where both `x', `y' have the same type Commiter note: renamed TFRC_t_mbi to TFRC_T_MBI, to follow Linux coding style. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 66 ++++++++++++++++++++++++++------------------------ net/dccp/ccids/ccid3.h | 4 +-- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 05513f3df652..aa5440ee20ae 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -128,7 +128,8 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) * X = max(min(2 * X, 2 * X_recv), s / R); * tld = now; */ -static void ccid3_hc_tx_update_x(struct sock *sk) +static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) + { struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); const __u32 old_x = hctx->ccid3hctx_x; @@ -138,23 +139,20 @@ static void ccid3_hc_tx_update_x(struct sock *sk) hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt, hctx->ccid3hctx_p); - hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc, - 2 * hctx->ccid3hctx_x_recv), - (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME)); - } else { - struct timeval now; + hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc, + hctx->ccid3hctx_x_recv * 2), + hctx->ccid3hctx_s / TFRC_T_MBI); + + } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >= + hctx->ccid3hctx_rtt) { + hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv, + hctx->ccid3hctx_x ) * 2, + usecs_div(hctx->ccid3hctx_s, + hctx->ccid3hctx_rtt) ); + hctx->ccid3hctx_t_ld = *now; + } else + ccid3_pr_debug("Not changing X\n"); - dccp_timestamp(sk, &now); - if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= - hctx->ccid3hctx_rtt) { - hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, - hctx->ccid3hctx_x) * 2, - usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_rtt)); - hctx->ccid3hctx_t_ld = now; - } - } if (hctx->ccid3hctx_x != old_x) ccid3_update_send_time(hctx); } @@ -196,12 +194,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_FBACK: - /* Halve send rate */ - hctx->ccid3hctx_x /= 2; - if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME)) - hctx->ccid3hctx_x = (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME); + /* RFC 3448, 4.4: Halve send rate directly */ + hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2, + hctx->ccid3hctx_s / TFRC_T_MBI); ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d " "bytes/s\n", @@ -221,6 +216,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) if (!hctx->ccid3hctx_idle || (hctx->ccid3hctx_x_recv >= 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { + struct timeval now; + ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", dccp_role(sk), sk, ccid3_tx_state_name(hctx->ccid3hctx_state)); @@ -238,12 +235,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, - hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME)); + hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); else hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; /* Update sending rate */ - ccid3_hc_tx_update_x(sk); + dccp_timestamp(sk, &now); + ccid3_hc_tx_update_x(sk, &now); } /* * Schedule no feedback timer to expire in @@ -473,11 +471,21 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) * q is a constant, RFC 3448 recomments 0.9 */ if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { + /* Use Larger Initial Windows [RFC 4342, sec. 5] + * We deviate in that we use `s' instead of `MSS'. */ + u16 w_init = max( 4 * hctx->ccid3hctx_s, + max(2 * hctx->ccid3hctx_s, 4380)); + hctx->ccid3hctx_rtt = r_sample; + hctx->ccid3hctx_x = usecs_div(w_init, r_sample); + hctx->ccid3hctx_t_ld = now; + + ccid3_update_send_time(hctx); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); - hctx->ccid3hctx_rtt = r_sample; - } else + } else { hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + r_sample / 10; + ccid3_hc_tx_update_x(sk, &now); + } ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " "r_sample=%us\n", dccp_role(sk), sk, @@ -502,9 +510,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); - /* Update sending rate (and likely t_ipi, t_nom, and delta) */ - ccid3_hc_tx_update_x(sk); - /* remove all packets older than the one acked from history */ dccp_tx_hist_purge_older(ccid3_tx_hist, &hctx->ccid3hctx_hist, packet); @@ -514,7 +519,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) */ sk->sk_write_space(sk); - /* Update timeout interval. We use the alternative variant of * [RFC 3448, 3.1] which sets the upper bound of t_rto to one * second, as it is suggested for TCP (see RFC 2988, 2.4). */ diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index dbb884426dfa..27cb20ae1da8 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -48,8 +48,8 @@ /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ #define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) -/* In seconds */ -#define TFRC_MAX_BACK_OFF_TIME 64 +/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ +#define TFRC_T_MBI 64 #define TFRC_SMALLEST_P 40 -- cgit v1.2.3-70-g09d2 From 6b57c93dc3aa0115b589cb89ef862d46ab9bd95e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:55:06 -0200 Subject: [DCCP]: Use `unsigned' for packet lengths This patch implements a suggestion by Ian McDonald and 1) Avoids tests against negative packet lengths by using unsigned int for packet payload lengths in the CCID send_packet()/packet_sent() routines 2) As a consequence, it removes an now unnecessary test with regard to `len > 0' in ccid3_hc_tx_packet_sent: that condition is always true, since * negative packet lengths are avoided * ccid3_hc_tx_send_packet flags an error whenever the payload length is 0. As a consequence, ccid3_hc_tx_packet_sent is never called as all errors returned by ccid_hc_tx_send_packet are caught in dccp_write_xmit 3) Removes the third argument of ccid_hc_tx_send_packet (the `len' parameter), since it is currently always set to skb->len. The code is updated with regard to this parameter change. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccid.h | 12 ++++---- net/dccp/ccids/ccid2.c | 5 ++- net/dccp/ccids/ccid3.c | 83 +++++++++++++++++++++++--------------------------- net/dccp/output.c | 6 ++-- 4 files changed, 48 insertions(+), 58 deletions(-) (limited to 'net') diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index f7eb6c613414..c7c29514dce8 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -52,9 +52,9 @@ struct ccid_operations { unsigned char len, u16 idx, unsigned char* value); int (*ccid_hc_tx_send_packet)(struct sock *sk, - struct sk_buff *skb, int len); - void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, - int len); + struct sk_buff *skb); + void (*ccid_hc_tx_packet_sent)(struct sock *sk, + int more, unsigned int len); void (*ccid_hc_rx_get_info)(struct sock *sk, struct tcp_info *info); void (*ccid_hc_tx_get_info)(struct sock *sk, @@ -94,16 +94,16 @@ extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk); extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk); static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, - struct sk_buff *skb, int len) + struct sk_buff *skb) { int rc = 0; if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL) - rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len); + rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb); return rc; } static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk, - int more, int len) + int more, unsigned int len) { if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL) ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len); diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 207f7f9b36ca..2555be8f4790 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -125,8 +125,7 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, return 0; } -static int ccid2_hc_tx_send_packet(struct sock *sk, - struct sk_buff *skb, int len) +static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) { struct ccid2_hc_tx_sock *hctx; @@ -268,7 +267,7 @@ static void ccid2_start_rto_timer(struct sock *sk) jiffies + hctx->ccid2hctx_rto); } -static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) +static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index aa5440ee20ae..70ebe705eb75 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -272,8 +272,7 @@ out: * = 0: can send immediately * < 0: error condition; do not send packet */ -static int ccid3_hc_tx_send_packet(struct sock *sk, - struct sk_buff *skb, int len) +static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); @@ -288,7 +287,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * zero-sized Data(Ack)s is theoretically possible, but for congestion * control this case is pathological - ignore it. */ - if (unlikely(len == 0)) + if (unlikely(skb->len == 0)) return -EBADMSG; /* See if last packet allocated was not sent */ @@ -317,7 +316,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); /* Set initial sending rate to 1 packet per second */ - ccid3_hc_tx_update_s(hctx, len); + ccid3_hc_tx_update_s(hctx, skb->len); hctx->ccid3hctx_x = hctx->ccid3hctx_s; /* First timeout, according to [RFC 3448, 4.2], is 1 second */ @@ -356,59 +355,53 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, return 0; } -static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) +static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) { const struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct timeval now; + unsigned long quarter_rtt; + struct dccp_tx_hist_entry *packet; BUG_ON(hctx == NULL); dccp_timestamp(sk, &now); - /* check if we have sent a data packet */ - if (len > 0) { - unsigned long quarter_rtt; - struct dccp_tx_hist_entry *packet; + ccid3_hc_tx_update_s(hctx, len); - ccid3_hc_tx_update_s(hctx, len); + packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); + if (unlikely(packet == NULL)) { + DCCP_WARN("packet doesn't exist in history!\n"); + return; + } + if (unlikely(packet->dccphtx_sent)) { + DCCP_WARN("no unsent packet in history!\n"); + return; + } + packet->dccphtx_tstamp = now; + packet->dccphtx_seqno = dp->dccps_gss; + /* + * Check if win_count have changed + * Algorithm in "8.1. Window Counter Value" in RFC 4342. + */ + quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); + if (likely(hctx->ccid3hctx_rtt > 8)) + quarter_rtt /= hctx->ccid3hctx_rtt / 4; - packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); - if (unlikely(packet == NULL)) { - DCCP_WARN("packet doesn't exist in history!\n"); - return; - } - if (unlikely(packet->dccphtx_sent)) { - DCCP_WARN("no unsent packet in history!\n"); - return; - } - packet->dccphtx_tstamp = now; - packet->dccphtx_seqno = dp->dccps_gss; - /* - * Check if win_count have changed - * Algorithm in "8.1. Window Counter Value" in RFC 4342. - */ - quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); - if (likely(hctx->ccid3hctx_rtt > 8)) - quarter_rtt /= hctx->ccid3hctx_rtt / 4; - - if (quarter_rtt > 0) { - hctx->ccid3hctx_t_last_win_count = now; - hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + - min_t(unsigned long, quarter_rtt, 5)) % 16; - ccid3_pr_debug("%s, sk=%p, window changed from " - "%u to %u!\n", - dccp_role(sk), sk, - packet->dccphtx_ccval, - hctx->ccid3hctx_last_win_count); - } + if (quarter_rtt > 0) { + hctx->ccid3hctx_t_last_win_count = now; + hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + + min_t(unsigned long, quarter_rtt, 5)) % 16; + ccid3_pr_debug("%s, sk=%p, window changed from " + "%u to %u!\n", + dccp_role(sk), sk, + packet->dccphtx_ccval, + hctx->ccid3hctx_last_win_count); + } - hctx->ccid3hctx_idle = 0; - packet->dccphtx_rtt = hctx->ccid3hctx_rtt; - packet->dccphtx_sent = 1; - } else - ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", - dccp_role(sk), sk, dp->dccps_gss); + hctx->ccid3hctx_idle = 0; + packet->dccphtx_rtt = hctx->ccid3hctx_rtt; + packet->dccphtx_sent = 1; } static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) diff --git a/net/dccp/output.c b/net/dccp/output.c index bfd9c5757897..400c30b6fcae 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -195,8 +195,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, if (signal_pending(current)) goto do_interrupted; - rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, - skb->len); + rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); if (rc <= 0) break; delay = msecs_to_jiffies(rc); @@ -245,8 +244,7 @@ void dccp_write_xmit(struct sock *sk, int block) this we have other issues */ while ((skb = skb_peek(&sk->sk_write_queue))) { - int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, - skb->len); + int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); if (err > 0) { if (!block) { -- cgit v1.2.3-70-g09d2 From d2e4bdc8704b0e711c5046a430bfd1681b0bd5a9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 28 Nov 2006 14:37:38 -0800 Subject: [TCP] Vegas: Increase default alpha to 2 and beta to 4. This helps Vegas cope better with delayed ACKs, see analysis at: http://www.cs.caltech.edu/%7Eweixl/technical/ns2linux/known_linux/index.html#vegas Signed-off-by: David S. Miller --- net/ipv4/tcp_vegas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index a3b7aa015a2f..ddc4bcc5785e 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c @@ -42,8 +42,8 @@ * with V_PARAM_SHIFT bits to the right of the binary point. */ #define V_PARAM_SHIFT 1 -static int alpha = 1< Date: Wed, 29 Nov 2006 02:34:58 +0100 Subject: [NETFILTER]: nf_conntrack: split out expectation handling This patch splits out expectation handling into its own file nf_conntrack_expect.c Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack.h | 49 +--- include/net/netfilter/nf_conntrack_core.h | 7 + include/net/netfilter/nf_conntrack_expect.h | 72 ++++++ include/net/netfilter/nf_conntrack_helper.h | 10 - net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_core.c | 265 +------------------- net/netfilter/nf_conntrack_expect.c | 365 ++++++++++++++++++++++++++++ net/netfilter/nf_conntrack_ftp.c | 1 + net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nf_conntrack_standalone.c | 81 +----- 10 files changed, 452 insertions(+), 401 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_expect.h create mode 100644 net/netfilter/nf_conntrack_expect.c (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 1fbd8193d5f1..9d2581fc04be 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -124,44 +124,6 @@ struct nf_conn char data[0]; }; -struct nf_conntrack_expect -{ - /* Internal linked list (global expectation list) */ - struct list_head list; - - /* We expect this tuple, with the following mask */ - struct nf_conntrack_tuple tuple, mask; - - /* Function to call after setup and insertion */ - void (*expectfn)(struct nf_conn *new, - struct nf_conntrack_expect *this); - - /* The conntrack of the master connection */ - struct nf_conn *master; - - /* Timer function; deletes the expectation. */ - struct timer_list timeout; - - /* Usage count. */ - atomic_t use; - - /* Unique ID */ - unsigned int id; - - /* Flags */ - unsigned int flags; - -#ifdef CONFIG_NF_NAT_NEEDED - /* This is the original per-proto part, used to map the - * expected connection the way the recipient expects. */ - union nf_conntrack_manip_proto saved_proto; - /* Direction relative to the master connection. */ - enum ip_conntrack_dir dir; -#endif -}; - -#define NF_CT_EXPECT_PERMANENT 0x1 - static inline struct nf_conn * nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash) { @@ -208,16 +170,6 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, extern void nf_conntrack_hash_insert(struct nf_conn *ct); -extern struct nf_conntrack_expect * -__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); - -extern struct nf_conntrack_expect * -nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); - -extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); - -extern void nf_ct_remove_expectations(struct nf_conn *ct); - extern void nf_conntrack_flush(void); extern struct nf_conntrack_helper * @@ -295,6 +247,7 @@ extern int nf_conntrack_checksum; #ifdef CONFIG_NF_CONNTRACK_EVENTS #include #include +#include struct nf_conntrack_ecache { struct nf_conn *ct; diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index da254525a4ce..84a8e01941fb 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -13,6 +13,8 @@ #define _NF_CONNTRACK_CORE_H #include +#include +#include /* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use @@ -70,6 +72,11 @@ static inline int nf_conntrack_confirm(struct sk_buff **pskb) extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb); +int +print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, + struct nf_conntrack_l3proto *l3proto, + struct nf_conntrack_protocol *proto); + extern struct list_head *nf_conntrack_hash; extern struct list_head nf_conntrack_expect_list; extern rwlock_t nf_conntrack_lock ; diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h new file mode 100644 index 000000000000..5aa483e03455 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -0,0 +1,72 @@ +/* + * connection tracking expectations. + */ + +#ifndef _NF_CONNTRACK_EXPECT_H +#define _NF_CONNTRACK_EXPECT_H +#include + +extern struct list_head nf_conntrack_expect_list; +extern kmem_cache_t *nf_conntrack_expect_cachep; +extern struct file_operations exp_file_ops; + +struct nf_conntrack_expect +{ + /* Internal linked list (global expectation list) */ + struct list_head list; + + /* We expect this tuple, with the following mask */ + struct nf_conntrack_tuple tuple, mask; + + /* Function to call after setup and insertion */ + void (*expectfn)(struct nf_conn *new, + struct nf_conntrack_expect *this); + + /* The conntrack of the master connection */ + struct nf_conn *master; + + /* Timer function; deletes the expectation. */ + struct timer_list timeout; + + /* Usage count. */ + atomic_t use; + + /* Unique ID */ + unsigned int id; + + /* Flags */ + unsigned int flags; + +#ifdef CONFIG_NF_NAT_NEEDED + /* This is the original per-proto part, used to map the + * expected connection the way the recipient expects. */ + union nf_conntrack_manip_proto saved_proto; + /* Direction relative to the master connection. */ + enum ip_conntrack_dir dir; +#endif +}; + +#define NF_CT_EXPECT_PERMANENT 0x1 + + +struct nf_conntrack_expect * +__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); + +struct nf_conntrack_expect * +nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); + +struct nf_conntrack_expect * +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); + +/* 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_put(struct nf_conntrack_expect *exp); +int nf_conntrack_expect_related(struct nf_conntrack_expect *expect); + +#endif /*_NF_CONNTRACK_EXPECT_H*/ + diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 86ec8174ad02..3cbd13e22160 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -40,14 +40,4 @@ struct nf_conntrack_helper extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); -/* Allocate space for an expectation: this is mandatory before calling - nf_conntrack_expect_related. You will have to call put afterwards. */ -extern struct nf_conntrack_expect * -nf_conntrack_expect_alloc(struct nf_conn *master); -extern void nf_conntrack_expect_put(struct nf_conntrack_expect *exp); - -/* Add an expected connection: can have more than one per connection */ -extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp); -extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp); - #endif /*_NF_CONNTRACK_HELPER_H*/ diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index a74be492fd0a..d33b9ac01aa7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,5 +1,5 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o -nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o +nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o obj-$(CONFIG_NETFILTER) = netfilter.o diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index de0567b1f422..72fbae4e594c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -72,21 +73,19 @@ DEFINE_RWLOCK(nf_conntrack_lock); atomic_t nf_conntrack_count = ATOMIC_INIT(0); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; -LIST_HEAD(nf_conntrack_expect_list); struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; static LIST_HEAD(helpers); unsigned int nf_conntrack_htable_size __read_mostly = 0; int nf_conntrack_max __read_mostly; struct list_head *nf_conntrack_hash __read_mostly; -static kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; struct nf_conn nf_conntrack_untracked; unsigned int nf_ct_log_invalid __read_mostly; static LIST_HEAD(unconfirmed); static int nf_conntrack_vmalloc __read_mostly; static unsigned int nf_conntrack_next_id; -static unsigned int nf_conntrack_expect_next_id; + #ifdef CONFIG_NF_CONNTRACK_EVENTS ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); @@ -438,103 +437,6 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, return protocol->invert_tuple(inverse, orig); } -/* nf_conntrack_expect helper functions */ -void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) -{ - struct nf_conn_help *master_help = nfct_help(exp->master); - - NF_CT_ASSERT(master_help); - ASSERT_WRITE_LOCK(&nf_conntrack_lock); - NF_CT_ASSERT(!timer_pending(&exp->timeout)); - - list_del(&exp->list); - NF_CT_STAT_INC(expect_delete); - master_help->expecting--; - nf_conntrack_expect_put(exp); -} - -static void 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); -} - -struct nf_conntrack_expect * -__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_expect *i; - - list_for_each_entry(i, &nf_conntrack_expect_list, list) { - if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) - return i; - } - return NULL; -} - -/* Just find a expectation corresponding to a tuple. */ -struct nf_conntrack_expect * -nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_expect *i; - - read_lock_bh(&nf_conntrack_lock); - i = __nf_conntrack_expect_find(tuple); - if (i) - atomic_inc(&i->use); - read_unlock_bh(&nf_conntrack_lock); - - return i; -} - -/* If an expectation for this connection is found, it gets delete from - * global list then returned. */ -static struct nf_conntrack_expect * -find_expectation(const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_expect *i; - - list_for_each_entry(i, &nf_conntrack_expect_list, list) { - /* If master is not in hash table yet (ie. packet hasn't left - this machine yet), how can other end know about expected? - Hence these are not the droids you are looking for (if - master ct never got confirmed, we'd hold a reference to it - and weird things would happen to future packets). */ - if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) - && nf_ct_is_confirmed(i->master)) { - if (i->flags & NF_CT_EXPECT_PERMANENT) { - atomic_inc(&i->use); - return i; - } else if (del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - return i; - } - } - } - return NULL; -} - -/* 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); - - /* Optimization: most connection never expect any others. */ - if (!help || help->expecting == 0) - return; - - list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { - if (i->master == ct && del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - nf_conntrack_expect_put(i); - } - } -} - static void clean_from_lists(struct nf_conn *ct) { @@ -1133,169 +1035,6 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, orig->dst.protonum)); } -/* Would two expected things clash? */ -static inline int expect_clash(const struct nf_conntrack_expect *a, - const struct nf_conntrack_expect *b) -{ - /* Part covered by intersection of masks must be unequal, - otherwise they clash */ - struct nf_conntrack_tuple 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); -} - -static inline int expect_matches(const struct nf_conntrack_expect *a, - const struct nf_conntrack_expect *b) -{ - return a->master == b->master - && nf_ct_tuple_equal(&a->tuple, &b->tuple) - && nf_ct_tuple_equal(&a->mask, &b->mask); -} - -/* Generally a bad idea to call this: could have matched already. */ -void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp) -{ - struct nf_conntrack_expect *i; - - write_lock_bh(&nf_conntrack_lock); - /* choose the the oldest expectation to evict */ - list_for_each_entry_reverse(i, &nf_conntrack_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); - return; - } - } - write_unlock_bh(&nf_conntrack_lock); -} - -/* 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 *new; - - new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC); - if (!new) { - DEBUGP("expect_related: OOM allocating expect\n"); - return NULL; - } - new->master = me; - atomic_set(&new->use, 1); - return new; -} - -void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) -{ - if (atomic_dec_and_test(&exp->use)) - kmem_cache_free(nf_conntrack_expect_cachep, exp); -} - -static void nf_conntrack_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); - - init_timer(&exp->timeout); - exp->timeout.data = (unsigned long)exp; - exp->timeout.function = expectation_timed_out; - exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; - add_timer(&exp->timeout); - - exp->id = ++nf_conntrack_expect_next_id; - atomic_inc(&exp->use); - NF_CT_STAT_INC(expect_create); -} - -/* 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; - - list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { - if (i->master == master) { - if (del_timer(&i->timeout)) { - nf_ct_unlink_expect(i); - nf_conntrack_expect_put(i); - } - break; - } - } -} - -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ - struct nf_conn_help *master_help = nfct_help(i->master); - - if (!del_timer(&i->timeout)) - return 0; - - i->timeout.expires = jiffies + master_help->helper->timeout*HZ; - add_timer(&i->timeout); - return 1; -} - -int nf_conntrack_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); - int ret; - - NF_CT_ASSERT(master_help); - - DEBUGP("nf_conntrack_expect_related %p\n", related_to); - DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple); - DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask); - - write_lock_bh(&nf_conntrack_lock); - list_for_each_entry(i, &nf_conntrack_expect_list, list) { - if (expect_matches(i, expect)) { - /* Refresh timer: if it's dying, ignore.. */ - if (refresh_timer(i)) { - ret = 0; - goto out; - } - } else if (expect_clash(i, expect)) { - ret = -EBUSY; - goto out; - } - } - /* Will be over limit? */ - if (master_help->helper->max_expected && - master_help->expecting >= master_help->helper->max_expected) - evict_oldest_expect(master); - - nf_conntrack_expect_insert(expect); - nf_conntrack_expect_event(IPEXP_NEW, expect); - ret = 0; -out: - write_unlock_bh(&nf_conntrack_lock); - return ret; -} - int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { int ret; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c new file mode 100644 index 000000000000..076e678b3188 --- /dev/null +++ b/net/netfilter/nf_conntrack_expect.c @@ -0,0 +1,365 @@ +/* Expectation handling for nf_conntrack. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * (C) 2003,2004 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 version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +LIST_HEAD(nf_conntrack_expect_list); +kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; +DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); +static unsigned int nf_conntrack_expect_next_id; + +/* nf_conntrack_expect helper functions */ +void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) +{ + struct nf_conn_help *master_help = nfct_help(exp->master); + + NF_CT_ASSERT(master_help); + NF_CT_ASSERT(!timer_pending(&exp->timeout)); + + list_del(&exp->list); + NF_CT_STAT_INC(expect_delete); + master_help->expecting--; + nf_conntrack_expect_put(exp); +} + +static void 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); +} + +struct nf_conntrack_expect * +__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) +{ + struct nf_conntrack_expect *i; + + list_for_each_entry(i, &nf_conntrack_expect_list, list) { + if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) + return i; + } + return NULL; +} + +/* Just find a expectation corresponding to a tuple. */ +struct nf_conntrack_expect * +nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) +{ + struct nf_conntrack_expect *i; + + read_lock_bh(&nf_conntrack_lock); + i = __nf_conntrack_expect_find(tuple); + if (i) + atomic_inc(&i->use); + read_unlock_bh(&nf_conntrack_lock); + + return i; +} + +/* 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) +{ + struct nf_conntrack_expect *i; + + list_for_each_entry(i, &nf_conntrack_expect_list, list) { + /* If master is not in hash table yet (ie. packet hasn't left + this machine yet), how can other end know about expected? + Hence these are not the droids you are looking for (if + master ct never got confirmed, we'd hold a reference to it + and weird things would happen to future packets). */ + if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) + && nf_ct_is_confirmed(i->master)) { + if (i->flags & NF_CT_EXPECT_PERMANENT) { + atomic_inc(&i->use); + return i; + } else if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + return i; + } + } + } + return NULL; +} + +/* 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); + + /* Optimization: most connection never expect any others. */ + if (!help || help->expecting == 0) + return; + + list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { + if (i->master == ct && del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_conntrack_expect_put(i); + } + } +} + +/* Would two expected things clash? */ +static inline int expect_clash(const struct nf_conntrack_expect *a, + const struct nf_conntrack_expect *b) +{ + /* Part covered by intersection of masks must be unequal, + otherwise they clash */ + struct nf_conntrack_tuple 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); +} + +static inline int expect_matches(const struct nf_conntrack_expect *a, + const struct nf_conntrack_expect *b) +{ + return a->master == b->master + && nf_ct_tuple_equal(&a->tuple, &b->tuple) + && nf_ct_tuple_equal(&a->mask, &b->mask); +} + +/* Generally a bad idea to call this: could have matched already. */ +void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp) +{ + struct nf_conntrack_expect *i; + + write_lock_bh(&nf_conntrack_lock); + /* choose the the oldest expectation to evict */ + list_for_each_entry_reverse(i, &nf_conntrack_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); + return; + } + } + write_unlock_bh(&nf_conntrack_lock); +} + +/* 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 *new; + + new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC); + if (!new) + return NULL; + + new->master = me; + atomic_set(&new->use, 1); + return new; +} + +void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) +{ + if (atomic_dec_and_test(&exp->use)) + kmem_cache_free(nf_conntrack_expect_cachep, exp); +} + +static void nf_conntrack_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); + + init_timer(&exp->timeout); + exp->timeout.data = (unsigned long)exp; + exp->timeout.function = expectation_timed_out; + exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; + add_timer(&exp->timeout); + + exp->id = ++nf_conntrack_expect_next_id; + atomic_inc(&exp->use); + NF_CT_STAT_INC(expect_create); +} + +/* 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; + + list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { + if (i->master == master) { + if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_conntrack_expect_put(i); + } + break; + } + } +} + +static inline int refresh_timer(struct nf_conntrack_expect *i) +{ + struct nf_conn_help *master_help = nfct_help(i->master); + + if (!del_timer(&i->timeout)) + return 0; + + i->timeout.expires = jiffies + master_help->helper->timeout*HZ; + add_timer(&i->timeout); + return 1; +} + +int nf_conntrack_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); + int ret; + + NF_CT_ASSERT(master_help); + + write_lock_bh(&nf_conntrack_lock); + list_for_each_entry(i, &nf_conntrack_expect_list, list) { + if (expect_matches(i, expect)) { + /* Refresh timer: if it's dying, ignore.. */ + if (refresh_timer(i)) { + ret = 0; + goto out; + } + } else if (expect_clash(i, expect)) { + ret = -EBUSY; + goto out; + } + } + /* Will be over limit? */ + if (master_help->helper->max_expected && + master_help->expecting >= master_help->helper->max_expected) + evict_oldest_expect(master); + + nf_conntrack_expect_insert(expect); + nf_conntrack_expect_event(IPEXP_NEW, expect); + ret = 0; +out: + write_unlock_bh(&nf_conntrack_lock); + return ret; +} + +#ifdef CONFIG_PROC_FS +static void *exp_seq_start(struct seq_file *s, loff_t *pos) +{ + struct list_head *e = &nf_conntrack_expect_list; + loff_t i; + + /* strange seq_file api calls stop even if we fail, + * thus we need to grab lock since stop unlocks */ + read_lock_bh(&nf_conntrack_lock); + + if (list_empty(e)) + return NULL; + + for (i = 0; i <= *pos; i++) { + e = e->next; + if (e == &nf_conntrack_expect_list) + return NULL; + } + return e; +} + +static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct list_head *e = v; + + ++*pos; + e = e->next; + + if (e == &nf_conntrack_expect_list) + return NULL; + + return e; +} + +static void exp_seq_stop(struct seq_file *s, void *v) +{ + read_unlock_bh(&nf_conntrack_lock); +} + +static int exp_seq_show(struct seq_file *s, void *v) +{ + struct nf_conntrack_expect *expect = v; + + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); + else + seq_printf(s, "- "); + seq_printf(s, "l3proto = %u proto=%u ", + expect->tuple.src.l3num, + expect->tuple.dst.protonum); + print_tuple(s, &expect->tuple, + __nf_ct_l3proto_find(expect->tuple.src.l3num), + __nf_ct_proto_find(expect->tuple.src.l3num, + expect->tuple.dst.protonum)); + return seq_putc(s, '\n'); +} + +static struct seq_operations exp_seq_ops = { + .start = exp_seq_start, + .next = exp_seq_next, + .stop = exp_seq_stop, + .show = exp_seq_show +}; + +static int exp_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &exp_seq_ops); +} + +struct file_operations exp_file_ops = { + .owner = THIS_MODULE, + .open = exp_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; +#endif /* CONFIG_PROC_FS */ diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 0c17a5bd112b..503fabf18843 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -26,6 +26,7 @@ #include #include +#include #include #include diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cfb35fd8d9b9..c3d53d91929f 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 5954f6773810..72643d32cab3 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #if 0 @@ -66,7 +67,7 @@ static int kill_proto(struct nf_conn *i, void *data) } #ifdef CONFIG_PROC_FS -static int +int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, struct nf_conntrack_protocol *proto) @@ -258,84 +259,6 @@ static struct file_operations ct_file_ops = { .release = seq_release_private, }; -/* expects */ -static void *exp_seq_start(struct seq_file *s, loff_t *pos) -{ - struct list_head *e = &nf_conntrack_expect_list; - loff_t i; - - /* strange seq_file api calls stop even if we fail, - * thus we need to grab lock since stop unlocks */ - read_lock_bh(&nf_conntrack_lock); - - if (list_empty(e)) - return NULL; - - for (i = 0; i <= *pos; i++) { - e = e->next; - if (e == &nf_conntrack_expect_list) - return NULL; - } - return e; -} - -static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - struct list_head *e = v; - - ++*pos; - e = e->next; - - if (e == &nf_conntrack_expect_list) - return NULL; - - return e; -} - -static void exp_seq_stop(struct seq_file *s, void *v) -{ - read_unlock_bh(&nf_conntrack_lock); -} - -static int exp_seq_show(struct seq_file *s, void *v) -{ - struct nf_conntrack_expect *expect = v; - - if (expect->timeout.function) - seq_printf(s, "%ld ", timer_pending(&expect->timeout) - ? (long)(expect->timeout.expires - jiffies)/HZ : 0); - else - seq_printf(s, "- "); - seq_printf(s, "l3proto = %u proto=%u ", - expect->tuple.src.l3num, - expect->tuple.dst.protonum); - print_tuple(s, &expect->tuple, - __nf_ct_l3proto_find(expect->tuple.src.l3num), - __nf_ct_proto_find(expect->tuple.src.l3num, - expect->tuple.dst.protonum)); - return seq_putc(s, '\n'); -} - -static struct seq_operations exp_seq_ops = { - .start = exp_seq_start, - .next = exp_seq_next, - .stop = exp_seq_stop, - .show = exp_seq_show -}; - -static int exp_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &exp_seq_ops); -} - -static struct file_operations exp_file_ops = { - .owner = THIS_MODULE, - .open = exp_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release -}; - static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) { int cpu; -- cgit v1.2.3-70-g09d2 From 7e5d03bb9d2b96fdeab0cb0c98b93e6cf7130c96 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:34:59 +0100 Subject: [NETFILTER]: nf_conntrack: split out helper handling This patch splits out handling of helpers into its own file nf_conntrack_helper.c Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_core.h | 2 + include/net/netfilter/nf_conntrack_helper.h | 10 ++ net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_core.c | 120 +--------------------- net/netfilter/nf_conntrack_helper.c | 151 ++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 120 deletions(-) create mode 100644 net/netfilter/nf_conntrack_helper.c (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 84a8e01941fb..bf8d3008a381 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -80,4 +80,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, extern struct list_head *nf_conntrack_hash; extern struct list_head nf_conntrack_expect_list; extern rwlock_t nf_conntrack_lock ; +extern struct list_head unconfirmed; + #endif /* _NF_CONNTRACK_CORE_H */ diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 3cbd13e22160..fbba9e8b95fc 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -37,6 +37,16 @@ struct nf_conntrack_helper int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct); }; +extern struct nf_conntrack_helper * +__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple); + +extern struct nf_conntrack_helper * +nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); + +extern struct nf_conntrack_helper * +__nf_conntrack_helper_find_byname(const char *name); + +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 *); diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index d33b9ac01aa7..236376483ef7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,5 +1,5 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o -nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o +nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o obj-$(CONFIG_NETFILTER) = netfilter.o diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 72fbae4e594c..cf6face67af4 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -75,13 +75,12 @@ atomic_t nf_conntrack_count = ATOMIC_INIT(0); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; -static LIST_HEAD(helpers); unsigned int nf_conntrack_htable_size __read_mostly = 0; int nf_conntrack_max __read_mostly; struct list_head *nf_conntrack_hash __read_mostly; struct nf_conn nf_conntrack_untracked; unsigned int nf_ct_log_invalid __read_mostly; -static LIST_HEAD(unconfirmed); +LIST_HEAD(unconfirmed); static int nf_conntrack_vmalloc __read_mostly; static unsigned int nf_conntrack_next_id; @@ -696,46 +695,6 @@ static int early_drop(struct list_head *chain) return dropped; } -static struct nf_conntrack_helper * -__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_helper *h; - - list_for_each_entry(h, &helpers, list) { - if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) - return h; - } - return NULL; -} - -struct nf_conntrack_helper * -nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) -{ - struct nf_conntrack_helper *helper; - - /* need nf_conntrack_lock to assure that helper exists until - * try_module_get() is called */ - read_lock_bh(&nf_conntrack_lock); - - helper = __nf_ct_helper_find(tuple); - if (helper) { - /* need to increase module usage count to assure helper will - * not go away while the caller is e.g. busy putting a - * conntrack in the hash that uses the helper */ - if (!try_module_get(helper->me)) - helper = NULL; - } - - read_unlock_bh(&nf_conntrack_lock); - - return helper; -} - -void nf_ct_helper_put(struct nf_conntrack_helper *helper) -{ - module_put(helper->me); -} - static struct nf_conn * __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *repl, @@ -1035,83 +994,6 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, orig->dst.protonum)); } -int nf_conntrack_helper_register(struct nf_conntrack_helper *me) -{ - int ret; - BUG_ON(me->timeout == 0); - - ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", - sizeof(struct nf_conn) - + sizeof(struct nf_conn_help) - + __alignof__(struct nf_conn_help)); - if (ret < 0) { - printk(KERN_ERR "nf_conntrack_helper_reigster: 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); - - return 0; -} - -struct nf_conntrack_helper * -__nf_conntrack_helper_find_byname(const char *name) -{ - struct nf_conntrack_helper *h; - - list_for_each_entry(h, &helpers, list) { - if (!strcmp(h->name, name)) - return h; - } - - return NULL; -} - -static inline void unhelp(struct nf_conntrack_tuple_hash *i, - const struct nf_conntrack_helper *me) -{ - struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); - struct nf_conn_help *help = nfct_help(ct); - - if (help && help->helper == me) { - nf_conntrack_event(IPCT_HELPER, ct); - help->helper = NULL; - } -} - -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; - - /* Need write lock here, to delete helper. */ - write_lock_bh(&nf_conntrack_lock); - list_del(&me->list); - - /* Get rid of expectations */ - list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { - struct nf_conn_help *help = nfct_help(exp->master); - if (help->helper == me && del_timer(&exp->timeout)) { - nf_ct_unlink_expect(exp); - nf_conntrack_expect_put(exp); - } - } - - /* Get rid of expecteds, set helpers to NULL. */ - list_for_each_entry(h, &unconfirmed, list) - unhelp(h, me); - for (i = 0; i < nf_conntrack_htable_size; i++) { - list_for_each_entry(h, &nf_conntrack_hash[i], list) - unhelp(h, me); - } - write_unlock_bh(&nf_conntrack_lock); - - /* Someone could be still looking at the helper in a bh. */ - synchronize_net(); -} - /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c new file mode 100644 index 000000000000..ca044875a561 --- /dev/null +++ b/net/netfilter/nf_conntrack_helper.c @@ -0,0 +1,151 @@ +/* Helper handling for netfilter. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * (C) 2003,2004 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 version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + +#include +#include +#include +#include +#include + +static LIST_HEAD(helpers); + +struct nf_conntrack_helper * +__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) +{ + struct nf_conntrack_helper *h; + + list_for_each_entry(h, &helpers, list) { + if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) + return h; + } + return NULL; +} + +struct nf_conntrack_helper * +nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) +{ + struct nf_conntrack_helper *helper; + + /* need nf_conntrack_lock to assure that helper exists until + * try_module_get() is called */ + read_lock_bh(&nf_conntrack_lock); + + helper = __nf_ct_helper_find(tuple); + if (helper) { + /* need to increase module usage count to assure helper will + * not go away while the caller is e.g. busy putting a + * conntrack in the hash that uses the helper */ + if (!try_module_get(helper->me)) + helper = NULL; + } + + read_unlock_bh(&nf_conntrack_lock); + + return helper; +} + +void nf_ct_helper_put(struct nf_conntrack_helper *helper) +{ + module_put(helper->me); +} + +struct nf_conntrack_helper * +__nf_conntrack_helper_find_byname(const char *name) +{ + struct nf_conntrack_helper *h; + + list_for_each_entry(h, &helpers, list) { + if (!strcmp(h->name, name)) + return h; + } + + return NULL; +} + +static inline int unhelp(struct nf_conntrack_tuple_hash *i, + const struct nf_conntrack_helper *me) +{ + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); + struct nf_conn_help *help = nfct_help(ct); + + if (help && help->helper == me) { + nf_conntrack_event(IPCT_HELPER, ct); + help->helper = NULL; + } + return 0; +} + +int nf_conntrack_helper_register(struct nf_conntrack_helper *me) +{ + int ret; + BUG_ON(me->timeout == 0); + + ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", + sizeof(struct nf_conn) + + sizeof(struct nf_conn_help) + + __alignof__(struct nf_conn_help)); + 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); + + return 0; +} + +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; + + /* Need write lock here, to delete helper. */ + write_lock_bh(&nf_conntrack_lock); + list_del(&me->list); + + /* Get rid of expectations */ + list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { + struct nf_conn_help *help = nfct_help(exp->master); + if (help->helper == me && del_timer(&exp->timeout)) { + nf_ct_unlink_expect(exp); + nf_conntrack_expect_put(exp); + } + } + + /* Get rid of expecteds, set helpers to NULL. */ + list_for_each_entry(h, &unconfirmed, list) + unhelp(h, me); + for (i = 0; i < nf_conntrack_htable_size; i++) { + list_for_each_entry(h, &nf_conntrack_hash[i], list) + unhelp(h, me); + } + write_unlock_bh(&nf_conntrack_lock); + + /* Someone could be still looking at the helper in a bh. */ + synchronize_net(); +} -- cgit v1.2.3-70-g09d2 From f61801218a58381f498ae5c38ae3eae0bc73e976 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:01 +0100 Subject: [NETFILTER]: nf_conntrack: split out the event cache This patch splits out the event cache into its own file nf_conntrack_ecache.c Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack.h | 81 ------------------------ include/net/netfilter/nf_conntrack_core.h | 1 + include/net/netfilter/nf_conntrack_ecache.h | 95 +++++++++++++++++++++++++++++ net/netfilter/Makefile | 4 +- net/netfilter/nf_conntrack_core.c | 67 -------------------- net/netfilter/nf_conntrack_ecache.c | 91 +++++++++++++++++++++++++++ net/netfilter/nf_conntrack_ftp.c | 1 + net/netfilter/nf_conntrack_proto_sctp.c | 1 + net/netfilter/nf_conntrack_proto_tcp.c | 1 + net/netfilter/nf_conntrack_proto_udp.c | 2 + net/netfilter/nf_conntrack_standalone.c | 2 +- net/netfilter/xt_CONNMARK.c | 3 + 12 files changed, 199 insertions(+), 150 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_ecache.h create mode 100644 net/netfilter/nf_conntrack_ecache.c (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 9d2581fc04be..9a2950551cd3 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -244,87 +244,6 @@ extern int nf_conntrack_checksum; #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++) -#ifdef CONFIG_NF_CONNTRACK_EVENTS -#include -#include -#include - -struct nf_conntrack_ecache { - struct nf_conn *ct; - unsigned int events; -}; -DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); - -#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x) - -extern struct atomic_notifier_head nf_conntrack_chain; -extern struct atomic_notifier_head nf_conntrack_expect_chain; - -static inline int nf_conntrack_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&nf_conntrack_chain, nb); -} - -static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); -} - -static inline int -nf_conntrack_expect_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); -} - -static inline int -nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, - nb); -} - -extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); -extern void __nf_ct_event_cache_init(struct nf_conn *ct); - -static inline void -nf_conntrack_event_cache(enum ip_conntrack_events event, - const struct sk_buff *skb) -{ - struct nf_conn *ct = (struct nf_conn *)skb->nfct; - struct nf_conntrack_ecache *ecache; - - local_bh_disable(); - ecache = &__get_cpu_var(nf_conntrack_ecache); - if (ct != ecache->ct) - __nf_ct_event_cache_init(ct); - ecache->events |= event; - local_bh_enable(); -} - -static inline void nf_conntrack_event(enum ip_conntrack_events event, - struct nf_conn *ct) -{ - if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) - atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); -} - -static inline void -nf_conntrack_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) -{ - atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp); -} -#else /* CONFIG_NF_CONNTRACK_EVENTS */ -static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, - const struct sk_buff *skb) {} -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) {} -#endif /* CONFIG_NF_CONNTRACK_EVENTS */ - /* no helper, no nat */ #define NF_CT_F_BASIC 0 /* for helper */ diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index bf8d3008a381..4676b492d635 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -15,6 +15,7 @@ #include #include #include +#include /* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h new file mode 100644 index 000000000000..b62a8a9ec9d8 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -0,0 +1,95 @@ +/* + * connection tracking event cache. + */ + +#ifndef _NF_CONNTRACK_ECACHE_H +#define _NF_CONNTRACK_ECACHE_H +#include + +#include +#include +#include + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +struct nf_conntrack_ecache { + struct nf_conn *ct; + unsigned int events; +}; +DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); + +#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x) + +extern struct atomic_notifier_head nf_conntrack_chain; +extern struct atomic_notifier_head nf_conntrack_expect_chain; + +static inline int nf_conntrack_register_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&nf_conntrack_chain, nb); +} + +static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); +} + +static inline int +nf_conntrack_expect_register_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); +} + +static inline int +nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, + nb); +} + +extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); +extern void __nf_ct_event_cache_init(struct nf_conn *ct); +extern void nf_ct_event_cache_flush(void); + +static inline void +nf_conntrack_event_cache(enum ip_conntrack_events event, + const struct sk_buff *skb) +{ + struct nf_conn *ct = (struct nf_conn *)skb->nfct; + struct nf_conntrack_ecache *ecache; + + local_bh_disable(); + ecache = &__get_cpu_var(nf_conntrack_ecache); + if (ct != ecache->ct) + __nf_ct_event_cache_init(ct); + ecache->events |= event; + local_bh_enable(); +} + +static inline void nf_conntrack_event(enum ip_conntrack_events event, + struct nf_conn *ct) +{ + if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) + atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); +} + +static inline void +nf_conntrack_expect_event(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp) +{ + atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp); +} + +#else /* CONFIG_NF_CONNTRACK_EVENTS */ + +static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, + const struct sk_buff *skb) {} +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_event_cache_flush(void) {} +#endif /* CONFIG_NF_CONNTRACK_EVENTS */ + +#endif /*_NF_CONNTRACK_ECACHE_H*/ + diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 236376483ef7..fd0641d6679a 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,5 +1,7 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o -nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.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_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.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 cf6face67af4..029acc4f9643 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -85,73 +85,6 @@ static int nf_conntrack_vmalloc __read_mostly; static unsigned int nf_conntrack_next_id; -#ifdef CONFIG_NF_CONNTRACK_EVENTS -ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); -ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); - -DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); - -/* deliver cached events and clear cache entry - must be called with locally - * disabled softirqs */ -static inline void -__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) -{ - DEBUGP("ecache: delivering events for %p\n", ecache->ct); - if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) - && ecache->events) - atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, - ecache->ct); - - ecache->events = 0; - nf_ct_put(ecache->ct); - ecache->ct = NULL; -} - -/* Deliver all cached events for a particular conntrack. This is called - * by code prior to async packet handling for freeing the skb */ -void nf_ct_deliver_cached_events(const struct nf_conn *ct) -{ - struct nf_conntrack_ecache *ecache; - - local_bh_disable(); - ecache = &__get_cpu_var(nf_conntrack_ecache); - if (ecache->ct == ct) - __nf_ct_deliver_cached_events(ecache); - local_bh_enable(); -} - -/* Deliver cached events for old pending events, if current conntrack != old */ -void __nf_ct_event_cache_init(struct nf_conn *ct) -{ - struct nf_conntrack_ecache *ecache; - - /* take care of delivering potentially old events */ - ecache = &__get_cpu_var(nf_conntrack_ecache); - BUG_ON(ecache->ct == ct); - if (ecache->ct) - __nf_ct_deliver_cached_events(ecache); - /* initialize for this conntrack/packet */ - ecache->ct = ct; - nf_conntrack_get(&ct->ct_general); -} - -/* flush the event cache - touches other CPU's data and must not be called - * while packets are still passing through the code */ -static void nf_ct_event_cache_flush(void) -{ - struct nf_conntrack_ecache *ecache; - int cpu; - - for_each_possible_cpu(cpu) { - ecache = &per_cpu(nf_conntrack_ecache, cpu); - if (ecache->ct) - nf_ct_put(ecache->ct); - } -} -#else -static inline void nf_ct_event_cache_flush(void) {} -#endif /* CONFIG_NF_CONNTRACK_EVENTS */ - DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat); diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c new file mode 100644 index 000000000000..35763e96fddb --- /dev/null +++ b/net/netfilter/nf_conntrack_ecache.c @@ -0,0 +1,91 @@ +/* Event cache for netfilter. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * (C) 2003,2004 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 version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); +ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); + +DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); + +/* deliver cached events and clear cache entry - must be called with locally + * disabled softirqs */ +static inline void +__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) +{ + if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) + && ecache->events) + atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, + ecache->ct); + + ecache->events = 0; + nf_ct_put(ecache->ct); + ecache->ct = NULL; +} + +/* Deliver all cached events for a particular conntrack. This is called + * by code prior to async packet handling for freeing the skb */ +void nf_ct_deliver_cached_events(const struct nf_conn *ct) +{ + struct nf_conntrack_ecache *ecache; + + local_bh_disable(); + ecache = &__get_cpu_var(nf_conntrack_ecache); + if (ecache->ct == ct) + __nf_ct_deliver_cached_events(ecache); + local_bh_enable(); +} + +/* Deliver cached events for old pending events, if current conntrack != old */ +void __nf_ct_event_cache_init(struct nf_conn *ct) +{ + struct nf_conntrack_ecache *ecache; + + /* take care of delivering potentially old events */ + ecache = &__get_cpu_var(nf_conntrack_ecache); + BUG_ON(ecache->ct == ct); + if (ecache->ct) + __nf_ct_deliver_cached_events(ecache); + /* initialize for this conntrack/packet */ + ecache->ct = ct; + nf_conntrack_get(&ct->ct_general); +} + +/* flush the event cache - touches other CPU's data and must not be called + * while packets are still passing through the code */ +void nf_ct_event_cache_flush(void) +{ + struct nf_conntrack_ecache *ecache; + int cpu; + + for_each_possible_cpu(cpu) { + ecache = &per_cpu(nf_conntrack_ecache, cpu); + if (ecache->ct) + nf_ct_put(ecache->ct); + } +} + diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 503fabf18843..10836fc22a44 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index af568777372b..ba3e31f2acd7 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -33,6 +33,7 @@ #include #include +#include #if 0 #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 238bbb5b72ef..e6b6f23ecdd6 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -43,6 +43,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index d28981cf9af5..cf9db035d39a 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -22,10 +22,12 @@ #include #include #include + #include #include #include #include +#include unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 72643d32cab3..73ca156bb098 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -33,9 +33,9 @@ #define ASSERT_WRITE_LOCK(x) #include +#include #include #include -#include #include #include diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 67ed53152999..b5548239d412 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -31,6 +31,9 @@ MODULE_ALIAS("ipt_CONNMARK"); #include #include #include +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#include +#endif static unsigned int target(struct sk_buff **pskb, -- cgit v1.2.3-70-g09d2 From 8f03dea52b1d0227656319e1b0822628b43791a8 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:03 +0100 Subject: [NETFILTER]: nf_conntrack: split out protocol handling This patch splits out L3/L4 protocol handling into its own file nf_conntrack_proto.c Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_core.c | 81 ------------ net/netfilter/nf_conntrack_proto.c | 225 ++++++++++++++++++++++++++++++++ net/netfilter/nf_conntrack_standalone.c | 116 ---------------- 4 files changed, 226 insertions(+), 198 deletions(-) create mode 100644 net/netfilter/nf_conntrack_proto.c (limited to 'net') diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index fd0641d6679a..627105df1040 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_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-$(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 029acc4f9643..09c0e6311044 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -73,8 +73,6 @@ DEFINE_RWLOCK(nf_conntrack_lock); atomic_t nf_conntrack_count = ATOMIC_INIT(0); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; -struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; -struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; unsigned int nf_conntrack_htable_size __read_mostly = 0; int nf_conntrack_max __read_mostly; struct list_head *nf_conntrack_hash __read_mostly; @@ -115,85 +113,6 @@ DEFINE_RWLOCK(nf_ct_cache_lock); /* This avoids calling kmem_cache_create() with same name simultaneously */ static DEFINE_MUTEX(nf_ct_cache_mutex); -extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; -struct nf_conntrack_protocol * -__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) -{ - if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) - return &nf_conntrack_generic_protocol; - - return nf_ct_protos[l3proto][protocol]; -} - -/* this is guaranteed to always return a valid protocol helper, since - * it falls back to generic_protocol */ -struct nf_conntrack_protocol * -nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) -{ - struct nf_conntrack_protocol *p; - - preempt_disable(); - p = __nf_ct_proto_find(l3proto, protocol); - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_protocol; - preempt_enable(); - - return p; -} - -void nf_ct_proto_put(struct nf_conntrack_protocol *p) -{ - module_put(p->me); -} - -struct nf_conntrack_l3proto * -nf_ct_l3proto_find_get(u_int16_t l3proto) -{ - struct nf_conntrack_l3proto *p; - - preempt_disable(); - p = __nf_ct_l3proto_find(l3proto); - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_l3proto; - preempt_enable(); - - return p; -} - -void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) -{ - module_put(p->me); -} - -int -nf_ct_l3proto_try_module_get(unsigned short l3proto) -{ - int ret; - struct nf_conntrack_l3proto *p; - -retry: p = nf_ct_l3proto_find_get(l3proto); - if (p == &nf_conntrack_generic_l3proto) { - ret = request_module("nf_conntrack-%d", l3proto); - if (!ret) - goto retry; - - return -EPROTOTYPE; - } - - return 0; -} - -void nf_ct_l3proto_module_put(unsigned short l3proto) -{ - struct nf_conntrack_l3proto *p; - - preempt_disable(); - p = __nf_ct_l3proto_find(l3proto); - preempt_enable(); - - module_put(p->me); -} - static int nf_conntrack_hash_rnd_initted; static unsigned int nf_conntrack_hash_rnd; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c new file mode 100644 index 000000000000..24c61a384716 --- /dev/null +++ b/net/netfilter/nf_conntrack_proto.c @@ -0,0 +1,225 @@ +/* L3/L4 protocol support for nf_conntrack. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * (C) 2003,2004 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 version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; +struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; + +struct nf_conntrack_protocol * +__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) +{ + if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) + return &nf_conntrack_generic_protocol; + + return nf_ct_protos[l3proto][protocol]; +} + +/* this is guaranteed to always return a valid protocol helper, since + * it falls back to generic_protocol */ +struct nf_conntrack_protocol * +nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) +{ + struct nf_conntrack_protocol *p; + + preempt_disable(); + p = __nf_ct_proto_find(l3proto, protocol); + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_protocol; + preempt_enable(); + + return p; +} + +void nf_ct_proto_put(struct nf_conntrack_protocol *p) +{ + module_put(p->me); +} + +struct nf_conntrack_l3proto * +nf_ct_l3proto_find_get(u_int16_t l3proto) +{ + struct nf_conntrack_l3proto *p; + + preempt_disable(); + p = __nf_ct_l3proto_find(l3proto); + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_l3proto; + preempt_enable(); + + return p; +} + +void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) +{ + module_put(p->me); +} + +int +nf_ct_l3proto_try_module_get(unsigned short l3proto) +{ + int ret; + struct nf_conntrack_l3proto *p; + +retry: p = nf_ct_l3proto_find_get(l3proto); + if (p == &nf_conntrack_generic_l3proto) { + ret = request_module("nf_conntrack-%d", l3proto); + if (!ret) + goto retry; + + return -EPROTOTYPE; + } + + return 0; +} + +void nf_ct_l3proto_module_put(unsigned short l3proto) +{ + struct nf_conntrack_l3proto *p; + + preempt_disable(); + p = __nf_ct_l3proto_find(l3proto); + preempt_enable(); + + module_put(p->me); +} + +static int kill_l3proto(struct nf_conn *i, void *data) +{ + return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == + ((struct nf_conntrack_l3proto *)data)->l3proto); +} + +static int kill_proto(struct nf_conn *i, void *data) +{ + struct nf_conntrack_protocol *proto; + proto = (struct nf_conntrack_protocol *)data; + return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == + proto->proto) && + (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == + proto->l3proto); +} + +int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) +{ + int ret = 0; + + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) { + ret = -EBUSY; + goto out; + } + nf_ct_l3protos[proto->l3proto] = proto; +out: + write_unlock_bh(&nf_conntrack_lock); + + return ret; +} + +void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) +{ + write_lock_bh(&nf_conntrack_lock); + nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto; + write_unlock_bh(&nf_conntrack_lock); + + /* Somebody could be still looking at the proto in bh. */ + synchronize_net(); + + /* Remove all contrack entries for this protocol */ + nf_ct_iterate_cleanup(kill_l3proto, proto); +} + +/* FIXME: Allow NULL functions and sub in pointers to generic for + them. --RR */ +int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto) +{ + int ret = 0; + +retry: + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_protos[proto->l3proto]) { + if (nf_ct_protos[proto->l3proto][proto->proto] + != &nf_conntrack_generic_protocol) { + ret = -EBUSY; + goto out_unlock; + } + } else { + /* l3proto may be loaded latter. */ + struct nf_conntrack_protocol **proto_array; + int i; + + write_unlock_bh(&nf_conntrack_lock); + + proto_array = (struct nf_conntrack_protocol **) + kmalloc(MAX_NF_CT_PROTO * + sizeof(struct nf_conntrack_protocol *), + GFP_KERNEL); + if (proto_array == NULL) { + ret = -ENOMEM; + goto out; + } + for (i = 0; i < MAX_NF_CT_PROTO; i++) + proto_array[i] = &nf_conntrack_generic_protocol; + + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_protos[proto->l3proto]) { + /* bad timing, but no problem */ + write_unlock_bh(&nf_conntrack_lock); + kfree(proto_array); + } else { + nf_ct_protos[proto->l3proto] = proto_array; + write_unlock_bh(&nf_conntrack_lock); + } + + /* + * Just once because array is never freed until unloading + * nf_conntrack.ko + */ + goto retry; + } + + nf_ct_protos[proto->l3proto][proto->proto] = proto; + +out_unlock: + write_unlock_bh(&nf_conntrack_lock); +out: + return ret; +} + +void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) +{ + write_lock_bh(&nf_conntrack_lock); + nf_ct_protos[proto->l3proto][proto->proto] + = &nf_conntrack_generic_protocol; + write_unlock_bh(&nf_conntrack_lock); + + /* Somebody could be still looking at the proto in bh. */ + synchronize_net(); + + /* Remove all contrack entries for this protocol */ + nf_ct_iterate_cleanup(kill_proto, proto); +} diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 73ca156bb098..eb031d20e510 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -50,22 +50,6 @@ MODULE_LICENSE("GPL"); extern atomic_t nf_conntrack_count; DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); -static int kill_l3proto(struct nf_conn *i, void *data) -{ - return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == - ((struct nf_conntrack_l3proto *)data)->l3proto); -} - -static int kill_proto(struct nf_conn *i, void *data) -{ - struct nf_conntrack_protocol *proto; - proto = (struct nf_conntrack_protocol *)data; - return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == - proto->proto) && - (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == - proto->l3proto); -} - #ifdef CONFIG_PROC_FS int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, @@ -585,106 +569,6 @@ static ctl_table nf_ct_net_table[] = { EXPORT_SYMBOL(nf_ct_log_invalid); #endif /* CONFIG_SYSCTL */ -int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) -{ - int ret = 0; - - write_lock_bh(&nf_conntrack_lock); - if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) { - ret = -EBUSY; - goto out; - } - nf_ct_l3protos[proto->l3proto] = proto; -out: - write_unlock_bh(&nf_conntrack_lock); - - return ret; -} - -void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) -{ - write_lock_bh(&nf_conntrack_lock); - nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto; - write_unlock_bh(&nf_conntrack_lock); - - /* Somebody could be still looking at the proto in bh. */ - synchronize_net(); - - /* Remove all contrack entries for this protocol */ - nf_ct_iterate_cleanup(kill_l3proto, proto); -} - -/* FIXME: Allow NULL functions and sub in pointers to generic for - them. --RR */ -int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto) -{ - int ret = 0; - -retry: - write_lock_bh(&nf_conntrack_lock); - if (nf_ct_protos[proto->l3proto]) { - if (nf_ct_protos[proto->l3proto][proto->proto] - != &nf_conntrack_generic_protocol) { - ret = -EBUSY; - goto out_unlock; - } - } else { - /* l3proto may be loaded latter. */ - struct nf_conntrack_protocol **proto_array; - int i; - - write_unlock_bh(&nf_conntrack_lock); - - proto_array = (struct nf_conntrack_protocol **) - kmalloc(MAX_NF_CT_PROTO * - sizeof(struct nf_conntrack_protocol *), - GFP_KERNEL); - if (proto_array == NULL) { - ret = -ENOMEM; - goto out; - } - for (i = 0; i < MAX_NF_CT_PROTO; i++) - proto_array[i] = &nf_conntrack_generic_protocol; - - write_lock_bh(&nf_conntrack_lock); - if (nf_ct_protos[proto->l3proto]) { - /* bad timing, but no problem */ - write_unlock_bh(&nf_conntrack_lock); - kfree(proto_array); - } else { - nf_ct_protos[proto->l3proto] = proto_array; - write_unlock_bh(&nf_conntrack_lock); - } - - /* - * Just once because array is never freed until unloading - * nf_conntrack.ko - */ - goto retry; - } - - nf_ct_protos[proto->l3proto][proto->proto] = proto; - -out_unlock: - write_unlock_bh(&nf_conntrack_lock); -out: - return ret; -} - -void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) -{ - write_lock_bh(&nf_conntrack_lock); - nf_ct_protos[proto->l3proto][proto->proto] - = &nf_conntrack_generic_protocol; - write_unlock_bh(&nf_conntrack_lock); - - /* Somebody could be still looking at the proto in bh. */ - synchronize_net(); - - /* Remove all contrack entries for this protocol */ - nf_ct_iterate_cleanup(kill_proto, proto); -} - static int __init nf_conntrack_standalone_init(void) { #ifdef CONFIG_PROC_FS -- cgit v1.2.3-70-g09d2 From e2b7606cdb602a4f69c02cfc8bebe9c63b595e24 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:04 +0100 Subject: [NETFILTER]: More __read_mostly annotations Place rarely written variables in the read-mostly section by using __read_mostly Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- net/netfilter/core.c | 4 ++-- net/netfilter/nf_conntrack_core.c | 4 ++-- net/netfilter/nf_conntrack_helper.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 17f9e1cbc73b..291b8c6862f1 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -28,7 +28,7 @@ static DEFINE_SPINLOCK(afinfo_lock); -struct nf_afinfo *nf_afinfo[NPROTO]; +struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly; EXPORT_SYMBOL(nf_afinfo); int nf_register_afinfo(struct nf_afinfo *afinfo) @@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_unregister_afinfo); * of skbuffs queued for userspace, and not deregister a hook unless * this is zero, but that sucks. Now, we simply check when the * packets come back: if the hook is gone, the packet is discarded. */ -struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]; +struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly; EXPORT_SYMBOL(nf_hooks); static DEFINE_SPINLOCK(nf_hook_lock); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 09c0e6311044..6607ed415861 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -73,10 +73,10 @@ DEFINE_RWLOCK(nf_conntrack_lock); atomic_t nf_conntrack_count = ATOMIC_INIT(0); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; -unsigned int nf_conntrack_htable_size __read_mostly = 0; +unsigned int nf_conntrack_htable_size __read_mostly; int nf_conntrack_max __read_mostly; struct list_head *nf_conntrack_hash __read_mostly; -struct nf_conn nf_conntrack_untracked; +struct nf_conn nf_conntrack_untracked __read_mostly; unsigned int nf_ct_log_invalid __read_mostly; LIST_HEAD(unconfirmed); static int nf_conntrack_vmalloc __read_mostly; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index ca044875a561..2af92204722b 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -30,7 +30,7 @@ #include #include -static LIST_HEAD(helpers); +static __read_mostly LIST_HEAD(helpers); struct nf_conntrack_helper * __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) -- cgit v1.2.3-70-g09d2 From 605dcad6c85226e6d43387917b329d65b95cef39 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:06 +0100 Subject: [NETFILTER]: nf_conntrack: rename struct nf_conntrack_protocol Rename 'struct nf_conntrack_protocol' to 'struct nf_conntrack_l4proto' in order to help distinguish it from 'struct nf_conntrack_l3proto'. It gets rather confusing with 'nf_conntrack_protocol'. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_core.h | 10 +- include/net/netfilter/nf_conntrack_l3proto.h | 4 +- include/net/netfilter/nf_conntrack_l4proto.h | 129 +++++++++++++++++++++++++ include/net/netfilter/nf_conntrack_protocol.h | 129 ------------------------- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 26 ++--- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 12 +-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 26 ++--- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 12 +-- net/netfilter/nf_conntrack_core.c | 46 ++++----- net/netfilter/nf_conntrack_ecache.c | 2 +- net/netfilter/nf_conntrack_expect.c | 2 +- net/netfilter/nf_conntrack_helper.c | 2 +- net/netfilter/nf_conntrack_l3proto_generic.c | 4 +- net/netfilter/nf_conntrack_netlink.c | 56 +++++------ net/netfilter/nf_conntrack_proto.c | 72 +++++++------- net/netfilter/nf_conntrack_proto_generic.c | 6 +- net/netfilter/nf_conntrack_proto_sctp.c | 26 ++--- net/netfilter/nf_conntrack_proto_tcp.c | 14 +-- net/netfilter/nf_conntrack_proto_udp.c | 14 +-- net/netfilter/nf_conntrack_standalone.c | 30 +++--- 20 files changed, 311 insertions(+), 311 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_l4proto.h delete mode 100644 include/net/netfilter/nf_conntrack_protocol.h (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 4676b492d635..7fdc72c01356 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include /* This header is used to share core functionality between the @@ -32,7 +32,7 @@ extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf); /* Like above, but you already have conntrack read lock. */ extern struct nf_conntrack_l3proto *__nf_ct_find_l3proto(u_int16_t l3proto); -struct nf_conntrack_protocol; +struct nf_conntrack_l4proto; extern int nf_ct_get_tuple(const struct sk_buff *skb, @@ -42,13 +42,13 @@ nf_ct_get_tuple(const struct sk_buff *skb, u_int8_t protonum, struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_protocol *protocol); + const struct nf_conntrack_l4proto *l4proto); extern int nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig, const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_protocol *protocol); + const struct nf_conntrack_l4proto *l4proto); /* Find a connection corresponding to a tuple. */ extern struct nf_conntrack_tuple_hash * @@ -76,7 +76,7 @@ extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb); int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_protocol *proto); + struct nf_conntrack_l4proto *proto); extern struct list_head *nf_conntrack_hash; extern struct list_head nf_conntrack_expect_list; diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index dac43b15a5b0..ffe23a1e0b97 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -96,13 +96,13 @@ 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_generic_l3proto; +extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic; static inline struct nf_conntrack_l3proto * __nf_ct_l3proto_find(u_int16_t l3proto) { if (unlikely(l3proto >= AF_MAX)) - return &nf_conntrack_generic_l3proto; + return &nf_conntrack_l3proto_generic; return nf_ct_l3protos[l3proto]; } diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h new file mode 100644 index 000000000000..0c6babd54396 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -0,0 +1,129 @@ +/* + * Header for use in defining a given L4 protocol for connection tracking. + * + * 16 Dec 2003: Yasuyuki Kozakai @USAGI + * - generalized L3 protocol dependent part. + * + * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h + */ + +#ifndef _NF_CONNTRACK_L4PROTO_H +#define _NF_CONNTRACK_L4PROTO_H +#include + +struct seq_file; +struct nfattr; + +struct nf_conntrack_l4proto +{ + /* Next pointer. */ + struct list_head list; + + /* L3 Protocol number. */ + u_int16_t l3proto; + + /* L4 Protocol number. */ + u_int8_t l4proto; + + /* Protocol name */ + const char *name; + + /* Try to fill in the third arg: dataoff is offset past network protocol + hdr. Return true if possible. */ + int (*pkt_to_tuple)(const struct sk_buff *skb, + unsigned int dataoff, + struct nf_conntrack_tuple *tuple); + + /* Invert the per-proto part of the tuple: ie. turn xmit into reply. + * Some packets can't be inverted: return 0 in that case. + */ + int (*invert_tuple)(struct nf_conntrack_tuple *inverse, + const struct nf_conntrack_tuple *orig); + + /* Print out the per-protocol part of the tuple. Return like seq_* */ + int (*print_tuple)(struct seq_file *s, + const struct nf_conntrack_tuple *); + + /* Print out the private part of the conntrack. */ + int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); + + /* Returns verdict for packet, or -1 for invalid. */ + int (*packet)(struct nf_conn *conntrack, + const struct sk_buff *skb, + unsigned int dataoff, + enum ip_conntrack_info ctinfo, + int pf, + unsigned int hooknum); + + /* Called when a new connection for this protocol found; + * returns TRUE if it's OK. If so, packet() called next. */ + int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb, + unsigned int dataoff); + + /* Called when a conntrack entry is destroyed */ + void (*destroy)(struct nf_conn *conntrack); + + int (*error)(struct sk_buff *skb, unsigned int dataoff, + enum ip_conntrack_info *ctinfo, + int pf, unsigned int hooknum); + + /* convert protoinfo to nfnetink attributes */ + int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa, + const struct nf_conn *ct); + + /* convert nfnetlink attributes to protoinfo */ + int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct); + + int (*tuple_to_nfattr)(struct sk_buff *skb, + const struct nf_conntrack_tuple *t); + int (*nfattr_to_tuple)(struct nfattr *tb[], + struct nf_conntrack_tuple *t); + + /* Module (if any) which this is connected to. */ + struct module *me; +}; + +/* Existing built-in protocols */ +extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; +extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; +extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; +extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; + +#define MAX_NF_CT_PROTO 256 +extern struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX]; + +extern struct nf_conntrack_l4proto * +__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto); + +extern struct nf_conntrack_l4proto * +nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t protocol); + +extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); + +/* Protocol registration. */ +extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); +extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); + +/* Generic netlink helpers */ +extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple); +extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[], + struct nf_conntrack_tuple *t); + +/* Log invalid packets */ +extern unsigned int nf_ct_log_invalid; + +#ifdef CONFIG_SYSCTL +#ifdef DEBUG_INVALID_PACKETS +#define LOG_INVALID(proto) \ + (nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) +#else +#define LOG_INVALID(proto) \ + ((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \ + && net_ratelimit()) +#endif +#else +#define LOG_INVALID(proto) 0 +#endif /* CONFIG_SYSCTL */ + +#endif /*_NF_CONNTRACK_PROTOCOL_H*/ diff --git a/include/net/netfilter/nf_conntrack_protocol.h b/include/net/netfilter/nf_conntrack_protocol.h deleted file mode 100644 index 1f33737fcea5..000000000000 --- a/include/net/netfilter/nf_conntrack_protocol.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Header for use in defining a given protocol for connection tracking. - * - * 16 Dec 2003: Yasuyuki Kozakai @USAGI - * - generalized L3 protocol dependent part. - * - * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h - */ - -#ifndef _NF_CONNTRACK_PROTOCOL_H -#define _NF_CONNTRACK_PROTOCOL_H -#include - -struct seq_file; -struct nfattr; - -struct nf_conntrack_protocol -{ - /* Next pointer. */ - struct list_head list; - - /* L3 Protocol number. */ - u_int16_t l3proto; - - /* Protocol number. */ - u_int8_t proto; - - /* Protocol name */ - const char *name; - - /* Try to fill in the third arg: dataoff is offset past network protocol - hdr. Return true if possible. */ - int (*pkt_to_tuple)(const struct sk_buff *skb, - unsigned int dataoff, - struct nf_conntrack_tuple *tuple); - - /* Invert the per-proto part of the tuple: ie. turn xmit into reply. - * Some packets can't be inverted: return 0 in that case. - */ - int (*invert_tuple)(struct nf_conntrack_tuple *inverse, - const struct nf_conntrack_tuple *orig); - - /* Print out the per-protocol part of the tuple. Return like seq_* */ - int (*print_tuple)(struct seq_file *s, - const struct nf_conntrack_tuple *); - - /* Print out the private part of the conntrack. */ - int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); - - /* Returns verdict for packet, or -1 for invalid. */ - int (*packet)(struct nf_conn *conntrack, - const struct sk_buff *skb, - unsigned int dataoff, - enum ip_conntrack_info ctinfo, - int pf, - unsigned int hooknum); - - /* Called when a new connection for this protocol found; - * returns TRUE if it's OK. If so, packet() called next. */ - int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb, - unsigned int dataoff); - - /* Called when a conntrack entry is destroyed */ - void (*destroy)(struct nf_conn *conntrack); - - int (*error)(struct sk_buff *skb, unsigned int dataoff, - enum ip_conntrack_info *ctinfo, - int pf, unsigned int hooknum); - - /* convert protoinfo to nfnetink attributes */ - int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa, - const struct nf_conn *ct); - - /* convert nfnetlink attributes to protoinfo */ - int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct); - - int (*tuple_to_nfattr)(struct sk_buff *skb, - const struct nf_conntrack_tuple *t); - int (*nfattr_to_tuple)(struct nfattr *tb[], - struct nf_conntrack_tuple *t); - - /* Module (if any) which this is connected to. */ - struct module *me; -}; - -/* Existing built-in protocols */ -extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6; -extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; -extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6; -extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; - -#define MAX_NF_CT_PROTO 256 -extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX]; - -extern struct nf_conntrack_protocol * -__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol); - -extern struct nf_conntrack_protocol * -nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol); - -extern void nf_ct_proto_put(struct nf_conntrack_protocol *p); - -/* Protocol registration. */ -extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto); -extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto); - -/* Generic netlink helpers */ -extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple); -extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[], - struct nf_conntrack_tuple *t); - -/* Log invalid packets */ -extern unsigned int nf_ct_log_invalid; - -#ifdef CONFIG_SYSCTL -#ifdef DEBUG_INVALID_PACKETS -#define LOG_INVALID(proto) \ - (nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) -#else -#define LOG_INVALID(proto) \ - ((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \ - && net_ratelimit()) -#endif -#else -#define LOG_INVALID(proto) 0 -#endif /* CONFIG_SYSCTL */ - -#endif /*_NF_CONNTRACK_PROTOCOL_H*/ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0af803df82b0..370df0fdb22b 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -429,9 +429,9 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .me = THIS_MODULE, }; -extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; -extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; -extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; +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; MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); MODULE_LICENSE("GPL"); @@ -448,19 +448,19 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) return ret; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); if (ret < 0) { printk("nf_conntrack_ipv4: can't register tcp.\n"); goto cleanup_sockopt; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4); if (ret < 0) { printk("nf_conntrack_ipv4: can't register udp.\n"); goto cleanup_tcp; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp); if (ret < 0) { printk("nf_conntrack_ipv4: can't register icmp.\n"); goto cleanup_udp; @@ -495,11 +495,11 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) cleanup_ipv4: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); cleanup_icmp: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); cleanup_udp: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); cleanup_tcp: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); cleanup_sockopt: nf_unregister_sockopt(&so_getorigdst); return ret; @@ -513,9 +513,9 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) #endif nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); nf_unregister_sockopt(&so_getorigdst); } diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 790f00d500c3..08223a57a44d 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; @@ -152,7 +152,7 @@ icmp_error_message(struct sk_buff *skb, struct icmphdr icmp; struct iphdr ip; } _in, *inside; - struct nf_conntrack_protocol *innerproto; + struct nf_conntrack_l4proto *innerproto; struct nf_conntrack_tuple_hash *h; int dataoff; @@ -170,7 +170,7 @@ icmp_error_message(struct sk_buff *skb, return -NF_ACCEPT; } - innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol); + innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); dataoff = skb->nh.iph->ihl*4 + 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, @@ -321,11 +321,11 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], } #endif -struct nf_conntrack_protocol nf_conntrack_protocol_icmp = +struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = { .list = { NULL, NULL }, .l3proto = PF_INET, - .proto = IPPROTO_ICMP, + .l4proto = IPPROTO_ICMP, .name = "icmp", .pkt_to_tuple = icmp_pkt_to_tuple, .invert_tuple = icmp_invert_tuple, @@ -343,4 +343,4 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp = #endif }; -EXPORT_SYMBOL(nf_conntrack_protocol_icmp); +EXPORT_SYMBOL(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 e5e53fff9e38..cdbba44017df 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -458,9 +458,9 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .me = THIS_MODULE, }; -extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6; -extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6; -extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; +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_frag6_init(void); extern void nf_ct_frag6_cleanup(void); @@ -479,19 +479,19 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) printk("nf_conntrack_ipv6: can't initialize frag6.\n"); return ret; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); if (ret < 0) { printk("nf_conntrack_ipv6: can't register tcp.\n"); goto cleanup_frag6; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp6); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); if (ret < 0) { printk("nf_conntrack_ipv6: can't register udp.\n"); goto cleanup_tcp; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmpv6); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); if (ret < 0) { printk("nf_conntrack_ipv6: can't register icmpv6.\n"); goto cleanup_udp; @@ -527,11 +527,11 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) cleanup_ipv6: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); cleanup_icmpv6: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); cleanup_udp: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); cleanup_tcp: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); cleanup_frag6: nf_ct_frag6_cleanup(); return ret; @@ -545,9 +545,9 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void) #endif nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); nf_ct_frag6_cleanup(); } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 34d447208ffd..2cdf225f162d 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -155,7 +155,7 @@ icmpv6_error_message(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h; struct icmp6hdr _hdr, *hp; unsigned int inip6off; - struct nf_conntrack_protocol *inproto; + struct nf_conntrack_l4proto *inproto; u_int8_t inprotonum; unsigned int inprotoff; @@ -185,7 +185,7 @@ icmpv6_error_message(struct sk_buff *skb, return -NF_ACCEPT; } - inproto = __nf_ct_proto_find(PF_INET6, inprotonum); + 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, @@ -301,10 +301,10 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[], } #endif -struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = { .l3proto = PF_INET6, - .proto = IPPROTO_ICMPV6, + .l4proto = IPPROTO_ICMPV6, .name = "icmpv6", .pkt_to_tuple = icmpv6_pkt_to_tuple, .invert_tuple = icmpv6_invert_tuple, @@ -320,4 +320,4 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 = #endif }; -EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6); +EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 6607ed415861..441a647b7847 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -54,7 +54,7 @@ #include #include -#include +#include #include #include #include @@ -256,7 +256,7 @@ nf_ct_get_tuple(const struct sk_buff *skb, u_int8_t protonum, struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_protocol *protocol) + const struct nf_conntrack_l4proto *l4proto) { NF_CT_TUPLE_U_BLANK(tuple); @@ -267,14 +267,14 @@ nf_ct_get_tuple(const struct sk_buff *skb, tuple->dst.protonum = protonum; tuple->dst.dir = IP_CT_DIR_ORIGINAL; - return protocol->pkt_to_tuple(skb, dataoff, tuple); + return l4proto->pkt_to_tuple(skb, dataoff, tuple); } int nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig, const struct nf_conntrack_l3proto *l3proto, - const struct nf_conntrack_protocol *protocol) + const struct nf_conntrack_l4proto *l4proto) { NF_CT_TUPLE_U_BLANK(inverse); @@ -285,7 +285,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, inverse->dst.dir = !orig->dst.dir; inverse->dst.protonum = orig->dst.protonum; - return protocol->invert_tuple(inverse, orig); + return l4proto->invert_tuple(inverse, orig); } static void @@ -305,7 +305,7 @@ destroy_conntrack(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; DEBUGP("destroy_conntrack(%p)\n", ct); NF_CT_ASSERT(atomic_read(&nfct->use) == 0); @@ -321,9 +321,9 @@ destroy_conntrack(struct nf_conntrack *nfct) if (l3proto && l3proto->destroy) l3proto->destroy(ct); - proto = __nf_ct_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); - if (proto && proto->destroy) - proto->destroy(ct); + l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); + if (l4proto && l4proto->destroy) + l4proto->destroy(ct); if (nf_conntrack_destroyed) nf_conntrack_destroyed(ct); @@ -647,7 +647,7 @@ void nf_conntrack_free(struct nf_conn *conntrack) static struct nf_conntrack_tuple_hash * init_conntrack(const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_protocol *protocol, + struct nf_conntrack_l4proto *l4proto, struct sk_buff *skb, unsigned int dataoff) { @@ -655,7 +655,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_expect *exp; - if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, protocol)) { + if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { DEBUGP("Can't invert tuple.\n"); return NULL; } @@ -666,7 +666,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, return (struct nf_conntrack_tuple_hash *)conntrack; } - if (!protocol->new(conntrack, skb, dataoff)) { + if (!l4proto->new(conntrack, skb, dataoff)) { nf_conntrack_free(conntrack); DEBUGP("init conntrack: can't track with proto module\n"); return NULL; @@ -718,7 +718,7 @@ resolve_normal_ct(struct sk_buff *skb, u_int16_t l3num, u_int8_t protonum, struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_protocol *proto, + struct nf_conntrack_l4proto *l4proto, int *set_reply, enum ip_conntrack_info *ctinfo) { @@ -728,7 +728,7 @@ resolve_normal_ct(struct sk_buff *skb, if (!nf_ct_get_tuple(skb, (unsigned int)(skb->nh.raw - skb->data), dataoff, l3num, protonum, &tuple, l3proto, - proto)) { + l4proto)) { DEBUGP("resolve_normal_ct: Can't get tuple\n"); return NULL; } @@ -736,7 +736,7 @@ resolve_normal_ct(struct sk_buff *skb, /* look for tuple match */ h = nf_conntrack_find_get(&tuple, NULL); if (!h) { - h = init_conntrack(&tuple, l3proto, proto, skb, dataoff); + h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff); if (!h) return NULL; if (IS_ERR(h)) @@ -774,7 +774,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) struct nf_conn *ct; enum ip_conntrack_info ctinfo; struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; unsigned int dataoff; u_int8_t protonum; int set_reply = 0; @@ -792,19 +792,19 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) return -ret; } - proto = __nf_ct_proto_find((u_int16_t)pf, protonum); + l4proto = __nf_ct_l4proto_find((u_int16_t)pf, protonum); /* It may be an special packet, error, unclean... * inverse of the return code tells to the netfilter * core what to do with the packet. */ - if (proto->error != NULL && - (ret = proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { + if (l4proto->error != NULL && + (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { NF_CT_STAT_INC(error); NF_CT_STAT_INC(invalid); return -ret; } - ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, proto, + ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto, &set_reply, &ctinfo); if (!ct) { /* Not valid part of a connection */ @@ -820,7 +820,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) NF_CT_ASSERT((*pskb)->nfct); - ret = proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum); + ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum); if (ret < 0) { /* Invalid: inverse of the return code tells * the netfilter core what to do */ @@ -842,7 +842,7 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, { return nf_ct_invert_tuple(inverse, orig, __nf_ct_l3proto_find(orig->src.l3num), - __nf_ct_proto_find(orig->src.l3num, + __nf_ct_l4proto_find(orig->src.l3num, orig->dst.protonum)); } @@ -1199,7 +1199,7 @@ int __init nf_conntrack_init(void) /* Don't NEED lock here, but good form anyway. */ write_lock_bh(&nf_conntrack_lock); for (i = 0; i < PF_MAX; i++) - nf_ct_l3protos[i] = &nf_conntrack_generic_l3proto; + nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); /* For use by REJECT target */ diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 35763e96fddb..5152efd511d0 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 076e678b3188..7269bffd8e49 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -338,7 +338,7 @@ static int exp_seq_show(struct seq_file *s, void *v) expect->tuple.dst.protonum); print_tuple(s, &expect->tuple, __nf_ct_l3proto_find(expect->tuple.src.l3num), - __nf_ct_proto_find(expect->tuple.src.l3num, + __nf_ct_l4proto_find(expect->tuple.src.l3num, expect->tuple.dst.protonum)); return seq_putc(s, '\n'); } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 2af92204722b..5cbe55f66c15 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 21e0bc91cf23..1852c9d927d8 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -84,7 +84,7 @@ static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple) return NF_CT_F_BASIC; } -struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = { +struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { .l3proto = PF_UNSPEC, .name = "unknown", .pkt_to_tuple = generic_pkt_to_tuple, diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c3d53d91929f..dc0830220130 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include @@ -51,15 +51,15 @@ static char __initdata version[] = "0.93"; static inline int ctnetlink_dump_tuples_proto(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, - struct nf_conntrack_protocol *proto) + struct nf_conntrack_l4proto *l4proto) { int ret = 0; struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); - if (likely(proto->tuple_to_nfattr)) - ret = proto->tuple_to_nfattr(skb, tuple); + if (likely(l4proto->tuple_to_nfattr)) + ret = l4proto->tuple_to_nfattr(skb, tuple); NFA_NEST_END(skb, nest_parms); @@ -94,7 +94,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb, { int ret; struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto); @@ -103,9 +103,9 @@ ctnetlink_dump_tuples(struct sk_buff *skb, if (unlikely(ret < 0)) return ret; - proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); - ret = ctnetlink_dump_tuples_proto(skb, tuple, proto); - nf_ct_proto_put(proto); + l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); + ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto); + nf_ct_l4proto_put(l4proto); return ret; } @@ -142,27 +142,27 @@ nfattr_failure: static inline int ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) { - struct nf_conntrack_protocol *proto = nf_ct_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); + struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); struct nfattr *nest_proto; int ret; - if (!proto->to_nfattr) { - nf_ct_proto_put(proto); + if (!l4proto->to_nfattr) { + nf_ct_l4proto_put(l4proto); return 0; } nest_proto = NFA_NEST(skb, CTA_PROTOINFO); - ret = proto->to_nfattr(skb, nest_proto, ct); + ret = l4proto->to_nfattr(skb, nest_proto, ct); - nf_ct_proto_put(proto); + nf_ct_l4proto_put(l4proto); NFA_NEST_END(skb, nest_proto); return ret; nfattr_failure: - nf_ct_proto_put(proto); + nf_ct_l4proto_put(l4proto); return -1; } @@ -493,7 +493,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, struct nf_conntrack_tuple *tuple) { struct nfattr *tb[CTA_PROTO_MAX]; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; int ret = 0; nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); @@ -505,12 +505,12 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, return -EINVAL; tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]); - proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); + l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); - if (likely(proto->nfattr_to_tuple)) - ret = proto->nfattr_to_tuple(tb, tuple); + if (likely(l4proto->nfattr_to_tuple)) + ret = l4proto->nfattr_to_tuple(tb, tuple); - nf_ct_proto_put(proto); + nf_ct_l4proto_put(l4proto); return ret; } @@ -890,18 +890,18 @@ static inline int ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[]) { struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1]; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; int err = 0; nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); - proto = nf_ct_proto_find_get(l3num, npt); + l4proto = nf_ct_l4proto_find_get(l3num, npt); - if (proto->from_nfattr) - err = proto->from_nfattr(tb, ct); - nf_ct_proto_put(proto); + if (l4proto->from_nfattr) + err = l4proto->from_nfattr(tb, ct); + nf_ct_l4proto_put(l4proto); return err; } @@ -1081,7 +1081,7 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb, { int ret; struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); @@ -1091,9 +1091,9 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb, if (unlikely(ret < 0)) goto nfattr_failure; - proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); - ret = ctnetlink_dump_tuples_proto(skb, mask, proto); - nf_ct_proto_put(proto); + l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); + ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto); + nf_ct_l4proto_put(l4proto); if (unlikely(ret < 0)) goto nfattr_failure; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 24c61a384716..330b9acc62d8 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -24,38 +24,38 @@ #include #include -#include +#include #include -struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; +struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly; struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; -struct nf_conntrack_protocol * -__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) +struct nf_conntrack_l4proto * +__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) { if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) - return &nf_conntrack_generic_protocol; + return &nf_conntrack_l4proto_generic; - return nf_ct_protos[l3proto][protocol]; + return nf_ct_protos[l3proto][l4proto]; } /* this is guaranteed to always return a valid protocol helper, since * it falls back to generic_protocol */ -struct nf_conntrack_protocol * -nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) +struct nf_conntrack_l4proto * +nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto) { - struct nf_conntrack_protocol *p; + struct nf_conntrack_l4proto *p; preempt_disable(); - p = __nf_ct_proto_find(l3proto, protocol); + p = __nf_ct_l4proto_find(l3proto, l4proto); if (!try_module_get(p->me)) - p = &nf_conntrack_generic_protocol; + p = &nf_conntrack_l4proto_generic; preempt_enable(); return p; } -void nf_ct_proto_put(struct nf_conntrack_protocol *p) +void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p) { module_put(p->me); } @@ -68,7 +68,7 @@ nf_ct_l3proto_find_get(u_int16_t l3proto) preempt_disable(); p = __nf_ct_l3proto_find(l3proto); if (!try_module_get(p->me)) - p = &nf_conntrack_generic_l3proto; + p = &nf_conntrack_l3proto_generic; preempt_enable(); return p; @@ -86,7 +86,7 @@ nf_ct_l3proto_try_module_get(unsigned short l3proto) struct nf_conntrack_l3proto *p; retry: p = nf_ct_l3proto_find_get(l3proto); - if (p == &nf_conntrack_generic_l3proto) { + if (p == &nf_conntrack_l3proto_generic) { ret = request_module("nf_conntrack-%d", l3proto); if (!ret) goto retry; @@ -114,14 +114,14 @@ static int kill_l3proto(struct nf_conn *i, void *data) ((struct nf_conntrack_l3proto *)data)->l3proto); } -static int kill_proto(struct nf_conn *i, void *data) +static int kill_l4proto(struct nf_conn *i, void *data) { - struct nf_conntrack_protocol *proto; - proto = (struct nf_conntrack_protocol *)data; + struct nf_conntrack_l4proto *l4proto; + l4proto = (struct nf_conntrack_l4proto *)data; return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == - proto->proto) && + l4proto->l4proto) && (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == - proto->l3proto); + l4proto->l3proto); } int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) @@ -129,7 +129,7 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) int ret = 0; write_lock_bh(&nf_conntrack_lock); - if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) { + if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { ret = -EBUSY; goto out; } @@ -143,7 +143,7 @@ out: void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) { write_lock_bh(&nf_conntrack_lock); - nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto; + nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); /* Somebody could be still looking at the proto in bh. */ @@ -155,43 +155,43 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) /* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */ -int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto) +int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; retry: write_lock_bh(&nf_conntrack_lock); - if (nf_ct_protos[proto->l3proto]) { - if (nf_ct_protos[proto->l3proto][proto->proto] - != &nf_conntrack_generic_protocol) { + if (nf_ct_protos[l4proto->l3proto]) { + if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] + != &nf_conntrack_l4proto_generic) { ret = -EBUSY; goto out_unlock; } } else { /* l3proto may be loaded latter. */ - struct nf_conntrack_protocol **proto_array; + struct nf_conntrack_l4proto **proto_array; int i; write_unlock_bh(&nf_conntrack_lock); - proto_array = (struct nf_conntrack_protocol **) + proto_array = (struct nf_conntrack_l4proto **) kmalloc(MAX_NF_CT_PROTO * - sizeof(struct nf_conntrack_protocol *), + sizeof(struct nf_conntrack_l4proto *), GFP_KERNEL); if (proto_array == NULL) { ret = -ENOMEM; goto out; } for (i = 0; i < MAX_NF_CT_PROTO; i++) - proto_array[i] = &nf_conntrack_generic_protocol; + proto_array[i] = &nf_conntrack_l4proto_generic; write_lock_bh(&nf_conntrack_lock); - if (nf_ct_protos[proto->l3proto]) { + if (nf_ct_protos[l4proto->l3proto]) { /* bad timing, but no problem */ write_unlock_bh(&nf_conntrack_lock); kfree(proto_array); } else { - nf_ct_protos[proto->l3proto] = proto_array; + nf_ct_protos[l4proto->l3proto] = proto_array; write_unlock_bh(&nf_conntrack_lock); } @@ -202,7 +202,7 @@ retry: goto retry; } - nf_ct_protos[proto->l3proto][proto->proto] = proto; + nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto; out_unlock: write_unlock_bh(&nf_conntrack_lock); @@ -210,16 +210,16 @@ out: return ret; } -void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) +void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) { write_lock_bh(&nf_conntrack_lock); - nf_ct_protos[proto->l3proto][proto->proto] - = &nf_conntrack_generic_protocol; + nf_ct_protos[l4proto->l3proto][l4proto->l4proto] + = &nf_conntrack_l4proto_generic; write_unlock_bh(&nf_conntrack_lock); /* Somebody could be still looking at the proto in bh. */ synchronize_net(); /* Remove all contrack entries for this protocol */ - nf_ct_iterate_cleanup(kill_proto, proto); + nf_ct_iterate_cleanup(kill_l4proto, l4proto); } diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 26408bb0955b..f44811e0b475 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; @@ -71,10 +71,10 @@ static int new(struct nf_conn *conntrack, const struct sk_buff *skb, return 1; } -struct nf_conntrack_protocol nf_conntrack_generic_protocol = +struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = { .l3proto = PF_UNSPEC, - .proto = 0, + .l4proto = 0, .name = "unknown", .pkt_to_tuple = generic_pkt_to_tuple, .invert_tuple = generic_invert_tuple, diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index ba3e31f2acd7..5115619138e4 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #if 0 @@ -509,9 +509,9 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, return 1; } -struct nf_conntrack_protocol nf_conntrack_protocol_sctp4 = { +struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .l3proto = PF_INET, - .proto = IPPROTO_SCTP, + .l4proto = IPPROTO_SCTP, .name = "sctp", .pkt_to_tuple = sctp_pkt_to_tuple, .invert_tuple = sctp_invert_tuple, @@ -523,9 +523,9 @@ struct nf_conntrack_protocol nf_conntrack_protocol_sctp4 = { .me = THIS_MODULE }; -struct nf_conntrack_protocol nf_conntrack_protocol_sctp6 = { +struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { .l3proto = PF_INET6, - .proto = IPPROTO_SCTP, + .l4proto = IPPROTO_SCTP, .name = "sctp", .pkt_to_tuple = sctp_pkt_to_tuple, .invert_tuple = sctp_invert_tuple, @@ -625,14 +625,14 @@ int __init nf_conntrack_proto_sctp_init(void) { int ret; - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp4); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4); if (ret) { - printk("nf_conntrack_proto_sctp4: protocol register failed\n"); + printk("nf_conntrack_l4proto_sctp4: protocol register failed\n"); goto out; } - ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp6); + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6); if (ret) { - printk("nf_conntrack_proto_sctp6: protocol register failed\n"); + printk("nf_conntrack_l4proto_sctp6: protocol register failed\n"); goto cleanup_sctp4; } @@ -648,10 +648,10 @@ int __init nf_conntrack_proto_sctp_init(void) #ifdef CONFIG_SYSCTL cleanup: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); #endif cleanup_sctp4: - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); out: DEBUGP("SCTP conntrack module loading %s\n", ret ? "failed": "succeeded"); @@ -660,8 +660,8 @@ int __init nf_conntrack_proto_sctp_init(void) void __exit nf_conntrack_proto_sctp_fini(void) { - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6); - nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); #ifdef CONFIG_SYSCTL unregister_sysctl_table(nf_ct_sysctl_header); #endif diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index e6b6f23ecdd6..32b88b7efc46 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #if 0 @@ -1169,10 +1169,10 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct) } #endif -struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = { .l3proto = PF_INET, - .proto = IPPROTO_TCP, + .l4proto = IPPROTO_TCP, .name = "tcp", .pkt_to_tuple = tcp_pkt_to_tuple, .invert_tuple = tcp_invert_tuple, @@ -1190,10 +1190,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 = #endif }; -struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = { .l3proto = PF_INET6, - .proto = IPPROTO_TCP, + .l4proto = IPPROTO_TCP, .name = "tcp", .pkt_to_tuple = tcp_pkt_to_tuple, .invert_tuple = tcp_invert_tuple, @@ -1211,5 +1211,5 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 = #endif }; -EXPORT_SYMBOL(nf_conntrack_protocol_tcp4); -EXPORT_SYMBOL(nf_conntrack_protocol_tcp6); +EXPORT_SYMBOL(nf_conntrack_l4proto_tcp4); +EXPORT_SYMBOL(nf_conntrack_l4proto_tcp6); diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index cf9db035d39a..200d7d324362 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; @@ -148,10 +148,10 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, return NF_ACCEPT; } -struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = { .l3proto = PF_INET, - .proto = IPPROTO_UDP, + .l4proto = IPPROTO_UDP, .name = "udp", .pkt_to_tuple = udp_pkt_to_tuple, .invert_tuple = udp_invert_tuple, @@ -167,10 +167,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = #endif }; -struct nf_conntrack_protocol nf_conntrack_protocol_udp6 = +struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = { .l3proto = PF_INET6, - .proto = IPPROTO_UDP, + .l4proto = IPPROTO_UDP, .name = "udp", .pkt_to_tuple = udp_pkt_to_tuple, .invert_tuple = udp_invert_tuple, @@ -186,5 +186,5 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 = #endif }; -EXPORT_SYMBOL(nf_conntrack_protocol_udp4); -EXPORT_SYMBOL(nf_conntrack_protocol_udp6); +EXPORT_SYMBOL(nf_conntrack_l4proto_udp4); +EXPORT_SYMBOL(nf_conntrack_l4proto_udp6); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index eb031d20e510..6ebac7d9ee69 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -54,9 +54,9 @@ DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, - struct nf_conntrack_protocol *proto) + struct nf_conntrack_l4proto *l4proto) { - return l3proto->print_tuple(s, tuple) || proto->print_tuple(s, tuple); + return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple); } #ifdef CONFIG_NF_CT_ACCT @@ -135,7 +135,7 @@ static int ct_seq_show(struct seq_file *s, void *v) const struct nf_conntrack_tuple_hash *hash = v; const struct nf_conn *conntrack = nf_ct_tuplehash_to_ctrack(hash); struct nf_conntrack_l3proto *l3proto; - struct nf_conntrack_protocol *proto; + struct nf_conntrack_l4proto *l4proto; ASSERT_READ_LOCK(&nf_conntrack_lock); NF_CT_ASSERT(conntrack); @@ -148,16 +148,16 @@ static int ct_seq_show(struct seq_file *s, void *v) .tuple.src.l3num); NF_CT_ASSERT(l3proto); - proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + l4proto = __nf_ct_l4proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.src.l3num, conntrack->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.protonum); - NF_CT_ASSERT(proto); + NF_CT_ASSERT(l4proto); if (seq_printf(s, "%-8s %u %-8s %u %ld ", l3proto->name, conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, - proto->name, + l4proto->name, conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum, timer_pending(&conntrack->timeout) ? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0) @@ -166,11 +166,11 @@ static int ct_seq_show(struct seq_file *s, void *v) if (l3proto->print_conntrack(s, conntrack)) return -ENOSPC; - if (proto->print_conntrack(s, conntrack)) + if (l4proto->print_conntrack(s, conntrack)) return -ENOSPC; if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - l3proto, proto)) + l3proto, l4proto)) return -ENOSPC; if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL])) @@ -181,7 +181,7 @@ static int ct_seq_show(struct seq_file *s, void *v) return -ENOSPC; if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple, - l3proto, proto)) + l3proto, l4proto)) return -ENOSPC; if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY])) @@ -655,8 +655,8 @@ EXPORT_SYMBOL(nf_ct_l3proto_try_module_get); EXPORT_SYMBOL(nf_ct_l3proto_module_put); EXPORT_SYMBOL(nf_conntrack_l3proto_register); EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); -EXPORT_SYMBOL(nf_conntrack_protocol_register); -EXPORT_SYMBOL(nf_conntrack_protocol_unregister); +EXPORT_SYMBOL(nf_conntrack_l4proto_register); +EXPORT_SYMBOL(nf_conntrack_l4proto_unregister); EXPORT_SYMBOL(nf_ct_invert_tuplepr); EXPORT_SYMBOL(nf_conntrack_destroyed); EXPORT_SYMBOL(need_conntrack); @@ -665,9 +665,9 @@ EXPORT_SYMBOL(nf_conntrack_helper_unregister); EXPORT_SYMBOL(nf_ct_iterate_cleanup); EXPORT_SYMBOL(__nf_ct_refresh_acct); EXPORT_SYMBOL(nf_ct_protos); -EXPORT_SYMBOL(__nf_ct_proto_find); -EXPORT_SYMBOL(nf_ct_proto_find_get); -EXPORT_SYMBOL(nf_ct_proto_put); +EXPORT_SYMBOL(__nf_ct_l4proto_find); +EXPORT_SYMBOL(nf_ct_l4proto_find_get); +EXPORT_SYMBOL(nf_ct_l4proto_put); EXPORT_SYMBOL(nf_ct_l3proto_find_get); EXPORT_SYMBOL(nf_ct_l3proto_put); EXPORT_SYMBOL(nf_ct_l3protos); -- cgit v1.2.3-70-g09d2 From ae5718fb3dd0a11a4c9a061bf86417d52d58a6b3 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:08 +0100 Subject: [NETFILTER]: nf_conntrack: more sanity checks in protocol registration/unregistration Add some more sanity checks when registering/unregistering l3/l4 protocols. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l3proto.h | 2 +- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_proto.c | 55 +++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index ffe23a1e0b97..11b4b29bfab1 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -86,7 +86,7 @@ extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; /* Protocol registration. */ extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); -extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); +extern int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); extern struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 0c6babd54396..5193e4857b1b 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -102,7 +102,7 @@ extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); /* Protocol registration. */ extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); -extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); +extern int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); /* Generic netlink helpers */ extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 441a647b7847..73615d32a80c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1198,7 +1198,7 @@ int __init nf_conntrack_init(void) /* Don't NEED lock here, but good form anyway. */ write_lock_bh(&nf_conntrack_lock); - for (i = 0; i < PF_MAX; i++) + for (i = 0; i < AF_MAX; i++) nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 330b9acc62d8..a6a3b1ddd00d 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -28,7 +28,7 @@ #include struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly; -struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; +struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly; struct nf_conntrack_l4proto * __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) @@ -128,21 +128,40 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) { int ret = 0; + if (proto->l3proto >= AF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { ret = -EBUSY; - goto out; + goto out_unlock; } nf_ct_l3protos[proto->l3proto] = proto; -out: - write_unlock_bh(&nf_conntrack_lock); +out_unlock: + write_unlock_bh(&nf_conntrack_lock); +out: return ret; } -void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) +int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) { + int ret = 0; + + if (proto->l3proto >= AF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_l3protos[proto->l3proto] != proto) { + write_unlock_bh(&nf_conntrack_lock); + ret = -EBUSY; + goto out; + } + nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); @@ -151,6 +170,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l3proto, proto); + +out: + return ret; } /* FIXME: Allow NULL functions and sub in pointers to generic for @@ -159,6 +181,11 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; + if (l4proto->l3proto >= PF_MAX) { + ret = -EBUSY; + goto out; + } + retry: write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto]) { @@ -210,9 +237,22 @@ out: return ret; } -void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) +int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) { + int ret = 0; + + if (l4proto->l3proto >= PF_MAX) { + ret = -EBUSY; + goto out; + } + write_lock_bh(&nf_conntrack_lock); + if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] + != l4proto) { + write_unlock_bh(&nf_conntrack_lock); + ret = -EBUSY; + goto out; + } nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = &nf_conntrack_l4proto_generic; write_unlock_bh(&nf_conntrack_lock); @@ -222,4 +262,7 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l4proto, l4proto); + +out: + return ret; } -- cgit v1.2.3-70-g09d2 From 951d36cace3d3ad2ac6c222e126aed4113ad2bf7 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:09 +0100 Subject: [NETFILTER]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK Remove the usage of ASSERT_READ_LOCK/ASSERT_WRITE_LOCK in nf_conntrack, it didn't do anything, it was just an empty define and it uglified the code. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 7 ------- net/netfilter/nf_conntrack_standalone.c | 4 ---- 2 files changed, 11 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 73615d32a80c..ab161b7a76a3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -47,11 +47,6 @@ #include #include -/* This rwlock protects the main hash table, protocol/helper/expected - registrations, conntrack timers*/ -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) - #include #include #include @@ -292,7 +287,6 @@ static void clean_from_lists(struct nf_conn *ct) { DEBUGP("clean_from_lists(%p)\n", ct); - ASSERT_WRITE_LOCK(&nf_conntrack_lock); list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); @@ -371,7 +365,6 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple_hash *h; unsigned int hash = hash_conntrack(tuple); - ASSERT_READ_LOCK(&nf_conntrack_lock); list_for_each_entry(h, &nf_conntrack_hash[hash], list) { if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && nf_ct_tuple_equal(tuple, &h->tuple)) { diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 6ebac7d9ee69..f87d333b0c0c 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -29,9 +29,6 @@ #include #endif -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) - #include #include #include @@ -137,7 +134,6 @@ static int ct_seq_show(struct seq_file *s, void *v) struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; - ASSERT_READ_LOCK(&nf_conntrack_lock); NF_CT_ASSERT(conntrack); /* we only want to print DIR_ORIGINAL */ -- cgit v1.2.3-70-g09d2 From 3ffd5eeb1a031ad226c80ae6e658970cd08569e2 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:10 +0100 Subject: [NETFILTER]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup Minor whitespace cleanup. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ab161b7a76a3..355b330c214e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -877,9 +877,10 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, ct->counters[CTINFO2DIR(ctinfo)].packets++; ct->counters[CTINFO2DIR(ctinfo)].bytes += skb->len - (unsigned int)(skb->nh.raw - skb->data); - if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) - || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) - event |= IPCT_COUNTER_FILLING; + + if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) + || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) + event |= IPCT_COUNTER_FILLING; } #endif -- cgit v1.2.3-70-g09d2 From 824621eddd2087b0e6f0b2e0da91e8d77e4919bf Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:11 +0100 Subject: [NETFILTER]: nf_conntrack: remove unused struct list_head from protocols Remove unused struct list_head from struct nf_conntrack_l3proto and nf_conntrack_l4proto as all protocols are kept in arrays, not linked lists. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l3proto.h | 3 --- include/net/netfilter/nf_conntrack_l4proto.h | 3 --- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 1 - 3 files changed, 7 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 11b4b29bfab1..6364df059422 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -18,9 +18,6 @@ struct nfattr; struct nf_conntrack_l3proto { - /* Next pointer. */ - struct list_head list; - /* L3 Protocol Family number. ex) PF_INET */ u_int16_t l3proto; diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 5193e4857b1b..c22804aa227e 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -16,9 +16,6 @@ struct nfattr; struct nf_conntrack_l4proto { - /* Next pointer. */ - struct list_head list; - /* L3 Protocol number. */ u_int16_t l3proto; diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 08223a57a44d..95fc22b49694 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -323,7 +323,6 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = { - .list = { NULL, NULL }, .l3proto = PF_INET, .l4proto = IPPROTO_ICMP, .name = "icmp", -- cgit v1.2.3-70-g09d2 From be00c8e48993368663e2714bd1e7c886b7736406 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Wed, 29 Nov 2006 02:35:12 +0100 Subject: [NETFILTER]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct() Only update the conntrack timer if there's been at least HZ jiffies since the last update. Reduces the number of del_timer/add_timer cycles from one per packet to one per connection per second (plus once for each state change of a connection) Should handle timer wraparounds and connection timeout changes. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 355b330c214e..3e7c0a90003a 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -864,9 +864,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, ct->timeout.expires = extra_jiffies; event = IPCT_REFRESH; } else { - /* Need del_timer for race avoidance (may already be dying). */ - if (del_timer(&ct->timeout)) { - ct->timeout.expires = jiffies + extra_jiffies; + unsigned long newtime = jiffies + extra_jiffies; + + /* Only update the timeout if the new timeout is at least + HZ jiffies from the old timeout. Need del_timer for race + avoidance (may already be dying). */ + if (newtime - ct->timeout.expires >= HZ + && del_timer(&ct->timeout)) { + ct->timeout.expires = newtime; add_timer(&ct->timeout); event = IPCT_REFRESH; } -- cgit v1.2.3-70-g09d2 From d73468533451fd896324058d9ba649c11ba3e3ee Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:14 +0100 Subject: [NETFILTER]: nf_conntrack_ftp: fix missing helper mask initilization Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_ftp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 10836fc22a44..05cb78ca90ae 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -586,6 +586,7 @@ 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 = 0xFFFF; ftp[i][j].mask.dst.protonum = 0xFF; ftp[i][j].max_expected = 1; -- cgit v1.2.3-70-g09d2 From f8eb24a89afa12b48fa7e39775faea6d64b8e538 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:15 +0100 Subject: [NETFILTER]: nf_conntrack: move extern declaration to header files Using extern in a C file is a bad idea because the compiler can't catch type errors. Signed-off-by: Patrick McHardy --- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 4 ++++ include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 25 +++++++++++++++++++++++++ include/net/netfilter/nf_conntrack.h | 5 +++++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 ------ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 18 ------------------ net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 3 --- net/netfilter/nf_conntrack_expect.c | 1 - net/netfilter/nf_conntrack_l3proto_generic.c | 2 -- net/netfilter/nf_conntrack_standalone.c | 7 ------- 9 files changed, 34 insertions(+), 37 deletions(-) create mode 100644 include/net/netfilter/ipv6/nf_conntrack_ipv6.h (limited to 'net') diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 91684436af8e..8c4f7e89ce55 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -37,4 +37,8 @@ struct nf_conntrack_ipv4 { 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; +extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; + #endif /*_NF_CONNTRACK_IPV4_H*/ diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h new file mode 100644 index 000000000000..b4b6049e01fa --- /dev/null +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h @@ -0,0 +1,25 @@ +#ifndef _NF_CONNTRACK_IPV6_H +#define _NF_CONNTRACK_IPV6_H + +extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; + +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, + u8 *nexthdrp, int len); + +extern int nf_ct_frag6_init(void); +extern void nf_ct_frag6_cleanup(void); +extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb); +extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, + struct net_device *in, + struct net_device *out, + int (*okfn)(struct sk_buff *)); + +extern unsigned int nf_ct_frag6_timeout; +extern unsigned int nf_ct_frag6_low_thresh; +extern unsigned int nf_ct_frag6_high_thresh; + +#endif /* _NF_CONNTRACK_IPV6_H*/ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 9a2950551cd3..d0d0e6491448 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -79,6 +79,8 @@ struct nf_conn_help { #include +#include + struct nf_conn { /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, @@ -241,7 +243,10 @@ static inline int nf_ct_is_dying(struct nf_conn *ct) extern unsigned int nf_conntrack_htable_size; extern int nf_conntrack_checksum; +extern atomic_t nf_conntrack_count; +extern int nf_conntrack_max; +DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++) /* no helper, no nat */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 370df0fdb22b..d1907082d7d6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -38,8 +38,6 @@ #define DEBUGP(format, args...) #endif -DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat); - static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -429,10 +427,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .me = THIS_MODULE, }; -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; - MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); MODULE_LICENSE("GPL"); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index cdbba44017df..9108ecc22bea 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -43,8 +43,6 @@ #define DEBUGP(format, args...) #endif -DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); - static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { @@ -211,11 +209,6 @@ out: return nf_conntrack_confirm(pskb); } -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb); -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, - struct net_device *in, - struct net_device *out, - int (*okfn)(struct sk_buff *)); static unsigned int ipv6_defrag(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, @@ -335,11 +328,6 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { /* From nf_conntrack_proto_icmpv6.c */ extern unsigned int nf_ct_icmpv6_timeout; -/* From nf_conntrack_reasm.c */ -extern unsigned int nf_ct_frag6_timeout; -extern unsigned int nf_ct_frag6_low_thresh; -extern unsigned int nf_ct_frag6_high_thresh; - static struct ctl_table_header *nf_ct_ipv6_sysctl_header; static ctl_table nf_ct_sysctl_table[] = { @@ -458,12 +446,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .me = THIS_MODULE, }; -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_frag6_init(void); -extern void nf_ct_frag6_cleanup(void); - MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI "); diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 2cdf225f162d..b3b468c0ef7a 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -142,9 +142,6 @@ static int icmpv6_new(struct nf_conn *conntrack, return 1; } -extern int -nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len); -extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; static int icmpv6_error_message(struct sk_buff *skb, unsigned int icmp6off, diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 7269bffd8e49..79cfd79a42f0 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -28,7 +28,6 @@ LIST_HEAD(nf_conntrack_expect_list); kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; -DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); static unsigned int nf_conntrack_expect_next_id; /* nf_conntrack_expect helper functions */ diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 1852c9d927d8..3124b3a30102 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -37,8 +37,6 @@ #define DEBUGP(format, args...) #endif -DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat); - 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_standalone.c b/net/netfilter/nf_conntrack_standalone.c index f87d333b0c0c..2283a2686949 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -44,9 +44,6 @@ MODULE_LICENSE("GPL"); -extern atomic_t nf_conntrack_count; -DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); - #ifdef CONFIG_PROC_FS int print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, @@ -334,10 +331,6 @@ int nf_conntrack_checksum __read_mostly = 1; #ifdef CONFIG_SYSCTL -/* From nf_conntrack_core.c */ -extern int nf_conntrack_max; -extern unsigned int nf_conntrack_htable_size; - /* From nf_conntrack_proto_tcp.c */ extern unsigned int nf_ct_tcp_timeout_syn_sent; extern unsigned int nf_ct_tcp_timeout_syn_recv; -- cgit v1.2.3-70-g09d2 From d62f9ed4a490309bd9e5df0b42ba5d096e7b5902 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:17 +0100 Subject: [NETFILTER]: nf_conntrack: automatic sysctl registation for conntrack protocols Add helper functions for sysctl registration with optional instantiating of common path elements (like net/netfilter) and use it for support for automatic registation of conntrack protocol sysctls. Signed-off-by: Patrick McHardy --- include/linux/netfilter.h | 10 ++ include/net/netfilter/nf_conntrack_l3proto.h | 6 ++ include/net/netfilter/nf_conntrack_l4proto.h | 6 ++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_proto.c | 102 ++++++++++++++++++++ net/netfilter/nf_sysctl.c | 134 +++++++++++++++++++++++++++ 6 files changed, 259 insertions(+) create mode 100644 net/netfilter/nf_sysctl.c (limited to 'net') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 6ab5e2d6133e..f6f3fcbd70ed 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -117,6 +117,16 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); int nf_register_sockopt(struct nf_sockopt_ops *reg); void nf_unregister_sockopt(struct nf_sockopt_ops *reg); +#ifdef CONFIG_SYSCTL +/* Sysctl registration */ +struct ctl_table_header *nf_register_sysctl_table(struct ctl_table *path, + struct ctl_table *table); +void nf_unregister_sysctl_table(struct ctl_table_header *header, + struct ctl_table *table); +extern struct ctl_table nf_net_netfilter_sysctl_path[]; +extern struct ctl_table nf_net_ipv4_netfilter_sysctl_path[]; +#endif /* CONFIG_SYSCTL */ + extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]; /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 6364df059422..664ddcffe00d 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -75,6 +75,12 @@ struct nf_conntrack_l3proto int (*nfattr_to_tuple)(struct nfattr *tb[], struct nf_conntrack_tuple *t); +#ifdef CONFIG_SYSCTL + struct ctl_table_header *ctl_table_header; + struct ctl_table *ctl_table_path; + struct ctl_table *ctl_table; +#endif /* CONFIG_SYSCTL */ + /* Module (if any) which this is connected to. */ struct module *me; }; diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index c22804aa227e..fe1e8fa30d2f 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -76,6 +76,12 @@ struct nf_conntrack_l4proto int (*nfattr_to_tuple)(struct nfattr *tb[], struct nf_conntrack_tuple *t); +#ifdef CONFIG_SYSCTL + struct ctl_table_header **ctl_table_header; + struct ctl_table *ctl_table; + unsigned int *ctl_table_users; +#endif /* CONFIG_SYSCTL */ + /* Module (if any) which this is connected to. */ struct module *me; }; diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 627105df1040..84d529ded952 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -4,6 +4,7 @@ nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_exp nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o obj-$(CONFIG_NETFILTER) = netfilter.o +obj-$(CONFIG_SYSCTL) += nf_sysctl.o obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index a6a3b1ddd00d..941b5c3754af 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,34 @@ struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly; struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly; +#ifdef CONFIG_SYSCTL +static DEFINE_MUTEX(nf_ct_proto_sysctl_mutex); + +static int +nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path, + struct ctl_table *table, unsigned int *users) +{ + if (*header == NULL) { + *header = nf_register_sysctl_table(path, table); + if (*header == NULL) + return -ENOMEM; + } + if (users != NULL) + (*users)++; + return 0; +} + +static void +nf_ct_unregister_sysctl(struct ctl_table_header **header, + struct ctl_table *table, unsigned int *users) +{ + if (users != NULL && --*users > 0) + return; + nf_unregister_sysctl_table(*header, table); + *header = NULL; +} +#endif + struct nf_conntrack_l4proto * __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) { @@ -124,6 +153,33 @@ static int kill_l4proto(struct nf_conn *i, void *data) l4proto->l3proto); } +static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto) +{ + int err = 0; + +#ifdef CONFIG_SYSCTL + mutex_lock(&nf_ct_proto_sysctl_mutex); + if (l3proto->ctl_table != NULL) { + err = nf_ct_register_sysctl(&l3proto->ctl_table_header, + l3proto->ctl_table_path, + l3proto->ctl_table, NULL); + } + mutex_unlock(&nf_ct_proto_sysctl_mutex); +#endif + return err; +} + +static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto) +{ +#ifdef CONFIG_SYSCTL + mutex_lock(&nf_ct_proto_sysctl_mutex); + if (l3proto->ctl_table_header != NULL) + nf_ct_unregister_sysctl(&l3proto->ctl_table_header, + l3proto->ctl_table, NULL); + mutex_unlock(&nf_ct_proto_sysctl_mutex); +#endif +} + int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) { int ret = 0; @@ -139,6 +195,12 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) goto out_unlock; } nf_ct_l3protos[proto->l3proto] = proto; + write_unlock_bh(&nf_conntrack_lock); + + ret = nf_ct_l3proto_register_sysctl(proto); + if (ret < 0) + nf_conntrack_l3proto_unregister(proto); + return ret; out_unlock: write_unlock_bh(&nf_conntrack_lock); @@ -165,6 +227,8 @@ int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic; write_unlock_bh(&nf_conntrack_lock); + nf_ct_l3proto_unregister_sysctl(proto); + /* Somebody could be still looking at the proto in bh. */ synchronize_net(); @@ -175,6 +239,36 @@ out: return ret; } +static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) +{ + int err = 0; + +#ifdef CONFIG_SYSCTL + mutex_lock(&nf_ct_proto_sysctl_mutex); + if (l4proto->ctl_table != NULL) { + err = nf_ct_register_sysctl(l4proto->ctl_table_header, + nf_net_netfilter_sysctl_path, + l4proto->ctl_table, + l4proto->ctl_table_users); + } + mutex_unlock(&nf_ct_proto_sysctl_mutex); +#endif + return err; +} + +static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto) +{ +#ifdef CONFIG_SYSCTL + mutex_lock(&nf_ct_proto_sysctl_mutex); + if (l4proto->ctl_table_header != NULL && + *l4proto->ctl_table_header != NULL) + nf_ct_unregister_sysctl(l4proto->ctl_table_header, + l4proto->ctl_table, + l4proto->ctl_table_users); + mutex_unlock(&nf_ct_proto_sysctl_mutex); +#endif +} + /* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) @@ -230,6 +324,12 @@ retry: } nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto; + write_unlock_bh(&nf_conntrack_lock); + + ret = nf_ct_l4proto_register_sysctl(l4proto); + if (ret < 0) + nf_conntrack_l4proto_unregister(l4proto); + return ret; out_unlock: write_unlock_bh(&nf_conntrack_lock); @@ -257,6 +357,8 @@ int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) = &nf_conntrack_l4proto_generic; write_unlock_bh(&nf_conntrack_lock); + nf_ct_l4proto_unregister_sysctl(l4proto); + /* Somebody could be still looking at the proto in bh. */ synchronize_net(); diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c new file mode 100644 index 000000000000..06ddddb2911f --- /dev/null +++ b/net/netfilter/nf_sysctl.c @@ -0,0 +1,134 @@ +/* nf_sysctl.c netfilter sysctl registration/unregistation + * + * Copyright (c) 2006 Patrick McHardy + */ +#include +#include +#include +#include + +static void +path_free(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table *t, *next; + + for (t = path; t != NULL && t != table; t = next) { + next = t->child; + kfree(t); + } +} + +static struct ctl_table * +path_dup(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table *t, *last = NULL, *tmp; + + for (t = path; t != NULL; t = t->child) { + /* twice the size since path elements are terminated by an + * empty element */ + tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL); + if (tmp == NULL) { + if (last != NULL) + path_free(path, table); + return NULL; + } + + if (last != NULL) + last->child = tmp; + else + path = tmp; + last = tmp; + } + + if (last != NULL) + last->child = table; + else + path = table; + + return path; +} + +struct ctl_table_header * +nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table_header *header; + + path = path_dup(path, table); + if (path == NULL) + return NULL; + header = register_sysctl_table(path, 0); + if (header == NULL) + path_free(path, table); + return header; +} +EXPORT_SYMBOL_GPL(nf_register_sysctl_table); + +void +nf_unregister_sysctl_table(struct ctl_table_header *header, + struct ctl_table *table) +{ + struct ctl_table *path = header->ctl_table; + + unregister_sysctl_table(header); + path_free(path, table); +} +EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table); + +/* net/netfilter */ +static struct ctl_table nf_net_netfilter_table[] = { + { + .ctl_name = NET_NETFILTER, + .procname = "netfilter", + .mode = 0555, + }, + { + .ctl_name = 0 + } +}; +struct ctl_table nf_net_netfilter_sysctl_path[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = nf_net_netfilter_table, + }, + { + .ctl_name = 0 + } +}; +EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path); + +/* net/ipv4/netfilter */ +static struct ctl_table nf_net_ipv4_netfilter_table[] = { + { + .ctl_name = NET_IPV4_NETFILTER, + .procname = "netfilter", + .mode = 0555, + }, + { + .ctl_name = 0 + } +}; +static struct ctl_table nf_net_ipv4_table[] = { + { + .ctl_name = NET_IPV4, + .procname = "ipv4", + .mode = 0555, + .child = nf_net_ipv4_netfilter_table, + }, + { + .ctl_name = 0 + } +}; +struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = nf_net_ipv4_table, + }, + { + .ctl_name = 0 + } +}; +EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path); -- cgit v1.2.3-70-g09d2 From 933a41e7e12b773d1dd026018f02b86b5d257a22 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:18 +0100 Subject: [NETFILTER]: nf_conntrack: move conntrack protocol sysctls to individual modules Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 53 --------- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 23 +++- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 55 +--------- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 23 +++- net/netfilter/nf_conntrack_core.c | 8 ++ net/netfilter/nf_conntrack_proto.c | 12 ++- net/netfilter/nf_conntrack_proto_generic.c | 23 +++- net/netfilter/nf_conntrack_proto_sctp.c | 101 +++++++----------- net/netfilter/nf_conntrack_proto_tcp.c | 140 +++++++++++++++++++++--- net/netfilter/nf_conntrack_proto_udp.c | 40 ++++++- net/netfilter/nf_conntrack_standalone.c | 142 ------------------------- 11 files changed, 293 insertions(+), 327 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index d1907082d7d6..786c4ce96cdf 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -266,44 +266,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] = { }, }; -#ifdef CONFIG_SYSCTL -/* From nf_conntrack_proto_icmp.c */ -extern unsigned int nf_ct_icmp_timeout; -static struct ctl_table_header *nf_ct_ipv4_sysctl_header; - -static ctl_table nf_ct_sysctl_table[] = { - { - .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT, - .procname = "nf_conntrack_icmp_timeout", - .data = &nf_ct_icmp_timeout, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { .ctl_name = 0 } -}; - -static ctl_table nf_ct_netfilter_table[] = { - { - .ctl_name = NET_NETFILTER, - .procname = "netfilter", - .mode = 0555, - .child = nf_ct_sysctl_table, - }, - { .ctl_name = 0 } -}; - -static ctl_table nf_ct_net_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = nf_ct_netfilter_table, - }, - { .ctl_name = 0 } -}; -#endif - /* Fast function for those who don't want to parse /proc (and I don't blame them). */ /* Reversing the socket's dst/src point of view gives us the reply @@ -472,20 +434,8 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) printk("nf_conntrack_ipv4: can't register hooks.\n"); goto cleanup_ipv4; } -#ifdef CONFIG_SYSCTL - nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); - if (nf_ct_ipv4_sysctl_header == NULL) { - printk("nf_conntrack: can't register to sysctl.\n"); - ret = -ENOMEM; - goto cleanup_hooks; - } -#endif return ret; -#ifdef CONFIG_SYSCTL - cleanup_hooks: - nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); -#endif cleanup_ipv4: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); cleanup_icmp: @@ -502,9 +452,6 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) static void __exit nf_conntrack_l3proto_ipv4_fini(void) { synchronize_net(); -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_ipv4_sysctl_header); -#endif nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 95fc22b49694..c59f28193a39 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -25,7 +25,7 @@ #include #include -unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; +static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; #if 0 #define DEBUGP printk @@ -321,6 +321,23 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], } #endif +#ifdef CONFIG_SYSCTL +static struct ctl_table_header *icmp_sysctl_header; +static struct ctl_table icmp_sysctl_table[] = { + { + .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT, + .procname = "nf_conntrack_icmp_timeout", + .data = &nf_ct_icmp_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL */ + struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = { .l3proto = PF_INET, @@ -340,6 +357,10 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = .tuple_to_nfattr = icmp_tuple_to_nfattr, .nfattr_to_tuple = icmp_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_header = &icmp_sysctl_header, + .ctl_table = icmp_sysctl_table, +#endif }; EXPORT_SYMBOL(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 9108ecc22bea..a20615ffccff 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -324,21 +324,7 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { }; #ifdef CONFIG_SYSCTL - -/* From nf_conntrack_proto_icmpv6.c */ -extern unsigned int nf_ct_icmpv6_timeout; - -static struct ctl_table_header *nf_ct_ipv6_sysctl_header; - -static ctl_table nf_ct_sysctl_table[] = { - { - .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT, - .procname = "nf_conntrack_icmpv6_timeout", - .data = &nf_ct_icmpv6_timeout, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, +static ctl_table nf_ct_ipv6_sysctl_table[] = { { .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, .procname = "nf_conntrack_frag6_timeout", @@ -365,26 +351,6 @@ static ctl_table nf_ct_sysctl_table[] = { }, { .ctl_name = 0 } }; - -static ctl_table nf_ct_netfilter_table[] = { - { - .ctl_name = NET_NETFILTER, - .procname = "netfilter", - .mode = 0555, - .child = nf_ct_sysctl_table, - }, - { .ctl_name = 0 } -}; - -static ctl_table nf_ct_net_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = nf_ct_netfilter_table, - }, - { .ctl_name = 0 } -}; #endif #if defined(CONFIG_NF_CT_NETLINK) || \ @@ -441,6 +407,10 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv6_tuple_to_nfattr, .nfattr_to_tuple = ipv6_nfattr_to_tuple, +#endif +#ifdef CONFIG_SYSCTL + .ctl_table_path = nf_net_netfilter_sysctl_path, + .ctl_table = nf_ct_ipv6_sysctl_table, #endif .get_features = ipv6_get_features, .me = THIS_MODULE, @@ -492,20 +462,8 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) "hook.\n"); goto cleanup_ipv6; } -#ifdef CONFIG_SYSCTL - nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); - if (nf_ct_ipv6_sysctl_header == NULL) { - printk("nf_conntrack: can't register to sysctl.\n"); - ret = -ENOMEM; - goto cleanup_hooks; - } -#endif return ret; -#ifdef CONFIG_SYSCTL - cleanup_hooks: - nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); -#endif cleanup_ipv6: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); cleanup_icmpv6: @@ -522,9 +480,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) static void __exit nf_conntrack_l3proto_ipv6_fini(void) { synchronize_net(); -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_ipv6_sysctl_header); -#endif nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index b3b468c0ef7a..1e8e700f6135 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -33,7 +33,7 @@ #include #include -unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; +static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; #if 0 #define DEBUGP printk @@ -298,6 +298,23 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[], } #endif +#ifdef CONFIG_SYSCTL +static struct ctl_table_header *icmpv6_sysctl_header; +static struct ctl_table icmpv6_sysctl_table[] = { + { + .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT, + .procname = "nf_conntrack_icmpv6_timeout", + .data = &nf_ct_icmpv6_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL */ + struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = { .l3proto = PF_INET6, @@ -315,6 +332,10 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .tuple_to_nfattr = icmpv6_tuple_to_nfattr, .nfattr_to_tuple = icmpv6_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_header = &icmpv6_sysctl_header, + .ctl_table = icmpv6_sysctl_table, +#endif }; EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3e7c0a90003a..4b972791149d 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1070,6 +1070,8 @@ void nf_conntrack_cleanup(void) free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, nf_conntrack_htable_size); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_generic); + /* free l3proto protocol tables */ for (i = 0; i < PF_MAX; i++) if (nf_ct_protos[i]) { @@ -1195,6 +1197,10 @@ int __init nf_conntrack_init(void) goto err_free_conntrack_slab; } + ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_generic); + if (ret < 0) + goto out_free_expect_slab; + /* Don't NEED lock here, but good form anyway. */ write_lock_bh(&nf_conntrack_lock); for (i = 0; i < AF_MAX; i++) @@ -1212,6 +1218,8 @@ int __init nf_conntrack_init(void) return ret; +out_free_expect_slab: + kmem_cache_destroy(nf_conntrack_expect_cachep); err_free_conntrack_slab: nf_conntrack_unregister_cache(NF_CT_F_BASIC); err_free_hash: diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 941b5c3754af..891c9c56c319 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -252,7 +252,7 @@ static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) l4proto->ctl_table_users); } mutex_unlock(&nf_ct_proto_sysctl_mutex); -#endif +#endif /* CONFIG_SYSCTL */ return err; } @@ -266,7 +266,7 @@ static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto l4proto->ctl_table, l4proto->ctl_table_users); mutex_unlock(&nf_ct_proto_sysctl_mutex); -#endif +#endif /* CONFIG_SYSCTL */ } /* FIXME: Allow NULL functions and sub in pointers to generic for @@ -280,6 +280,9 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) goto out; } + if (l4proto == &nf_conntrack_l4proto_generic) + return nf_ct_l4proto_register_sysctl(l4proto); + retry: write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto]) { @@ -346,6 +349,11 @@ int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) goto out; } + if (l4proto == &nf_conntrack_l4proto_generic) { + nf_ct_l4proto_unregister_sysctl(l4proto); + goto out; + } + write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto) { diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index f44811e0b475..15306b952510 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -17,7 +17,7 @@ #include #include -unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; +static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, @@ -71,6 +71,23 @@ static int new(struct nf_conn *conntrack, const struct sk_buff *skb, return 1; } +#ifdef CONFIG_SYSCTL +static struct ctl_table_header *generic_sysctl_header; +static struct ctl_table generic_sysctl_table[] = { + { + .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT, + .procname = "nf_conntrack_generic_timeout", + .data = &nf_ct_generic_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL */ + struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = { .l3proto = PF_UNSPEC, @@ -82,4 +99,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = .print_conntrack = generic_print_conntrack, .packet = packet, .new = new, +#ifdef CONFIG_SYSCTL + .ctl_table_header = &generic_sysctl_header, + .ctl_table = generic_sysctl_table, +#endif }; diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 5115619138e4..cc693308878f 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -509,36 +509,10 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, return 1; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { - .l3proto = PF_INET, - .l4proto = IPPROTO_SCTP, - .name = "sctp", - .pkt_to_tuple = sctp_pkt_to_tuple, - .invert_tuple = sctp_invert_tuple, - .print_tuple = sctp_print_tuple, - .print_conntrack = sctp_print_conntrack, - .packet = sctp_packet, - .new = sctp_new, - .destroy = NULL, - .me = THIS_MODULE -}; - -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { - .l3proto = PF_INET6, - .l4proto = IPPROTO_SCTP, - .name = "sctp", - .pkt_to_tuple = sctp_pkt_to_tuple, - .invert_tuple = sctp_invert_tuple, - .print_tuple = sctp_print_tuple, - .print_conntrack = sctp_print_conntrack, - .packet = sctp_packet, - .new = sctp_new, - .destroy = NULL, - .me = THIS_MODULE -}; - #ifdef CONFIG_SYSCTL -static ctl_table nf_ct_sysctl_table[] = { +static unsigned int sctp_sysctl_table_users; +static struct ctl_table_header *sctp_sysctl_header; +static struct ctl_table sctp_sysctl_table[] = { { .ctl_name = NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, .procname = "nf_conntrack_sctp_timeout_closed", @@ -595,31 +569,47 @@ static ctl_table nf_ct_sysctl_table[] = { .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, - { .ctl_name = 0 } -}; - -static ctl_table nf_ct_netfilter_table[] = { { - .ctl_name = NET_NETFILTER, - .procname = "netfilter", - .mode = 0555, - .child = nf_ct_sysctl_table, - }, - { .ctl_name = 0 } + .ctl_name = 0 + } }; +#endif -static ctl_table nf_ct_net_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = nf_ct_netfilter_table, - }, - { .ctl_name = 0 } +struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { + .l3proto = PF_INET, + .l4proto = IPPROTO_SCTP, + .name = "sctp", + .pkt_to_tuple = sctp_pkt_to_tuple, + .invert_tuple = sctp_invert_tuple, + .print_tuple = sctp_print_tuple, + .print_conntrack = sctp_print_conntrack, + .packet = sctp_packet, + .new = sctp_new, + .me = THIS_MODULE, +#ifdef CONFIG_SYSCTL + .ctl_table_users = &sctp_sysctl_table_users, + .ctl_table_header = &sctp_sysctl_header, + .ctl_table = sctp_sysctl_table, +#endif }; -static struct ctl_table_header *nf_ct_sysctl_header; +struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { + .l3proto = PF_INET6, + .l4proto = IPPROTO_SCTP, + .name = "sctp", + .pkt_to_tuple = sctp_pkt_to_tuple, + .invert_tuple = sctp_invert_tuple, + .print_tuple = sctp_print_tuple, + .print_conntrack = sctp_print_conntrack, + .packet = sctp_packet, + .new = sctp_new, + .me = THIS_MODULE, +#ifdef CONFIG_SYSCTL + .ctl_table_users = &sctp_sysctl_table_users, + .ctl_table_header = &sctp_sysctl_header, + .ctl_table = sctp_sysctl_table, #endif +}; int __init nf_conntrack_proto_sctp_init(void) { @@ -636,20 +626,8 @@ int __init nf_conntrack_proto_sctp_init(void) goto cleanup_sctp4; } -#ifdef CONFIG_SYSCTL - nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); - if (nf_ct_sysctl_header == NULL) { - printk("nf_conntrack_proto_sctp: can't register to sysctl.\n"); - goto cleanup; - } -#endif - return ret; -#ifdef CONFIG_SYSCTL - cleanup: - nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); -#endif cleanup_sctp4: nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); out: @@ -662,9 +640,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); -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_sysctl_header); -#endif DEBUGP("SCTP conntrack module unloaded\n"); } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 32b88b7efc46..6f6f9a061e76 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -93,22 +93,22 @@ static const char *tcp_conntrack_names[] = { #define HOURS * 60 MINS #define DAYS * 24 HOURS -unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS; -unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS; -unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS; -unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS; -unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS; +static unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS; +static unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS; +static unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS; +static unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS; +static unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS; +static unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS; +static unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS; +static unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS; /* RFC1122 says the R2 limit should be at least 100 seconds. Linux uses 15 packets as limit, which corresponds to ~13-30min depending on RTO. */ -unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; +static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; -static unsigned int * tcp_timeouts[] -= { NULL, /* TCP_CONNTRACK_NONE */ +static unsigned int * tcp_timeouts[] = { + NULL, /* TCP_CONNTRACK_NONE */ &nf_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */ &nf_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */ &nf_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */ @@ -1168,7 +1168,113 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct) return 0; } #endif - + +#ifdef CONFIG_SYSCTL +static unsigned int tcp_sysctl_table_users; +static struct ctl_table_header *tcp_sysctl_header; +static struct ctl_table tcp_sysctl_table[] = { + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, + .procname = "nf_conntrack_tcp_timeout_syn_sent", + .data = &nf_ct_tcp_timeout_syn_sent, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, + .procname = "nf_conntrack_tcp_timeout_syn_recv", + .data = &nf_ct_tcp_timeout_syn_recv, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, + .procname = "nf_conntrack_tcp_timeout_established", + .data = &nf_ct_tcp_timeout_established, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, + .procname = "nf_conntrack_tcp_timeout_fin_wait", + .data = &nf_ct_tcp_timeout_fin_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, + .procname = "nf_conntrack_tcp_timeout_close_wait", + .data = &nf_ct_tcp_timeout_close_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, + .procname = "nf_conntrack_tcp_timeout_last_ack", + .data = &nf_ct_tcp_timeout_last_ack, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, + .procname = "nf_conntrack_tcp_timeout_time_wait", + .data = &nf_ct_tcp_timeout_time_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, + .procname = "nf_conntrack_tcp_timeout_close", + .data = &nf_ct_tcp_timeout_close, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, + .procname = "nf_conntrack_tcp_timeout_max_retrans", + .data = &nf_ct_tcp_timeout_max_retrans, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE, + .procname = "nf_conntrack_tcp_loose", + .data = &nf_ct_tcp_loose, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL, + .procname = "nf_conntrack_tcp_be_liberal", + .data = &nf_ct_tcp_be_liberal, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS, + .procname = "nf_conntrack_tcp_max_retrans", + .data = &nf_ct_tcp_max_retrans, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL */ + struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = { .l3proto = PF_INET, @@ -1188,6 +1294,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_users = &tcp_sysctl_table_users, + .ctl_table_header = &tcp_sysctl_header, + .ctl_table = tcp_sysctl_table, +#endif }; struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = @@ -1209,6 +1320,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_users = &tcp_sysctl_table_users, + .ctl_table_header = &tcp_sysctl_header, + .ctl_table = tcp_sysctl_table, +#endif }; EXPORT_SYMBOL(nf_conntrack_l4proto_tcp4); diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 200d7d324362..d86749cb4a46 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -29,8 +29,8 @@ #include #include -unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; -unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; +static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; +static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; static int udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, @@ -148,6 +148,32 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, return NF_ACCEPT; } +#ifdef CONFIG_SYSCTL +static unsigned int udp_sysctl_table_users; +static struct ctl_table_header *udp_sysctl_header; +static struct ctl_table udp_sysctl_table[] = { + { + .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT, + .procname = "nf_conntrack_udp_timeout", + .data = &nf_ct_udp_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM, + .procname = "nf_conntrack_udp_timeout_stream", + .data = &nf_ct_udp_timeout_stream, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL */ + struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = { .l3proto = PF_INET, @@ -165,6 +191,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_users = &udp_sysctl_table_users, + .ctl_table_header = &udp_sysctl_header, + .ctl_table = udp_sysctl_table, +#endif }; struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = @@ -184,6 +215,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif +#ifdef CONFIG_SYSCTL + .ctl_table_users = &udp_sysctl_table_users, + .ctl_table_header = &udp_sysctl_header, + .ctl_table = udp_sysctl_table, +#endif }; EXPORT_SYMBOL(nf_conntrack_l4proto_udp4); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 2283a2686949..9d8906848b98 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -330,28 +330,6 @@ static struct file_operations ct_cpu_seq_fops = { int nf_conntrack_checksum __read_mostly = 1; #ifdef CONFIG_SYSCTL - -/* From nf_conntrack_proto_tcp.c */ -extern unsigned int nf_ct_tcp_timeout_syn_sent; -extern unsigned int nf_ct_tcp_timeout_syn_recv; -extern unsigned int nf_ct_tcp_timeout_established; -extern unsigned int nf_ct_tcp_timeout_fin_wait; -extern unsigned int nf_ct_tcp_timeout_close_wait; -extern unsigned int nf_ct_tcp_timeout_last_ack; -extern unsigned int nf_ct_tcp_timeout_time_wait; -extern unsigned int nf_ct_tcp_timeout_close; -extern unsigned int nf_ct_tcp_timeout_max_retrans; -extern int nf_ct_tcp_loose; -extern int nf_ct_tcp_be_liberal; -extern int nf_ct_tcp_max_retrans; - -/* From nf_conntrack_proto_udp.c */ -extern unsigned int nf_ct_udp_timeout; -extern unsigned int nf_ct_udp_timeout_stream; - -/* From nf_conntrack_proto_generic.c */ -extern unsigned int nf_ct_generic_timeout; - /* Log invalid packets of a given protocol */ static int log_invalid_proto_min = 0; static int log_invalid_proto_max = 255; @@ -391,94 +369,6 @@ static ctl_table nf_ct_sysctl_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, - .procname = "nf_conntrack_tcp_timeout_syn_sent", - .data = &nf_ct_tcp_timeout_syn_sent, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, - .procname = "nf_conntrack_tcp_timeout_syn_recv", - .data = &nf_ct_tcp_timeout_syn_recv, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, - .procname = "nf_conntrack_tcp_timeout_established", - .data = &nf_ct_tcp_timeout_established, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, - .procname = "nf_conntrack_tcp_timeout_fin_wait", - .data = &nf_ct_tcp_timeout_fin_wait, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, - .procname = "nf_conntrack_tcp_timeout_close_wait", - .data = &nf_ct_tcp_timeout_close_wait, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, - .procname = "nf_conntrack_tcp_timeout_last_ack", - .data = &nf_ct_tcp_timeout_last_ack, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, - .procname = "nf_conntrack_tcp_timeout_time_wait", - .data = &nf_ct_tcp_timeout_time_wait, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, - .procname = "nf_conntrack_tcp_timeout_close", - .data = &nf_ct_tcp_timeout_close, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT, - .procname = "nf_conntrack_udp_timeout", - .data = &nf_ct_udp_timeout, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM, - .procname = "nf_conntrack_udp_timeout_stream", - .data = &nf_ct_udp_timeout_stream, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_GENERIC_TIMEOUT, - .procname = "nf_conntrack_generic_timeout", - .data = &nf_ct_generic_timeout, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, { .ctl_name = NET_NF_CONNTRACK_LOG_INVALID, .procname = "nf_conntrack_log_invalid", @@ -490,38 +380,6 @@ static ctl_table nf_ct_sysctl_table[] = { .extra1 = &log_invalid_proto_min, .extra2 = &log_invalid_proto_max, }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, - .procname = "nf_conntrack_tcp_timeout_max_retrans", - .data = &nf_ct_tcp_timeout_max_retrans, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE, - .procname = "nf_conntrack_tcp_loose", - .data = &nf_ct_tcp_loose, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL, - .procname = "nf_conntrack_tcp_be_liberal", - .data = &nf_ct_tcp_be_liberal, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS, - .procname = "nf_conntrack_tcp_max_retrans", - .data = &nf_ct_tcp_max_retrans, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, { .ctl_name = 0 } }; -- cgit v1.2.3-70-g09d2 From a999e6837603e4b5a164333c93918a1292f074c8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:20 +0100 Subject: [NETFILTER]: nf_conntrack: sysctl compatibility with old connection tracking This patch adds an option to keep the connection tracking sysctls visible under their old names. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l4proto.h | 6 +- net/ipv4/netfilter/Kconfig | 11 +++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 58 ++++++++++++++ net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 18 +++++ net/netfilter/nf_conntrack_core.c | 2 + net/netfilter/nf_conntrack_proto.c | 20 +++++ net/netfilter/nf_conntrack_proto_generic.c | 18 +++++ net/netfilter/nf_conntrack_proto_sctp.c | 67 ++++++++++++++++ net/netfilter/nf_conntrack_proto_tcp.c | 107 +++++++++++++++++++++++++ net/netfilter/nf_conntrack_proto_udp.c | 26 ++++++ 10 files changed, 332 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index fe1e8fa30d2f..fc8af08ff542 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -80,7 +80,11 @@ struct nf_conntrack_l4proto struct ctl_table_header **ctl_table_header; struct ctl_table *ctl_table; unsigned int *ctl_table_users; -#endif /* CONFIG_SYSCTL */ +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + struct ctl_table_header *ctl_compat_table_header; + struct ctl_table *ctl_compat_table; +#endif +#endif /* Module (if any) which this is connected to. */ struct module *me; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index d88c292f118c..4ac5b5c4678d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -19,6 +19,17 @@ config NF_CONNTRACK_IPV4 To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_PROC_COMPAT + bool "proc/sysctl compatibility with old connection tracking" + depends on NF_CONNTRACK + default y + help + This option enables /proc and sysctl compatibility with the old + layer 3 dependant connection tracking. This is needed to keep + old programs that have not been adapted to the new names working. + + If unsure, say Y. + # connection tracking, helpers and protocols config IP_NF_CONNTRACK tristate "Connection tracking (required for masq/NAT)" diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 786c4ce96cdf..bcec6822f2ee 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -266,6 +266,60 @@ static struct nf_hook_ops ipv4_conntrack_ops[] = { }, }; +#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) +static int log_invalid_proto_min = 0; +static int log_invalid_proto_max = 255; + +static ctl_table ip_ct_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_MAX, + .procname = "ip_conntrack_max", + .data = &nf_conntrack_max, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT, + .procname = "ip_conntrack_count", + .data = &nf_conntrack_count, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS, + .procname = "ip_conntrack_buckets", + .data = &nf_conntrack_htable_size, + .maxlen = sizeof(unsigned int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM, + .procname = "ip_conntrack_checksum", + .data = &nf_conntrack_checksum, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID, + .procname = "ip_conntrack_log_invalid", + .data = &nf_ct_log_invalid, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &log_invalid_proto_min, + .extra2 = &log_invalid_proto_max, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */ + /* Fast function for those who don't want to parse /proc (and I don't blame them). */ /* Reversing the socket's dst/src point of view gives us the reply @@ -385,6 +439,10 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv4_tuple_to_nfattr, .nfattr_to_tuple = ipv4_nfattr_to_tuple, +#endif +#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + .ctl_table_path = nf_net_ipv4_netfilter_sysctl_path, + .ctl_table = ip_ct_sysctl_table, #endif .me = THIS_MODULE, }; diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index c59f28193a39..46aa44abc078 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -336,6 +336,21 @@ static struct ctl_table icmp_sysctl_table[] = { .ctl_name = 0 } }; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +static struct ctl_table icmp_compat_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, + .procname = "ip_conntrack_icmp_timeout", + .data = &nf_ct_icmp_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = @@ -360,6 +375,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = #ifdef CONFIG_SYSCTL .ctl_table_header = &icmp_sysctl_header, .ctl_table = icmp_sysctl_table, +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + .ctl_compat_table = icmp_compat_sysctl_table, +#endif #endif }; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4b972791149d..a6728067780a 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -66,10 +66,12 @@ DEFINE_RWLOCK(nf_conntrack_lock); /* nf_conntrack_standalone needs this */ atomic_t nf_conntrack_count = ATOMIC_INIT(0); +EXPORT_SYMBOL_GPL(nf_conntrack_count); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; unsigned int nf_conntrack_htable_size __read_mostly; int nf_conntrack_max __read_mostly; +EXPORT_SYMBOL_GPL(nf_conntrack_max); struct list_head *nf_conntrack_hash __read_mostly; struct nf_conn nf_conntrack_untracked __read_mostly; unsigned int nf_ct_log_invalid __read_mostly; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 891c9c56c319..4798afcbbb0d 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -250,7 +250,22 @@ static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) nf_net_netfilter_sysctl_path, l4proto->ctl_table, l4proto->ctl_table_users); + if (err < 0) + goto out; } +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + if (l4proto->ctl_compat_table != NULL) { + err = nf_ct_register_sysctl(&l4proto->ctl_compat_table_header, + nf_net_ipv4_netfilter_sysctl_path, + l4proto->ctl_compat_table, NULL); + if (err == 0) + goto out; + nf_ct_unregister_sysctl(l4proto->ctl_table_header, + l4proto->ctl_table, + l4proto->ctl_table_users); + } +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +out: mutex_unlock(&nf_ct_proto_sysctl_mutex); #endif /* CONFIG_SYSCTL */ return err; @@ -265,6 +280,11 @@ static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto nf_ct_unregister_sysctl(l4proto->ctl_table_header, l4proto->ctl_table, l4proto->ctl_table_users); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + if (l4proto->ctl_compat_table_header != NULL) + nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header, + l4proto->ctl_compat_table, NULL); +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ mutex_unlock(&nf_ct_proto_sysctl_mutex); #endif /* CONFIG_SYSCTL */ } diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 15306b952510..69902531c236 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -86,6 +86,21 @@ static struct ctl_table generic_sysctl_table[] = { .ctl_name = 0 } }; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +static struct ctl_table generic_compat_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, + .procname = "ip_conntrack_generic_timeout", + .data = &nf_ct_generic_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = @@ -102,5 +117,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = #ifdef CONFIG_SYSCTL .ctl_table_header = &generic_sysctl_header, .ctl_table = generic_sysctl_table, +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + .ctl_compat_table = generic_compat_sysctl_table, +#endif #endif }; diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index cc693308878f..7c64b9c1cf4a 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -573,6 +573,70 @@ static struct ctl_table sctp_sysctl_table[] = { .ctl_name = 0 } }; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +static struct ctl_table sctp_compat_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, + .procname = "ip_conntrack_sctp_timeout_closed", + .data = &nf_ct_sctp_timeout_closed, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, + .procname = "ip_conntrack_sctp_timeout_cookie_wait", + .data = &nf_ct_sctp_timeout_cookie_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, + .procname = "ip_conntrack_sctp_timeout_cookie_echoed", + .data = &nf_ct_sctp_timeout_cookie_echoed, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, + .procname = "ip_conntrack_sctp_timeout_established", + .data = &nf_ct_sctp_timeout_established, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, + .procname = "ip_conntrack_sctp_timeout_shutdown_sent", + .data = &nf_ct_sctp_timeout_shutdown_sent, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, + .procname = "ip_conntrack_sctp_timeout_shutdown_recd", + .data = &nf_ct_sctp_timeout_shutdown_recd, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, + .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent", + .data = &nf_ct_sctp_timeout_shutdown_ack_sent, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { @@ -590,6 +654,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .ctl_table_users = &sctp_sysctl_table_users, .ctl_table_header = &sctp_sysctl_header, .ctl_table = sctp_sysctl_table, +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + .ctl_compat_table = sctp_compat_sysctl_table, +#endif #endif }; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 6f6f9a061e76..d99c7c4176d4 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1273,6 +1273,110 @@ static struct ctl_table tcp_sysctl_table[] = { .ctl_name = 0 } }; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +static struct ctl_table tcp_compat_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, + .procname = "ip_conntrack_tcp_timeout_syn_sent", + .data = &nf_ct_tcp_timeout_syn_sent, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, + .procname = "ip_conntrack_tcp_timeout_syn_recv", + .data = &nf_ct_tcp_timeout_syn_recv, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, + .procname = "ip_conntrack_tcp_timeout_established", + .data = &nf_ct_tcp_timeout_established, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, + .procname = "ip_conntrack_tcp_timeout_fin_wait", + .data = &nf_ct_tcp_timeout_fin_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, + .procname = "ip_conntrack_tcp_timeout_close_wait", + .data = &nf_ct_tcp_timeout_close_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, + .procname = "ip_conntrack_tcp_timeout_last_ack", + .data = &nf_ct_tcp_timeout_last_ack, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, + .procname = "ip_conntrack_tcp_timeout_time_wait", + .data = &nf_ct_tcp_timeout_time_wait, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, + .procname = "ip_conntrack_tcp_timeout_close", + .data = &nf_ct_tcp_timeout_close, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS, + .procname = "ip_conntrack_tcp_timeout_max_retrans", + .data = &nf_ct_tcp_timeout_max_retrans, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE, + .procname = "ip_conntrack_tcp_loose", + .data = &nf_ct_tcp_loose, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, + .procname = "ip_conntrack_tcp_be_liberal", + .data = &nf_ct_tcp_be_liberal, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, + .procname = "ip_conntrack_tcp_max_retrans", + .data = &nf_ct_tcp_max_retrans, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = @@ -1298,6 +1402,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .ctl_table_users = &tcp_sysctl_table_users, .ctl_table_header = &tcp_sysctl_header, .ctl_table = tcp_sysctl_table, +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + .ctl_compat_table = tcp_compat_sysctl_table, +#endif #endif }; diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index d86749cb4a46..908fde7719f4 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -172,6 +172,29 @@ static struct ctl_table udp_sysctl_table[] = { .ctl_name = 0 } }; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +static struct ctl_table udp_compat_sysctl_table[] = { + { + .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, + .procname = "ip_conntrack_udp_timeout", + .data = &nf_ct_udp_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, + .procname = "ip_conntrack_udp_timeout_stream", + .data = &nf_ct_udp_timeout_stream, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + }, + { + .ctl_name = 0 + } +}; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_SYSCTL */ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = @@ -195,6 +218,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .ctl_table_users = &udp_sysctl_table_users, .ctl_table_header = &udp_sysctl_header, .ctl_table = udp_sysctl_table, +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + .ctl_compat_table = udp_compat_sysctl_table, +#endif #endif }; -- cgit v1.2.3-70-g09d2 From e4bd8bce3e8b53e2c0a0d5c9afbc29731e517f8d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:22 +0100 Subject: [NETFILTER]: nf_conntrack: /proc compatibility with old connection tracking This patch adds /proc/net/ip_conntrack, /proc/net/ip_conntrack_expect and /proc/net/stat/ip_conntrack files to keep old programs using them working. The /proc/net/ip_conntrack and /proc/net/ip_conntrack_expect files show only IPv4 entries, the /proc/net/stat/ip_conntrack shows global statistics. Signed-off-by: Patrick McHardy --- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 3 + net/ipv4/netfilter/Makefile | 5 + net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 13 +- .../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 412 +++++++++++++++++++++ net/netfilter/nf_conntrack_l3proto_generic.c | 1 + net/netfilter/nf_conntrack_standalone.c | 1 + 6 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c (limited to 'net') diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 8c4f7e89ce55..34b453a81a63 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -41,4 +41,7 @@ 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; +extern int nf_conntrack_ipv4_compat_init(void); +extern void nf_conntrack_ipv4_compat_fini(void); + #endif /*_NF_CONNTRACK_IPV4_H*/ diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 09aaed1a8063..4ce20ebc4d6c 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -89,6 +89,11 @@ obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o # objects for l3 independent conntrack nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o +ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y) +ifeq ($(CONFIG_PROC_FS),y) +nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o +endif +endif # l3 independent conntrack obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index bcec6822f2ee..f24e872d4b90 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -492,8 +492,16 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) printk("nf_conntrack_ipv4: can't register hooks.\n"); goto cleanup_ipv4; } +#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + ret = nf_conntrack_ipv4_compat_init(); + if (ret < 0) + goto cleanup_hooks; +#endif return ret; - +#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + cleanup_hooks: + nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); +#endif cleanup_ipv4: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); cleanup_icmp: @@ -510,6 +518,9 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) static void __exit nf_conntrack_l3proto_ipv4_fini(void) { synchronize_net(); +#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + nf_conntrack_ipv4_compat_fini(); +#endif nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c new file mode 100644 index 000000000000..3b31bc649608 --- /dev/null +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -0,0 +1,412 @@ +/* ip_conntrack proc compat - based on ip_conntrack_standalone.c + * + * (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#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, + const struct ip_conntrack_counter *counter) +{ + return seq_printf(s, "packets=%llu bytes=%llu ", + (unsigned long long)counter->packets, + (unsigned long long)counter->bytes); +} +#else +#define seq_print_counters(x, y) 0 +#endif + +struct ct_iter_state { + unsigned int bucket; +}; + +static struct list_head *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; + } + return NULL; +} + +static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head) +{ + struct ct_iter_state *st = seq->private; + + head = head->next; + while (head == &nf_conntrack_hash[st->bucket]) { + if (++st->bucket >= nf_conntrack_htable_size) + return NULL; + head = nf_conntrack_hash[st->bucket].next; + } + return head; +} + +static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) +{ + struct list_head *head = ct_get_first(seq); + + if (head) + while (pos && (head = ct_get_next(seq, head))) + pos--; + return pos ? NULL : head; +} + +static void *ct_seq_start(struct seq_file *seq, loff_t *pos) +{ + read_lock_bh(&nf_conntrack_lock); + return ct_get_idx(seq, *pos); +} + +static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + (*pos)++; + return ct_get_next(s, v); +} + +static void ct_seq_stop(struct seq_file *s, void *v) +{ + read_unlock_bh(&nf_conntrack_lock); +} + +static int ct_seq_show(struct seq_file *s, void *v) +{ + const struct nf_conntrack_tuple_hash *hash = v; + const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); + struct nf_conntrack_l3proto *l3proto; + struct nf_conntrack_l4proto *l4proto; + + NF_CT_ASSERT(ct); + + /* we only want to print DIR_ORIGINAL */ + if (NF_CT_DIRECTION(hash)) + return 0; + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET) + return 0; + + l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] + .tuple.src.l3num); + NF_CT_ASSERT(l3proto); + l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] + .tuple.src.l3num, + ct->tuplehash[IP_CT_DIR_ORIGINAL] + .tuple.dst.protonum); + NF_CT_ASSERT(l4proto); + + if (seq_printf(s, "%-8s %u %ld ", + l4proto->name, + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum, + timer_pending(&ct->timeout) + ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) + return -ENOSPC; + + if (l3proto->print_conntrack(s, ct)) + return -ENOSPC; + + if (l4proto->print_conntrack(s, ct)) + return -ENOSPC; + + if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, + l3proto, l4proto)) + return -ENOSPC; + + if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL])) + return -ENOSPC; + + if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) + if (seq_printf(s, "[UNREPLIED] ")) + return -ENOSPC; + + if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, + l3proto, l4proto)) + return -ENOSPC; + + if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY])) + return -ENOSPC; + + if (test_bit(IPS_ASSURED_BIT, &ct->status)) + if (seq_printf(s, "[ASSURED] ")) + return -ENOSPC; + +#ifdef CONFIG_NF_CONNTRACK_MARK + if (seq_printf(s, "mark=%u ", ct->mark)) + return -ENOSPC; +#endif + +#ifdef CONFIG_NF_CONNTRACK_SECMARK + if (seq_printf(s, "secmark=%u ", ct->secmark)) + return -ENOSPC; +#endif + + if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) + return -ENOSPC; + + return 0; +} + +static struct seq_operations ct_seq_ops = { + .start = ct_seq_start, + .next = ct_seq_next, + .stop = ct_seq_stop, + .show = ct_seq_show +}; + +static int ct_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + struct ct_iter_state *st; + int ret; + + st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL); + if (st == NULL) + return -ENOMEM; + ret = seq_open(file, &ct_seq_ops); + if (ret) + goto out_free; + seq = file->private_data; + seq->private = st; + memset(st, 0, sizeof(struct ct_iter_state)); + return ret; +out_free: + kfree(st); + return ret; +} + +static struct file_operations ct_file_ops = { + .owner = THIS_MODULE, + .open = ct_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +/* expects */ +static void *exp_seq_start(struct seq_file *s, loff_t *pos) +{ + struct list_head *e = &nf_conntrack_expect_list; + loff_t i; + + /* strange seq_file api calls stop even if we fail, + * thus we need to grab lock since stop unlocks */ + read_lock_bh(&nf_conntrack_lock); + + if (list_empty(e)) + return NULL; + + for (i = 0; i <= *pos; i++) { + e = e->next; + if (e == &nf_conntrack_expect_list) + return NULL; + } + return e; +} + +static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct list_head *e = v; + + ++*pos; + e = e->next; + + if (e == &nf_conntrack_expect_list) + return NULL; + + return e; +} + +static void exp_seq_stop(struct seq_file *s, void *v) +{ + read_unlock_bh(&nf_conntrack_lock); +} + +static int exp_seq_show(struct seq_file *s, void *v) +{ + struct nf_conntrack_expect *exp = v; + + if (exp->tuple.src.l3num != AF_INET) + return 0; + + if (exp->timeout.function) + seq_printf(s, "%ld ", timer_pending(&exp->timeout) + ? (long)(exp->timeout.expires - jiffies)/HZ : 0); + else + seq_printf(s, "- "); + + seq_printf(s, "proto=%u ", exp->tuple.dst.protonum); + + print_tuple(s, &exp->tuple, + __nf_ct_l3proto_find(exp->tuple.src.l3num), + __nf_ct_l4proto_find(exp->tuple.src.l3num, + exp->tuple.dst.protonum)); + return seq_putc(s, '\n'); +} + +static struct seq_operations exp_seq_ops = { + .start = exp_seq_start, + .next = exp_seq_next, + .stop = exp_seq_stop, + .show = exp_seq_show +}; + +static int exp_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &exp_seq_ops); +} + +static struct file_operations ip_exp_file_ops = { + .owner = THIS_MODULE, + .open = exp_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) +{ + int cpu; + + if (*pos == 0) + return SEQ_START_TOKEN; + + for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { + if (!cpu_possible(cpu)) + continue; + *pos = cpu+1; + return &per_cpu(nf_conntrack_stat, cpu); + } + + return NULL; +} + +static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + int cpu; + + for (cpu = *pos; cpu < NR_CPUS; ++cpu) { + if (!cpu_possible(cpu)) + continue; + *pos = cpu+1; + return &per_cpu(nf_conntrack_stat, cpu); + } + + return NULL; +} + +static void ct_cpu_seq_stop(struct seq_file *seq, void *v) +{ +} + +static int ct_cpu_seq_show(struct seq_file *seq, void *v) +{ + unsigned int nr_conntracks = atomic_read(&nf_conntrack_count); + struct ip_conntrack_stat *st = v; + + if (v == SEQ_START_TOKEN) { + seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n"); + return 0; + } + + seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " + "%08x %08x %08x %08x %08x %08x %08x %08x \n", + nr_conntracks, + st->searched, + st->found, + st->new, + st->invalid, + st->ignore, + st->delete, + st->delete_list, + st->insert, + st->insert_failed, + st->drop, + st->early_drop, + st->error, + + st->expect_new, + st->expect_create, + st->expect_delete + ); + return 0; +} + +static struct seq_operations ct_cpu_seq_ops = { + .start = ct_cpu_seq_start, + .next = ct_cpu_seq_next, + .stop = ct_cpu_seq_stop, + .show = ct_cpu_seq_show, +}; + +static int ct_cpu_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ct_cpu_seq_ops); +} + +static struct file_operations ct_cpu_seq_fops = { + .owner = THIS_MODULE, + .open = ct_cpu_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +int __init nf_conntrack_ipv4_compat_init(void) +{ + struct proc_dir_entry *proc, *proc_exp, *proc_stat; + + proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops); + if (!proc) + goto err1; + + proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440, + &ip_exp_file_ops); + if (!proc_exp) + goto err2; + + proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat); + if (!proc_stat) + goto err3; + + proc_stat->proc_fops = &ct_cpu_seq_fops; + proc_stat->owner = THIS_MODULE; + + return 0; + +err3: + proc_net_remove("ip_conntrack_expect"); +err2: + proc_net_remove("ip_conntrack"); +err1: + return -ENOMEM; +} + +void __exit nf_conntrack_ipv4_compat_fini(void) +{ + remove_proc_entry("ip_conntrack", proc_net_stat); + proc_net_remove("ip_conntrack_expect"); + proc_net_remove("ip_conntrack"); +} diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 3124b3a30102..a3d31c3ac8e6 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -92,3 +92,4 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { .prepare = generic_prepare, .get_features = generic_get_features, }; +EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 9d8906848b98..3db24f4f0f5b 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -52,6 +52,7 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, { return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple); } +EXPORT_SYMBOL_GPL(print_tuple); #ifdef CONFIG_NF_CT_ACCT static unsigned int -- cgit v1.2.3-70-g09d2 From 468ec44bd5a863736d955f78b8c38896f26864a1 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Wed, 29 Nov 2006 02:35:23 +0100 Subject: [NETFILTER]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find We usually uses 'xxx_find_get' for function which increments reference count. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy --- include/linux/netfilter_ipv4/ip_conntrack.h | 2 +- include/net/netfilter/nf_conntrack_expect.h | 2 +- net/ipv4/netfilter/ip_conntrack_core.c | 2 +- net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 4 ++-- net/ipv4/netfilter/ip_conntrack_netlink.c | 4 ++-- net/ipv4/netfilter/ip_conntrack_standalone.c | 2 +- net/ipv4/netfilter/ip_nat_helper_pptp.c | 2 +- net/netfilter/nf_conntrack_expect.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 4 ++-- net/netfilter/nf_conntrack_standalone.c | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 64e868034c4a..61da56941dce 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -277,7 +277,7 @@ extern struct ip_conntrack_expect * __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); extern struct ip_conntrack_expect * -ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); +ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple); extern struct ip_conntrack_tuple_hash * __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 5aa483e03455..2d335f024c85 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -53,7 +53,7 @@ struct nf_conntrack_expect * __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * -nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple); +nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * find_expectation(const struct nf_conntrack_tuple *tuple); diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 8b848aa77bfc..4d1f954d459b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) /* Just find a expectation corresponding to a tuple. */ struct ip_conntrack_expect * -ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) +ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple) { struct ip_conntrack_expect *i; diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index a2af5e0c7f99..a5c057bcecf4 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -142,7 +142,7 @@ static void pptp_expectfn(struct ip_conntrack *ct, DEBUGP("trying to unexpect other dir: "); DUMP_TUPLE(&inv_t); - exp_other = ip_conntrack_expect_find(&inv_t); + exp_other = ip_conntrack_expect_find_get(&inv_t); if (exp_other) { /* delete other expectation. */ DEBUGP("found\n"); @@ -176,7 +176,7 @@ static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) ip_conntrack_put(sibling); return 1; } else { - exp = ip_conntrack_expect_find(t); + exp = ip_conntrack_expect_find_get(t); if (exp) { DEBUGP("unexpect_related of expect %p\n", exp); ip_conntrack_unexpect_related(exp); diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 1bb8ed33c5bc..3d277aa869dd 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1256,7 +1256,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = ip_conntrack_expect_find(&tuple); + exp = ip_conntrack_expect_find_get(&tuple); if (!exp) return -ENOENT; @@ -1309,7 +1309,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = ip_conntrack_expect_find(&tuple); + exp = ip_conntrack_expect_find_get(&tuple); if (!exp) return -ENOENT; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 02135756562e..2df67538ffb0 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -926,7 +926,7 @@ EXPORT_SYMBOL(__ip_ct_refresh_acct); EXPORT_SYMBOL(ip_conntrack_expect_alloc); EXPORT_SYMBOL(ip_conntrack_expect_put); EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); -EXPORT_SYMBOL_GPL(ip_conntrack_expect_find); +EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get); EXPORT_SYMBOL(ip_conntrack_expect_related); EXPORT_SYMBOL(ip_conntrack_unexpect_related); EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index 329fdcd7d702..acf55d863100 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -101,7 +101,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct, DEBUGP("trying to unexpect other dir: "); DUMP_TUPLE(&t); - other_exp = ip_conntrack_expect_find(&t); + other_exp = ip_conntrack_expect_find_get(&t); if (other_exp) { ip_conntrack_unexpect_related(other_exp); ip_conntrack_expect_put(other_exp); diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 79cfd79a42f0..aa5903e4da11 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -68,7 +68,7 @@ __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) /* Just find a expectation corresponding to a tuple. */ struct nf_conntrack_expect * -nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) +nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index dc0830220130..7357b8f47acd 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1284,7 +1284,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = nf_conntrack_expect_find(&tuple); + exp = nf_conntrack_expect_find_get(&tuple); if (!exp) return -ENOENT; @@ -1339,7 +1339,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = nf_conntrack_expect_find(&tuple); + exp = nf_conntrack_expect_find_get(&tuple); if (!exp) return -ENOENT; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3db24f4f0f5b..be94b6359725 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -549,7 +549,7 @@ EXPORT_SYMBOL(__nf_conntrack_find); EXPORT_SYMBOL(nf_ct_unlink_expect); EXPORT_SYMBOL(nf_conntrack_hash_insert); EXPORT_SYMBOL(__nf_conntrack_expect_find); -EXPORT_SYMBOL(nf_conntrack_expect_find); +EXPORT_SYMBOL(nf_conntrack_expect_find_get); EXPORT_SYMBOL(nf_conntrack_expect_list); #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) -- cgit v1.2.3-70-g09d2 From 337fbc4166967a72c3cc71c597bdde7e6a8633ab Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:25 +0100 Subject: [NETFILTER]: ip_conntrack: fix NAT helper unload races The NAT helpr hooks are protected by RCU, but all of the conntrack helpers test and use the global pointers instead of copying them first using rcu_dereference() Also replace synchronize_net() by synchronize_rcu() for clarity since sychronizing only with packet receive processing is insufficient to prevent races. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_amanda.c | 9 +- net/ipv4/netfilter/ip_conntrack_ftp.c | 8 +- net/ipv4/netfilter/ip_conntrack_helper_h323.c | 164 +++++++++++++++----------- net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 29 +++-- net/ipv4/netfilter/ip_conntrack_irc.c | 12 +- net/ipv4/netfilter/ip_conntrack_sip.c | 12 +- net/ipv4/netfilter/ip_conntrack_tftp.c | 6 +- net/ipv4/netfilter/ip_nat_amanda.c | 9 +- net/ipv4/netfilter/ip_nat_ftp.c | 9 +- net/ipv4/netfilter/ip_nat_helper_h323.c | 58 ++++----- net/ipv4/netfilter/ip_nat_helper_pptp.c | 27 ++--- net/ipv4/netfilter/ip_nat_irc.c | 9 +- net/ipv4/netfilter/ip_nat_sip.c | 15 ++- net/ipv4/netfilter/ip_nat_tftp.c | 9 +- net/netfilter/nf_conntrack_ftp.c | 9 +- 15 files changed, 216 insertions(+), 169 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index 7fca246615d5..ad246ba7790b 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -92,6 +92,7 @@ static int help(struct sk_buff **pskb, char pbuf[sizeof("65535")], *tmp; u_int16_t port, len; int ret = NF_ACCEPT; + typeof(ip_nat_amanda_hook) ip_nat_amanda; /* Only look at packets from the Amanda server */ if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) @@ -161,9 +162,11 @@ static int help(struct sk_buff **pskb, exp->mask.dst.protonum = 0xFF; exp->mask.dst.u.tcp.port = htons(0xFFFF); - if (ip_nat_amanda_hook) - ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff, - len, exp); + /* RCU read locked by nf_hook_slow */ + ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook); + if (ip_nat_amanda) + ret = ip_nat_amanda(pskb, ctinfo, off - dataoff, + len, exp); else if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; ip_conntrack_expect_put(exp); diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 93dcf960662f..0410c99cacae 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -310,6 +310,7 @@ static int help(struct sk_buff **pskb, struct ip_conntrack_expect *exp; unsigned int i; int found = 0, ends_in_nl; + typeof(ip_nat_ftp_hook) ip_nat_ftp; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED @@ -433,9 +434,10 @@ static int help(struct sk_buff **pskb, /* Now, NAT might want to mangle the packet, and register the * (possibly changed) expectation itself. */ - if (ip_nat_ftp_hook) - ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype, - matchoff, matchlen, exp, &seq); + ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook); + if (ip_nat_ftp) + ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, + matchoff, matchlen, exp, &seq); else { /* Can't expect this? Best to drop packet now. */ if (ip_conntrack_expect_related(exp) != 0) diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index a06b340ea414..aabfe1c06905 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -237,6 +237,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, u_int16_t rtp_port; struct ip_conntrack_expect *rtp_exp; struct ip_conntrack_expect *rtcp_exp; + typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp; /* Read RTP or RTCP address */ if (!get_h245_addr(*data, addr, &ip, &port) || @@ -279,11 +280,11 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, rtcp_exp->flags = 0; if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) { + ct->tuplehash[!dir].tuple.dst.ip && + (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) { /* NAT needed */ - ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff, - addr, port, rtp_port, rtp_exp, - rtcp_exp); + ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + addr, port, rtp_port, rtp_exp, rtcp_exp); } else { /* Conntrack only */ rtp_exp->expectfn = NULL; rtcp_exp->expectfn = NULL; @@ -328,6 +329,7 @@ static int expect_t120(struct sk_buff **pskb, __be32 ip; u_int16_t port; struct ip_conntrack_expect *exp = NULL; + typeof(nat_t120_hook) nat_t120; /* Read T.120 address */ if (!get_h245_addr(*data, addr, &ip, &port) || @@ -350,10 +352,11 @@ static int expect_t120(struct sk_buff **pskb, exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */ if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) { + ct->tuplehash[!dir].tuple.dst.ip && + (nat_t120 = rcu_dereference(nat_t120_hook))) { /* NAT needed */ - ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr, - port, exp); + ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr, + port, exp); } else { /* Conntrack only */ exp->expectfn = NULL; if (ip_conntrack_expect_related(exp) == 0) { @@ -651,6 +654,7 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct, __be32 ip; u_int16_t port; struct ip_conntrack_expect *exp = NULL; + typeof(nat_h245_hook) nat_h245; /* Read h245Address */ if (!get_h225_addr(*data, addr, &ip, &port) || @@ -673,10 +677,11 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct, exp->flags = 0; if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) { + ct->tuplehash[!dir].tuple.dst.ip && + (nat_h245 = rcu_dereference(nat_h245_hook))) { /* NAT needed */ - ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr, - port, exp); + ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr, + port, exp); } else { /* Conntrack only */ exp->expectfn = ip_conntrack_h245_expect; @@ -712,6 +717,7 @@ static int expect_callforwarding(struct sk_buff **pskb, __be32 ip; u_int16_t port; struct ip_conntrack_expect *exp = NULL; + typeof(nat_callforwarding_hook) nat_callforwarding; /* Read alternativeAddress */ if (!get_h225_addr(*data, addr, &ip, &port) || port == 0) @@ -759,10 +765,11 @@ static int expect_callforwarding(struct sk_buff **pskb, exp->flags = 0; if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) { + ct->tuplehash[!dir].tuple.dst.ip && + (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) { /* Need NAT */ - ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff, - addr, port, exp); + ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, + addr, port, exp); } else { /* Conntrack only */ exp->expectfn = ip_conntrack_q931_expect; @@ -793,6 +800,7 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, int i; __be32 ip; u_int16_t port; + typeof(set_h225_addr_hook) set_h225_addr; DEBUGP("ip_ct_q931: Setup\n"); @@ -803,8 +811,10 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, return -1; } + set_h225_addr = rcu_dereference(set_h225_addr_hook); + if ((setup->options & eSetup_UUIE_destCallSignalAddress) && - (set_h225_addr_hook) && + (set_h225_addr) && get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) && ip != ct->tuplehash[!dir].tuple.src.ip) { DEBUGP("ip_ct_q931: set destCallSignalAddress " @@ -812,17 +822,17 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, NIPQUAD(ip), port, NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); - ret = set_h225_addr_hook(pskb, data, dataoff, - &setup->destCallSignalAddress, - ct->tuplehash[!dir].tuple.src.ip, - ntohs(ct->tuplehash[!dir].tuple.src. - u.tcp.port)); + ret = set_h225_addr(pskb, data, dataoff, + &setup->destCallSignalAddress, + ct->tuplehash[!dir].tuple.src.ip, + ntohs(ct->tuplehash[!dir].tuple.src. + u.tcp.port)); if (ret < 0) return -1; } if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && - (set_h225_addr_hook) && + (set_h225_addr) && get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port) && ip != ct->tuplehash[!dir].tuple.dst.ip) { DEBUGP("ip_ct_q931: set sourceCallSignalAddress " @@ -830,11 +840,11 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, NIPQUAD(ip), port, NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); - ret = set_h225_addr_hook(pskb, data, dataoff, - &setup->sourceCallSignalAddress, - ct->tuplehash[!dir].tuple.dst.ip, - ntohs(ct->tuplehash[!dir].tuple.dst. - u.tcp.port)); + ret = set_h225_addr(pskb, data, dataoff, + &setup->sourceCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + ntohs(ct->tuplehash[!dir].tuple.dst. + u.tcp.port)); if (ret < 0) return -1; } @@ -1231,6 +1241,7 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct, __be32 ip; u_int16_t port; struct ip_conntrack_expect *exp; + typeof(nat_q931_hook) nat_q931; /* Look for the first related address */ for (i = 0; i < count; i++) { @@ -1258,9 +1269,9 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct, exp->mask.dst.protonum = 0xFF; exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */ - if (nat_q931_hook) { /* Need NAT */ - ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i, - port, exp); + nat_q931 = rcu_dereference(nat_q931_hook); + if (nat_q931) { /* Need NAT */ + ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp); } else { /* Conntrack only */ exp->expectfn = ip_conntrack_q931_expect; @@ -1288,11 +1299,14 @@ static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, GatekeeperRequest * grq) { + typeof(set_ras_addr_hook) set_ras_addr; + DEBUGP("ip_ct_ras: GRQ\n"); - if (set_ras_addr_hook) /* NATed */ - return set_ras_addr_hook(pskb, ct, ctinfo, data, - &grq->rasAddress, 1); + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr) /* NATed */ + return set_ras_addr(pskb, ct, ctinfo, data, + &grq->rasAddress, 1); return 0; } @@ -1362,6 +1376,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, { struct ip_ct_h323_master *info = &ct->help.ct_h323_info; int ret; + typeof(set_ras_addr_hook) set_ras_addr; DEBUGP("ip_ct_ras: RRQ\n"); @@ -1371,10 +1386,11 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, if (ret < 0) return -1; - if (set_ras_addr_hook) { - ret = set_ras_addr_hook(pskb, ct, ctinfo, data, - rrq->rasAddress.item, - rrq->rasAddress.count); + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr) { + ret = set_ras_addr(pskb, ct, ctinfo, data, + rrq->rasAddress.item, + rrq->rasAddress.count); if (ret < 0) return -1; } @@ -1397,13 +1413,15 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, int dir = CTINFO2DIR(ctinfo); int ret; struct ip_conntrack_expect *exp; + typeof(set_sig_addr_hook) set_sig_addr; DEBUGP("ip_ct_ras: RCF\n"); - if (set_sig_addr_hook) { - ret = set_sig_addr_hook(pskb, ct, ctinfo, data, - rcf->callSignalAddress.item, - rcf->callSignalAddress.count); + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + rcf->callSignalAddress.item, + rcf->callSignalAddress.count); if (ret < 0) return -1; } @@ -1448,13 +1466,15 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, struct ip_ct_h323_master *info = &ct->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); int ret; + typeof(set_sig_addr_hook) set_sig_addr; DEBUGP("ip_ct_ras: URQ\n"); - if (set_sig_addr_hook) { - ret = set_sig_addr_hook(pskb, ct, ctinfo, data, - urq->callSignalAddress.item, - urq->callSignalAddress.count); + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + urq->callSignalAddress.item, + urq->callSignalAddress.count); if (ret < 0) return -1; } @@ -1479,28 +1499,30 @@ static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct, int dir = CTINFO2DIR(ctinfo); __be32 ip; u_int16_t port; + typeof(set_h225_addr_hook) set_h225_addr; DEBUGP("ip_ct_ras: ARQ\n"); + set_h225_addr = rcu_dereference(set_h225_addr_hook); if ((arq->options & eAdmissionRequest_destCallSignalAddress) && get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && ip == ct->tuplehash[dir].tuple.src.ip && - port == info->sig_port[dir] && set_h225_addr_hook) { + port == info->sig_port[dir] && set_h225_addr) { /* Answering ARQ */ - return set_h225_addr_hook(pskb, data, 0, - &arq->destCallSignalAddress, - ct->tuplehash[!dir].tuple.dst.ip, - info->sig_port[!dir]); + return set_h225_addr(pskb, data, 0, + &arq->destCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + info->sig_port[!dir]); } if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && - ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) { + ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) { /* Calling ARQ */ - return set_h225_addr_hook(pskb, data, 0, - &arq->srcCallSignalAddress, - ct->tuplehash[!dir].tuple.dst.ip, - port); + return set_h225_addr(pskb, data, 0, + &arq->srcCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + port); } return 0; @@ -1516,6 +1538,7 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, __be32 ip; u_int16_t port; struct ip_conntrack_expect *exp; + typeof(set_sig_addr_hook) set_sig_addr; DEBUGP("ip_ct_ras: ACF\n"); @@ -1523,10 +1546,10 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, return 0; if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ - if (set_sig_addr_hook) - return set_sig_addr_hook(pskb, ct, ctinfo, data, - &acf->destCallSignalAddress, - 1); + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr) + return set_sig_addr(pskb, ct, ctinfo, data, + &acf->destCallSignalAddress, 1); return 0; } @@ -1566,11 +1589,14 @@ static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, LocationRequest * lrq) { + typeof(set_ras_addr_hook) set_ras_addr; + DEBUGP("ip_ct_ras: LRQ\n"); - if (set_ras_addr_hook) - return set_ras_addr_hook(pskb, ct, ctinfo, data, - &lrq->replyAddress, 1); + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr) + return set_ras_addr(pskb, ct, ctinfo, data, + &lrq->replyAddress, 1); return 0; } @@ -1629,20 +1655,24 @@ static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct, unsigned char **data, InfoRequestResponse * irr) { int ret; + typeof(set_ras_addr_hook) set_ras_addr; + typeof(set_sig_addr_hook) set_sig_addr; DEBUGP("ip_ct_ras: IRR\n"); - if (set_ras_addr_hook) { - ret = set_ras_addr_hook(pskb, ct, ctinfo, data, - &irr->rasAddress, 1); + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr) { + ret = set_ras_addr(pskb, ct, ctinfo, data, + &irr->rasAddress, 1); if (ret < 0) return -1; } - if (set_sig_addr_hook) { - ret = set_sig_addr_hook(pskb, ct, ctinfo, data, - irr->callSignalAddress.item, - irr->callSignalAddress.count); + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + irr->callSignalAddress.item, + irr->callSignalAddress.count); if (ret < 0) return -1; } diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index a5c057bcecf4..4d19373bbf0d 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -124,6 +124,8 @@ EXPORT_SYMBOL(pptp_msg_name); static void pptp_expectfn(struct ip_conntrack *ct, struct ip_conntrack_expect *exp) { + typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn; + DEBUGP("increasing timeouts\n"); /* increase timeout of GRE data channel conntrack entry */ @@ -133,7 +135,9 @@ static void pptp_expectfn(struct ip_conntrack *ct, /* Can you see how rusty this code is, compared with the pre-2.6.11 * one? That's what happened to my shiny newnat of 2002 ;( -HW */ - if (!ip_nat_pptp_hook_expectfn) { + rcu_read_lock(); + ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn); + if (!ip_nat_pptp_expectfn) { struct ip_conntrack_tuple inv_t; struct ip_conntrack_expect *exp_other; @@ -153,8 +157,9 @@ static void pptp_expectfn(struct ip_conntrack *ct, } } else { /* we need more than simple inversion */ - ip_nat_pptp_hook_expectfn(ct, exp); + ip_nat_pptp_expectfn(ct, exp); } + rcu_read_unlock(); } static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) @@ -226,6 +231,7 @@ exp_gre(struct ip_conntrack *ct, { struct ip_conntrack_expect *exp_orig, *exp_reply; int ret = 1; + typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre; exp_orig = ip_conntrack_expect_alloc(ct); if (exp_orig == NULL) @@ -262,8 +268,9 @@ exp_gre(struct ip_conntrack *ct, exp_reply->tuple.dst.u.gre.key = peer_callid; exp_reply->tuple.dst.protonum = IPPROTO_GRE; - if (ip_nat_pptp_hook_exp_gre) - ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); + ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre); + if (ip_nat_pptp_exp_gre) + ip_nat_pptp_exp_gre(exp_orig, exp_reply); if (ip_conntrack_expect_related(exp_orig) != 0) goto out_put_both; if (ip_conntrack_expect_related(exp_reply) != 0) @@ -303,6 +310,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; u_int16_t msg; __be16 cid = 0, pcid = 0; + typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound; msg = ntohs(ctlh->messageType); DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); @@ -402,9 +410,9 @@ pptp_inbound_pkt(struct sk_buff **pskb, goto invalid; } - if (ip_nat_pptp_hook_inbound) - return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, - pptpReq); + ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound); + if (ip_nat_pptp_inbound) + return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq); return NF_ACCEPT; invalid: @@ -427,6 +435,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; u_int16_t msg; __be16 cid = 0, pcid = 0; + typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound; msg = ntohs(ctlh->messageType); DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); @@ -492,9 +501,9 @@ pptp_outbound_pkt(struct sk_buff **pskb, goto invalid; } - if (ip_nat_pptp_hook_outbound) - return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, - pptpReq); + ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound); + if (ip_nat_pptp_outbound) + return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq); return NF_ACCEPT; invalid: diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index 75f7c3db1619..91832eca4106 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c @@ -114,6 +114,7 @@ static int help(struct sk_buff **pskb, u_int16_t dcc_port; int i, ret = NF_ACCEPT; char *addr_beg_p, *addr_end_p; + typeof(ip_nat_irc_hook) ip_nat_irc; DEBUGP("entered\n"); @@ -222,11 +223,12 @@ static int help(struct sk_buff **pskb, { .tcp = { htons(0xFFFF) } }, 0xFF }}); exp->expectfn = NULL; exp->flags = 0; - if (ip_nat_irc_hook) - ret = ip_nat_irc_hook(pskb, ctinfo, - addr_beg_p - ib_ptr, - addr_end_p - addr_beg_p, - exp); + ip_nat_irc = rcu_dereference(ip_nat_irc_hook); + if (ip_nat_irc) + ret = ip_nat_irc(pskb, ctinfo, + addr_beg_p - ib_ptr, + addr_end_p - addr_beg_p, + exp); else if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; ip_conntrack_expect_put(exp); diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index f4f75995a9e4..bf423db4ed46 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -308,6 +308,7 @@ static int set_expected_rtp(struct sk_buff **pskb, struct ip_conntrack_expect *exp; enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); int ret; + typeof(ip_nat_sdp_hook) ip_nat_sdp; exp = ip_conntrack_expect_alloc(ct); if (exp == NULL) @@ -328,8 +329,9 @@ static int set_expected_rtp(struct sk_buff **pskb, exp->expectfn = NULL; exp->flags = 0; - if (ip_nat_sdp_hook) - ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr); + ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook); + if (ip_nat_sdp) + ret = ip_nat_sdp(pskb, ctinfo, exp, dptr); else { if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; @@ -351,6 +353,7 @@ static int sip_help(struct sk_buff **pskb, int matchoff, matchlen; __be32 ipaddr; u_int16_t port; + typeof(ip_nat_sip_hook) ip_nat_sip; /* No Data ? */ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); @@ -368,8 +371,9 @@ static int sip_help(struct sk_buff **pskb, goto out; } - if (ip_nat_sip_hook) { - if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) { + ip_nat_sip = rcu_dereference(ip_nat_sip_hook); + if (ip_nat_sip) { + if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) { ret = NF_DROP; goto out; } diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index fe0b634dd377..ef56de2eff0c 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c @@ -50,6 +50,7 @@ static int tftp_help(struct sk_buff **pskb, struct tftphdr _tftph, *tfh; struct ip_conntrack_expect *exp; unsigned int ret = NF_ACCEPT; + typeof(ip_nat_tftp_hook) ip_nat_tftp; tfh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), @@ -81,8 +82,9 @@ static int tftp_help(struct sk_buff **pskb, DEBUGP("expect: "); DUMP_TUPLE(&exp->tuple); DUMP_TUPLE(&exp->mask); - if (ip_nat_tftp_hook) - ret = ip_nat_tftp_hook(pskb, ctinfo, exp); + ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook); + if (ip_nat_tftp) + ret = ip_nat_tftp(pskb, ctinfo, exp); else if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; ip_conntrack_expect_put(exp); diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c index 3a888715bbf3..85df1a9aed33 100644 --- a/net/ipv4/netfilter/ip_nat_amanda.c +++ b/net/ipv4/netfilter/ip_nat_amanda.c @@ -70,15 +70,14 @@ static unsigned int help(struct sk_buff **pskb, static void __exit ip_nat_amanda_fini(void) { - ip_nat_amanda_hook = NULL; - /* Make sure noone calls it, meanwhile. */ - synchronize_net(); + rcu_assign_pointer(ip_nat_amanda_hook, NULL); + synchronize_rcu(); } static int __init ip_nat_amanda_init(void) { - BUG_ON(ip_nat_amanda_hook); - ip_nat_amanda_hook = help; + BUG_ON(rcu_dereference(ip_nat_amanda_hook)); + rcu_assign_pointer(ip_nat_amanda_hook, help); return 0; } diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c index a71c233d8112..913960e1380f 100644 --- a/net/ipv4/netfilter/ip_nat_ftp.c +++ b/net/ipv4/netfilter/ip_nat_ftp.c @@ -156,15 +156,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb, static void __exit ip_nat_ftp_fini(void) { - ip_nat_ftp_hook = NULL; - /* Make sure noone calls it, meanwhile. */ - synchronize_net(); + rcu_assign_pointer(ip_nat_ftp_hook, NULL); + synchronize_rcu(); } static int __init ip_nat_ftp_init(void) { - BUG_ON(ip_nat_ftp_hook); - ip_nat_ftp_hook = ip_nat_ftp; + BUG_ON(rcu_dereference(ip_nat_ftp_hook)); + rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp); return 0; } diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c index 4a7d34466ee2..bdc99ef6159e 100644 --- a/net/ipv4/netfilter/ip_nat_helper_h323.c +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c @@ -563,25 +563,25 @@ static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct, /****************************************************************************/ static int __init init(void) { - BUG_ON(set_h245_addr_hook != NULL); - BUG_ON(set_h225_addr_hook != NULL); - BUG_ON(set_sig_addr_hook != NULL); - BUG_ON(set_ras_addr_hook != NULL); - BUG_ON(nat_rtp_rtcp_hook != NULL); - BUG_ON(nat_t120_hook != NULL); - BUG_ON(nat_h245_hook != NULL); - BUG_ON(nat_callforwarding_hook != NULL); - BUG_ON(nat_q931_hook != NULL); - - set_h245_addr_hook = set_h245_addr; - set_h225_addr_hook = set_h225_addr; - set_sig_addr_hook = set_sig_addr; - set_ras_addr_hook = set_ras_addr; - nat_rtp_rtcp_hook = nat_rtp_rtcp; - nat_t120_hook = nat_t120; - nat_h245_hook = nat_h245; - nat_callforwarding_hook = nat_callforwarding; - nat_q931_hook = nat_q931; + BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL); + BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL); + BUG_ON(rcu_dereference(nat_t120_hook) != NULL); + BUG_ON(rcu_dereference(nat_h245_hook) != NULL); + BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL); + BUG_ON(rcu_dereference(nat_q931_hook) != NULL); + + rcu_assign_pointer(set_h245_addr_hook, set_h245_addr); + rcu_assign_pointer(set_h225_addr_hook, set_h225_addr); + rcu_assign_pointer(set_sig_addr_hook, set_sig_addr); + rcu_assign_pointer(set_ras_addr_hook, set_ras_addr); + rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp); + rcu_assign_pointer(nat_t120_hook, nat_t120); + 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("ip_nat_h323: init success\n"); return 0; @@ -590,16 +590,16 @@ static int __init init(void) /****************************************************************************/ static void __exit fini(void) { - set_h245_addr_hook = NULL; - set_h225_addr_hook = NULL; - set_sig_addr_hook = NULL; - set_ras_addr_hook = NULL; - nat_rtp_rtcp_hook = NULL; - nat_t120_hook = NULL; - nat_h245_hook = NULL; - nat_callforwarding_hook = NULL; - nat_q931_hook = NULL; - synchronize_net(); + rcu_assign_pointer(set_h245_addr_hook, NULL); + rcu_assign_pointer(set_h225_addr_hook, NULL); + rcu_assign_pointer(set_sig_addr_hook, NULL); + rcu_assign_pointer(set_ras_addr_hook, NULL); + rcu_assign_pointer(nat_rtp_rtcp_hook, NULL); + rcu_assign_pointer(nat_t120_hook, NULL); + rcu_assign_pointer(nat_h245_hook, NULL); + rcu_assign_pointer(nat_callforwarding_hook, NULL); + rcu_assign_pointer(nat_q931_hook, NULL); + synchronize_rcu(); } /****************************************************************************/ diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index acf55d863100..ec957bbb5366 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -315,17 +315,17 @@ static int __init ip_nat_helper_pptp_init(void) if (ret < 0) return ret; - BUG_ON(ip_nat_pptp_hook_outbound); - ip_nat_pptp_hook_outbound = &pptp_outbound_pkt; + BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound)); + rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt); - BUG_ON(ip_nat_pptp_hook_inbound); - ip_nat_pptp_hook_inbound = &pptp_inbound_pkt; + BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound)); + rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt); - BUG_ON(ip_nat_pptp_hook_exp_gre); - ip_nat_pptp_hook_exp_gre = &pptp_exp_gre; + BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre)); + rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre); - BUG_ON(ip_nat_pptp_hook_expectfn); - ip_nat_pptp_hook_expectfn = &pptp_nat_expected; + BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn)); + rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected); printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); return 0; @@ -335,14 +335,13 @@ static void __exit ip_nat_helper_pptp_fini(void) { DEBUGP("cleanup_module\n" ); - ip_nat_pptp_hook_expectfn = NULL; - ip_nat_pptp_hook_exp_gre = NULL; - ip_nat_pptp_hook_inbound = NULL; - ip_nat_pptp_hook_outbound = NULL; + rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL); + rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL); + rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL); + rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL); + synchronize_rcu(); ip_nat_proto_gre_fini(); - /* Make sure noone calls it, meanwhile */ - synchronize_net(); printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); } diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c index a767123e082c..feb26b48f1d5 100644 --- a/net/ipv4/netfilter/ip_nat_irc.c +++ b/net/ipv4/netfilter/ip_nat_irc.c @@ -98,15 +98,14 @@ static unsigned int help(struct sk_buff **pskb, static void __exit ip_nat_irc_fini(void) { - ip_nat_irc_hook = NULL; - /* Make sure noone calls it, meanwhile. */ - synchronize_net(); + rcu_assign_pointer(ip_nat_irc_hook, NULL); + synchronize_rcu(); } static int __init ip_nat_irc_init(void) { - BUG_ON(ip_nat_irc_hook); - ip_nat_irc_hook = help; + BUG_ON(rcu_dereference(ip_nat_irc_hook)); + rcu_assign_pointer(ip_nat_irc_hook, help); return 0; } diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c index 71fc2730a007..9fad98099532 100644 --- a/net/ipv4/netfilter/ip_nat_sip.c +++ b/net/ipv4/netfilter/ip_nat_sip.c @@ -230,18 +230,17 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, static void __exit fini(void) { - ip_nat_sip_hook = NULL; - ip_nat_sdp_hook = NULL; - /* Make sure noone calls it, meanwhile. */ - synchronize_net(); + rcu_assign_pointer(ip_nat_sip_hook, NULL); + rcu_assign_pointer(ip_nat_sdp_hook, NULL); + synchronize_rcu(); } static int __init init(void) { - BUG_ON(ip_nat_sip_hook); - BUG_ON(ip_nat_sdp_hook); - ip_nat_sip_hook = ip_nat_sip; - ip_nat_sdp_hook = ip_nat_sdp; + BUG_ON(rcu_dereference(ip_nat_sip_hook)); + BUG_ON(rcu_dereference(ip_nat_sdp_hook)); + rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip); + rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp); return 0; } diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c index 94a78015451c..604793536fc1 100644 --- a/net/ipv4/netfilter/ip_nat_tftp.c +++ b/net/ipv4/netfilter/ip_nat_tftp.c @@ -55,15 +55,14 @@ static unsigned int help(struct sk_buff **pskb, static void __exit ip_nat_tftp_fini(void) { - ip_nat_tftp_hook = NULL; - /* Make sure noone calls it, meanwhile. */ - synchronize_net(); + rcu_assign_pointer(ip_nat_tftp_hook, NULL); + synchronize_rcu(); } static int __init ip_nat_tftp_init(void) { - BUG_ON(ip_nat_tftp_hook); - ip_nat_tftp_hook = help; + BUG_ON(rcu_dereference(ip_nat_tftp_hook)); + rcu_assign_pointer(ip_nat_tftp_hook, help); return 0; } diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 05cb78ca90ae..2d2350152b90 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -369,9 +369,9 @@ static int help(struct sk_buff **pskb, struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; struct nf_conntrack_expect *exp; struct nf_conntrack_man cmd = {}; - unsigned int i; int found = 0, ends_in_nl; + typeof(nf_nat_ftp_hook) nf_nat_ftp; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED @@ -520,9 +520,10 @@ static int help(struct sk_buff **pskb, /* Now, NAT might want to mangle the packet, and register the * (possibly changed) expectation itself. */ - if (nf_nat_ftp_hook) - ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype, - matchoff, matchlen, exp, &seq); + nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); + if (nf_nat_ftp) + ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, + matchoff, matchlen, exp, &seq); else { /* Can't expect this? Best to drop packet now. */ if (nf_conntrack_expect_related(exp) != 0) -- cgit v1.2.3-70-g09d2 From 9d5b8baa4e9ace9be113c6151aaeeb3c07a26fc8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:26 +0100 Subject: [NETFILTER]: sip conntrack: minor cleanup - Use enum for header field enumeration - Use numerical value instead of pointer to header info structure to identify headers, unexport ct_sip_hdrs - group SIP and SDP entries in header info structure - remove double forward declaration of ct_sip_get_info Signed-off-by: Patrick McHardy --- include/linux/netfilter_ipv4/ip_conntrack_sip.h | 28 +++++------- net/ipv4/netfilter/ip_conntrack_sip.c | 60 +++++++++++++------------ net/ipv4/netfilter/ip_nat_sip.c | 30 ++++++------- 3 files changed, 55 insertions(+), 63 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h index 913dad66c0fb..2a15eb51fd6b 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h @@ -5,23 +5,15 @@ #define SIP_PORT 5060 #define SIP_TIMEOUT 3600 -#define POS_VIA 0 -#define POS_CONTACT 1 -#define POS_CONTENT 2 -#define POS_MEDIA 3 -#define POS_OWNER 4 -#define POS_CONNECTION 5 -#define POS_REQ_HEADER 6 -#define POS_SDP_HEADER 7 - -struct sip_header_nfo { - const char *lname; - const char *sname; - const char *ln_str; - size_t lnlen; - size_t snlen; - size_t ln_strlen; - int (*match_len)(const char *, const char *, int *); +enum sip_header_pos { + POS_REQ_HEADER, + POS_VIA, + POS_CONTACT, + POS_CONTENT, + POS_MEDIA, + POS_OWNER, + POS_CONNECTION, + POS_SDP_HEADER, }; extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb, @@ -36,7 +28,7 @@ extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb, extern int ct_sip_get_info(const char *dptr, size_t dlen, unsigned int *matchoff, unsigned int *matchlen, - struct sip_header_nfo *hnfo); + enum sip_header_pos pos); extern int ct_sip_lnlen(const char *line, const char *limit); extern const char *ct_sip_search(const char *needle, const char *haystack, size_t needle_len, size_t haystack_len); diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index bf423db4ed46..cc3176581667 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -52,20 +52,32 @@ unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb, const char *dptr); EXPORT_SYMBOL_GPL(ip_nat_sdp_hook); -int ct_sip_get_info(const char *dptr, size_t dlen, - unsigned int *matchoff, - unsigned int *matchlen, - struct sip_header_nfo *hnfo); -EXPORT_SYMBOL_GPL(ct_sip_get_info); - - static int digits_len(const char *dptr, const char *limit, int *shift); static int epaddr_len(const char *dptr, const char *limit, int *shift); static int skp_digits_len(const char *dptr, const char *limit, int *shift); static int skp_epaddr_len(const char *dptr, const char *limit, int *shift); -struct sip_header_nfo ct_sip_hdrs[] = { - { /* Via header */ +struct sip_header_nfo { + const char *lname; + const char *sname; + const char *ln_str; + size_t lnlen; + size_t snlen; + size_t ln_strlen; + int (*match_len)(const char *, const char *, int *); +}; + +static struct sip_header_nfo ct_sip_hdrs[] = { + [POS_REQ_HEADER] = { /* SIP Requests headers */ + .lname = "sip:", + .lnlen = sizeof("sip:") - 1, + .sname = "sip:", + .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */ + .ln_str = "@", + .ln_strlen = sizeof("@") - 1, + .match_len = epaddr_len + }, + [POS_VIA] = { /* SIP Via header */ .lname = "Via:", .lnlen = sizeof("Via:") - 1, .sname = "\r\nv:", @@ -74,7 +86,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof("UDP ") - 1, .match_len = epaddr_len, }, - { /* Contact header */ + [POS_CONTACT] = { /* SIP Contact header */ .lname = "Contact:", .lnlen = sizeof("Contact:") - 1, .sname = "\r\nm:", @@ -83,7 +95,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof("sip:") - 1, .match_len = skp_epaddr_len }, - { /* Content length header */ + [POS_CONTENT] = { /* SIP Content length header */ .lname = "Content-Length:", .lnlen = sizeof("Content-Length:") - 1, .sname = "\r\nl:", @@ -92,7 +104,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof(":") - 1, .match_len = skp_digits_len }, - { /* SDP media info */ + [POS_MEDIA] = { /* SDP media info */ .lname = "\nm=", .lnlen = sizeof("\nm=") - 1, .sname = "\rm=", @@ -101,7 +113,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof("audio ") - 1, .match_len = digits_len }, - { /* SDP owner address*/ + [POS_OWNER] = { /* SDP owner address*/ .lname = "\no=", .lnlen = sizeof("\no=") - 1, .sname = "\ro=", @@ -110,7 +122,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof("IN IP4 ") - 1, .match_len = epaddr_len }, - { /* SDP connection info */ + [POS_CONNECTION] = { /* SDP connection info */ .lname = "\nc=", .lnlen = sizeof("\nc=") - 1, .sname = "\rc=", @@ -119,16 +131,7 @@ struct sip_header_nfo ct_sip_hdrs[] = { .ln_strlen = sizeof("IN IP4 ") - 1, .match_len = epaddr_len }, - { /* Requests headers */ - .lname = "sip:", - .lnlen = sizeof("sip:") - 1, - .sname = "sip:", - .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */ - .ln_str = "@", - .ln_strlen = sizeof("@") - 1, - .match_len = epaddr_len - }, - { /* SDP version header */ + [POS_SDP_HEADER] = { /* SDP version header */ .lname = "\nv=", .lnlen = sizeof("\nv=") - 1, .sname = "\rv=", @@ -138,7 +141,6 @@ struct sip_header_nfo ct_sip_hdrs[] = { .match_len = digits_len } }; -EXPORT_SYMBOL_GPL(ct_sip_hdrs); /* get line lenght until first CR or LF seen. */ int ct_sip_lnlen(const char *line, const char *limit) @@ -263,8 +265,9 @@ static int skp_epaddr_len(const char *dptr, const char *limit, int *shift) int ct_sip_get_info(const char *dptr, size_t dlen, unsigned int *matchoff, unsigned int *matchlen, - struct sip_header_nfo *hnfo) + enum sip_header_pos pos) { + struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos]; const char *limit, *aux, *k = dptr; int shift = 0; @@ -298,6 +301,7 @@ int ct_sip_get_info(const char *dptr, size_t dlen, DEBUGP("%s header not found.\n", hnfo->lname); return 0; } +EXPORT_SYMBOL_GPL(ct_sip_get_info); static int set_expected_rtp(struct sk_buff **pskb, struct ip_conntrack *ct, @@ -393,7 +397,7 @@ static int sip_help(struct sk_buff **pskb, } /* Get ip and port address from SDP packet. */ if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, - &ct_sip_hdrs[POS_CONNECTION]) > 0) { + POS_CONNECTION) > 0) { /* We'll drop only if there are parse problems. */ if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr, @@ -402,7 +406,7 @@ static int sip_help(struct sk_buff **pskb, goto out; } if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, - &ct_sip_hdrs[POS_MEDIA]) > 0) { + POS_MEDIA) > 0) { port = simple_strtoul(dptr + matchoff, NULL, 10); if (port < 1024) { diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c index 9fad98099532..47097aac63d8 100644 --- a/net/ipv4/netfilter/ip_nat_sip.c +++ b/net/ipv4/netfilter/ip_nat_sip.c @@ -29,18 +29,16 @@ MODULE_DESCRIPTION("SIP NAT helper"); #define DEBUGP(format, args...) #endif -extern struct sip_header_nfo ct_sip_hdrs[]; - static unsigned int mangle_sip_packet(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, struct ip_conntrack *ct, const char **dptr, size_t dlen, char *buffer, int bufflen, - struct sip_header_nfo *hnfo) + enum sip_header_pos pos) { unsigned int matchlen, matchoff; - if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0) + if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0) return 0; if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, @@ -80,14 +78,13 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, if ((ctinfo) < IP_CT_IS_REPLY) { mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, - &ct_sip_hdrs[POS_CONTACT]); + buffer, bufflen, POS_CONTACT); return 1; } if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_VIA])) + buffer, bufflen, POS_VIA)) return 0; /* This search should ignore case, but later.. */ @@ -102,25 +99,24 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, return mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, - &ct_sip_hdrs[POS_CONTACT]); + buffer, bufflen, POS_CONTACT); } if ((ctinfo) < IP_CT_IS_REPLY) { if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_VIA])) + buffer, bufflen, POS_VIA)) return 0; /* Mangle Contact if exists only. - watch udp_nat_mangle()! */ mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]); + buffer, bufflen, POS_CONTACT); return 1; } /* This mangle requests headers. */ return mangle_sip_packet(pskb, ctinfo, ct, dptr, ct_sip_lnlen(*dptr, *dptr + (*pskb)->len - dataoff), - buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]); + buffer, bufflen, POS_REQ_HEADER); } static int mangle_content_len(struct sk_buff **pskb, @@ -136,7 +132,7 @@ static int mangle_content_len(struct sk_buff **pskb, /* Get actual SDP lenght */ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, - &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) { + &matchlen, POS_SDP_HEADER) > 0) { /* since ct_sip_get_info() give us a pointer passing 'v=' we need to add 2 bytes in this count. */ @@ -144,7 +140,7 @@ static int mangle_content_len(struct sk_buff **pskb, /* Now, update SDP lenght */ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, - &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) { + &matchlen, POS_CONTENT) > 0) { bufflen = sprintf(buffer, "%u", c_len); @@ -170,17 +166,17 @@ static unsigned int mangle_sdp(struct sk_buff **pskb, /* Mangle owner and contact info. */ bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) + buffer, bufflen, POS_OWNER)) return 0; if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION])) + buffer, bufflen, POS_CONNECTION)) return 0; /* Mangle media port. */ bufflen = sprintf(buffer, "%u", port); if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, - buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) + buffer, bufflen, POS_MEDIA)) return 0; return mangle_content_len(pskb, ctinfo, ct, dptr); -- cgit v1.2.3-70-g09d2 From 40883e8184947879f135605a05c0764c60656cc5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:27 +0100 Subject: [NETFILTER]: sip conntrack: do case insensitive SIP header search SIP headers are generally case-insensitive, only SDP headers are case sensitive. Signed-off-by: Patrick McHardy --- include/linux/netfilter_ipv4/ip_conntrack_sip.h | 3 ++- net/ipv4/netfilter/ip_conntrack_sip.c | 20 ++++++++++++++++---- net/ipv4/netfilter/ip_nat_sip.c | 7 ++++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h index 2a15eb51fd6b..51c65ac18c57 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h @@ -31,6 +31,7 @@ extern int ct_sip_get_info(const char *dptr, size_t dlen, enum sip_header_pos pos); extern int ct_sip_lnlen(const char *line, const char *limit); extern const char *ct_sip_search(const char *needle, const char *haystack, - size_t needle_len, size_t haystack_len); + size_t needle_len, size_t haystack_len, + int case_sensitive); #endif /* __KERNEL__ */ #endif /* __IP_CONNTRACK_SIP_H__ */ diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index cc3176581667..a9c0d1d3e56f 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -64,6 +64,7 @@ struct sip_header_nfo { size_t lnlen; size_t snlen; size_t ln_strlen; + int case_sensitive; int (*match_len)(const char *, const char *, int *); }; @@ -105,6 +106,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = { .match_len = skp_digits_len }, [POS_MEDIA] = { /* SDP media info */ + .case_sensitive = 1, .lname = "\nm=", .lnlen = sizeof("\nm=") - 1, .sname = "\rm=", @@ -114,6 +116,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = { .match_len = digits_len }, [POS_OWNER] = { /* SDP owner address*/ + .case_sensitive = 1, .lname = "\no=", .lnlen = sizeof("\no=") - 1, .sname = "\ro=", @@ -123,6 +126,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = { .match_len = epaddr_len }, [POS_CONNECTION] = { /* SDP connection info */ + .case_sensitive = 1, .lname = "\nc=", .lnlen = sizeof("\nc=") - 1, .sname = "\rc=", @@ -132,6 +136,7 @@ static struct sip_header_nfo ct_sip_hdrs[] = { .match_len = epaddr_len }, [POS_SDP_HEADER] = { /* SDP version header */ + .case_sensitive = 1, .lname = "\nv=", .lnlen = sizeof("\nv=") - 1, .sname = "\rv=", @@ -161,13 +166,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen); /* Linear string search, case sensitive. */ const char *ct_sip_search(const char *needle, const char *haystack, - size_t needle_len, size_t haystack_len) + size_t needle_len, size_t haystack_len, + int case_sensitive) { const char *limit = haystack + (haystack_len - needle_len); while (haystack <= limit) { - if (memcmp(haystack, needle, needle_len) == 0) - return haystack; + if (case_sensitive) { + if (strncmp(haystack, needle, needle_len) == 0) + return haystack; + } else { + if (strnicmp(haystack, needle, needle_len) == 0) + return haystack; + } haystack++; } return NULL; @@ -280,7 +291,8 @@ int ct_sip_get_info(const char *dptr, size_t dlen, continue; } aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen, - ct_sip_lnlen(dptr, limit)); + ct_sip_lnlen(dptr, limit), + hnfo->case_sensitive); if (!aux) { DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, hnfo->lname); diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c index 47097aac63d8..e16604c4339d 100644 --- a/net/ipv4/netfilter/ip_nat_sip.c +++ b/net/ipv4/netfilter/ip_nat_sip.c @@ -87,14 +87,15 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, buffer, bufflen, POS_VIA)) return 0; - /* This search should ignore case, but later.. */ aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1, - (*pskb)->len - dataoff); + (*pskb)->len - dataoff, 0); if (!aux) return 0; if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"), - ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) + ct_sip_lnlen(aux, + *dptr + (*pskb)->len - dataoff), + 1)) return 1; return mangle_sip_packet(pskb, ctinfo, ct, dptr, -- cgit v1.2.3-70-g09d2 From 77a78dec48386ce958196bf69f192ee76537c07d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:28 +0100 Subject: [NETFILTER]: sip conntrack: make header shortcuts optional Not every header has a shortcut, so make them optional instead of searching for the same string twice. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_sip.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index a9c0d1d3e56f..0a6a13c45b07 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -72,8 +72,6 @@ static struct sip_header_nfo ct_sip_hdrs[] = { [POS_REQ_HEADER] = { /* SIP Requests headers */ .lname = "sip:", .lnlen = sizeof("sip:") - 1, - .sname = "sip:", - .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */ .ln_str = "@", .ln_strlen = sizeof("@") - 1, .match_len = epaddr_len @@ -286,7 +284,8 @@ int ct_sip_get_info(const char *dptr, size_t dlen, while (dptr <= limit) { if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) && - (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { + (hinfo->sname == NULL || + strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { dptr++; continue; } -- cgit v1.2.3-70-g09d2 From 1b683b551209ca46ae59b29572018001db5af078 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:30 +0100 Subject: [NETFILTER]: sip conntrack: better NAT handling The NAT handling of the SIP helper has a few problems: - Request headers are only mangled in the reply direction, From/To headers not at all, which can lead to authentication failures with DNAT in case the authentication domain is the IP address - Contact headers in responses are only mangled for REGISTER responses - Headers may be mangled even though they contain addresses not participating in the connection, like alternative addresses - Packets are droppen when domain names are used where the helper expects IP addresses This patch takes a different approach, instead of fixed rules what field to mangle to what content, it adds symetric mapping of From/To/Via/Contact headers, which allows to deal properly with echoed addresses in responses and foreign addresses not belonging to the connection. Signed-off-by: Patrick McHardy --- include/linux/netfilter_ipv4/ip_conntrack_sip.h | 5 +- net/ipv4/netfilter/ip_conntrack_sip.c | 29 +++- net/ipv4/netfilter/ip_nat_sip.c | 171 ++++++++++++++---------- 3 files changed, 135 insertions(+), 70 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h index 51c65ac18c57..bef6c646defa 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h @@ -6,7 +6,10 @@ #define SIP_TIMEOUT 3600 enum sip_header_pos { - POS_REQ_HEADER, + POS_REG_REQ_URI, + POS_REQ_URI, + POS_FROM, + POS_TO, POS_VIA, POS_CONTACT, POS_CONTENT, diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index 0a6a13c45b07..3a26d63eed88 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -69,13 +69,38 @@ struct sip_header_nfo { }; static struct sip_header_nfo ct_sip_hdrs[] = { - [POS_REQ_HEADER] = { /* SIP Requests headers */ + [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */ + .lname = "sip:", + .lnlen = sizeof("sip:") - 1, + .ln_str = ":", + .ln_strlen = sizeof(":") - 1, + .match_len = epaddr_len + }, + [POS_REQ_URI] = { /* SIP request URI */ .lname = "sip:", .lnlen = sizeof("sip:") - 1, .ln_str = "@", .ln_strlen = sizeof("@") - 1, .match_len = epaddr_len }, + [POS_FROM] = { /* SIP From header */ + .lname = "From:", + .lnlen = sizeof("From:") - 1, + .sname = "\r\nf:", + .snlen = sizeof("\r\nf:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len, + }, + [POS_TO] = { /* SIP To header */ + .lname = "To:", + .lnlen = sizeof("To:") - 1, + .sname = "\r\nt:", + .snlen = sizeof("\r\nt:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len, + }, [POS_VIA] = { /* SIP Via header */ .lname = "Via:", .lnlen = sizeof("Via:") - 1, @@ -284,7 +309,7 @@ int ct_sip_get_info(const char *dptr, size_t dlen, while (dptr <= limit) { if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) && - (hinfo->sname == NULL || + (hnfo->sname == NULL || strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { dptr++; continue; diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c index e16604c4339d..6223abc924ff 100644 --- a/net/ipv4/netfilter/ip_nat_sip.c +++ b/net/ipv4/netfilter/ip_nat_sip.c @@ -29,25 +29,70 @@ MODULE_DESCRIPTION("SIP NAT helper"); #define DEBUGP(format, args...) #endif -static unsigned int mangle_sip_packet(struct sk_buff **pskb, - enum ip_conntrack_info ctinfo, - struct ip_conntrack *ct, - const char **dptr, size_t dlen, - char *buffer, int bufflen, - enum sip_header_pos pos) +struct addr_map { + struct { + char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; + char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; + unsigned int srclen, srciplen; + unsigned int dstlen, dstiplen; + } addr[IP_CT_DIR_MAX]; +}; + +static void addr_map_init(struct ip_conntrack *ct, struct addr_map *map) { - unsigned int matchlen, matchoff; + struct ip_conntrack_tuple *t; + enum ip_conntrack_dir dir; + unsigned int n; + + for (dir = 0; dir < IP_CT_DIR_MAX; dir++) { + t = &ct->tuplehash[dir].tuple; + + n = sprintf(map->addr[dir].src, "%u.%u.%u.%u", + NIPQUAD(t->src.ip)); + map->addr[dir].srciplen = n; + n += sprintf(map->addr[dir].src + n, ":%u", + ntohs(t->src.u.udp.port)); + map->addr[dir].srclen = n; + + n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u", + NIPQUAD(t->dst.ip)); + map->addr[dir].dstiplen = n; + n += sprintf(map->addr[dir].dst + n, ":%u", + ntohs(t->dst.u.udp.port)); + map->addr[dir].dstlen = n; + } +} + +static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, const char **dptr, size_t dlen, + enum sip_header_pos pos, struct addr_map *map) +{ + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + unsigned int matchlen, matchoff, addrlen; + char *addr; if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0) - return 0; + return 1; + + if ((matchlen == map->addr[dir].srciplen || + matchlen == map->addr[dir].srclen) && + memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) { + addr = map->addr[!dir].dst; + addrlen = map->addr[!dir].dstlen; + } else if ((matchlen == map->addr[dir].dstiplen || + matchlen == map->addr[dir].dstlen) && + memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) { + addr = map->addr[!dir].src; + addrlen = map->addr[!dir].srclen; + } else + return 1; if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, - matchoff, matchlen, buffer, bufflen)) + matchoff, matchlen, addr, addrlen)) return 0; - - /* We need to reload this. Thanks Patrick. */ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); return 1; + } static unsigned int ip_nat_sip(struct sk_buff **pskb, @@ -55,69 +100,61 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, struct ip_conntrack *ct, const char **dptr) { - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; - unsigned int bufflen, dataoff; - __be32 ip; - __be16 port; + enum sip_header_pos pos; + struct addr_map map; + int dataoff, datalen; dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + datalen = (*pskb)->len - dataoff; + if (datalen < sizeof("SIP/2.0") - 1) + return NF_DROP; + + addr_map_init(ct, &map); + + /* Basic rules: requests and responses. */ + if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) { + /* 10.2: Constructing the REGISTER Request: + * + * The "userinfo" and "@" components of the SIP URI MUST NOT + * be present. + */ + if (datalen >= sizeof("REGISTER") - 1 && + strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0) + pos = POS_REG_REQ_URI; + else + pos = POS_REQ_URI; + + if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map)) + return NF_DROP; + } - ip = ct->tuplehash[!dir].tuple.dst.ip; - port = ct->tuplehash[!dir].tuple.dst.u.udp.port; - bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port)); + if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) + return NF_DROP; + return NF_ACCEPT; +} + +static unsigned int mangle_sip_packet(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char **dptr, size_t dlen, + char *buffer, int bufflen, + enum sip_header_pos pos) +{ + unsigned int matchlen, matchoff; - /* short packet ? */ - if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1)) + if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0) return 0; - /* Basic rules: requests and responses. */ - if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) { - const char *aux; - - if ((ctinfo) < IP_CT_IS_REPLY) { - mangle_sip_packet(pskb, ctinfo, ct, dptr, - (*pskb)->len - dataoff, - buffer, bufflen, POS_CONTACT); - return 1; - } + if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, buffer, bufflen)) + return 0; - if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, - (*pskb)->len - dataoff, - buffer, bufflen, POS_VIA)) - return 0; - - aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1, - (*pskb)->len - dataoff, 0); - if (!aux) - return 0; - - if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"), - ct_sip_lnlen(aux, - *dptr + (*pskb)->len - dataoff), - 1)) - return 1; - - return mangle_sip_packet(pskb, ctinfo, ct, dptr, - (*pskb)->len - dataoff, - buffer, bufflen, POS_CONTACT); - } - if ((ctinfo) < IP_CT_IS_REPLY) { - if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, - (*pskb)->len - dataoff, - buffer, bufflen, POS_VIA)) - return 0; - - /* Mangle Contact if exists only. - watch udp_nat_mangle()! */ - mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, - buffer, bufflen, POS_CONTACT); - return 1; - } - /* This mangle requests headers. */ - return mangle_sip_packet(pskb, ctinfo, ct, dptr, - ct_sip_lnlen(*dptr, - *dptr + (*pskb)->len - dataoff), - buffer, bufflen, POS_REQ_HEADER); + /* We need to reload this. Thanks Patrick. */ + *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + return 1; } static int mangle_content_len(struct sk_buff **pskb, -- cgit v1.2.3-70-g09d2 From bbb3357d14f6becd156469220992ef7ab0f10e69 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Nov 2006 02:35:31 +0100 Subject: [NETFILTER]: ctnetlink: check for status attribute existence on conntrack creation Check that status flags are available in the netlink message received to create a new conntrack. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_netlink.c | 8 +++++--- net/netfilter/nf_conntrack_netlink.c | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 3d277aa869dd..d5d2efddba57 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -945,9 +945,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->timeout.expires = jiffies + ct->timeout.expires * HZ; ct->status |= IPS_CONFIRMED; - err = ctnetlink_change_status(ct, cda); - if (err < 0) - goto err; + if (cda[CTA_STATUS-1]) { + err = ctnetlink_change_status(ct, cda); + if (err < 0) + goto err; + } if (cda[CTA_PROTOINFO-1]) { err = ctnetlink_change_protoinfo(ct, cda); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 7357b8f47acd..ba77183be2f3 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -963,9 +963,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->timeout.expires = jiffies + ct->timeout.expires * HZ; ct->status |= IPS_CONFIRMED; - err = ctnetlink_change_status(ct, cda); - if (err < 0) - goto err; + if (cda[CTA_STATUS-1]) { + err = ctnetlink_change_status(ct, cda); + if (err < 0) + goto err; + } if (cda[CTA_PROTOINFO-1]) { err = ctnetlink_change_protoinfo(ct, cda); -- cgit v1.2.3-70-g09d2 From 7b621c1ea64a54f77b8a841b16dc4c9fee3ecf48 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Nov 2006 02:35:32 +0100 Subject: [NETFILTER]: ctnetlink: rework conntrack fields dumping logic on events | NEW | UPDATE | DESTROY | ----------------------------------------| tuples | Y | Y | Y | status | Y | Y | N | timeout | Y | Y | N | protoinfo | S | S | N | helper | S | S | N | mark | S | S | N | counters | F | F | Y | Leyend: Y: yes N: no S: iif the field is set F: iif overflow This patch also replace IPCT_HELPINFO by IPCT_HELPER since we want to track the helper assignation process, not the changes in the private information held by the helper. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_netlink.c | 49 +++++++++++++++++-------------- net/netfilter/nf_conntrack_netlink.c | 49 +++++++++++++++++-------------- 2 files changed, 54 insertions(+), 44 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index d5d2efddba57..5fcf91d617cd 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -320,8 +320,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, } else if (events & (IPCT_NEW | IPCT_RELATED)) { type = IPCTNL_MSG_CT_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; - /* dump everything */ - events = ~0UL; group = NFNLGRP_CONNTRACK_NEW; } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { type = IPCTNL_MSG_CT_NEW; @@ -356,28 +354,35 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0) goto nfattr_failure; NFA_NEST_END(skb, nest_parms); - - /* NAT stuff is now a status flag */ - if ((events & IPCT_STATUS || events & IPCT_NATINFO) - && ctnetlink_dump_status(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_REFRESH - && ctnetlink_dump_timeout(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_PROTOINFO - && ctnetlink_dump_protoinfo(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_HELPINFO - && ctnetlink_dump_helpinfo(skb, ct) < 0) - goto nfattr_failure; - if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || - ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) - goto nfattr_failure; + if (events & IPCT_DESTROY) { + if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || + ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) + goto nfattr_failure; + } else { + if (ctnetlink_dump_status(skb, ct) < 0) + goto nfattr_failure; - if (events & IPCT_MARK - && ctnetlink_dump_mark(skb, ct) < 0) - goto nfattr_failure; + if (ctnetlink_dump_timeout(skb, ct) < 0) + goto nfattr_failure; + + if (events & IPCT_PROTOINFO + && ctnetlink_dump_protoinfo(skb, ct) < 0) + goto nfattr_failure; + + if ((events & IPCT_HELPER || ct->helper) + && ctnetlink_dump_helpinfo(skb, ct) < 0) + goto nfattr_failure; + + if ((events & IPCT_MARK || ct->mark) + && ctnetlink_dump_mark(skb, ct) < 0) + goto nfattr_failure; + + if (events & IPCT_COUNTER_FILLING && + (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || + ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)) + goto nfattr_failure; + } nlh->nlmsg_len = skb->tail - b; nfnetlink_send(skb, 0, group, 0); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ba77183be2f3..e3a720472123 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -331,8 +331,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, } else if (events & (IPCT_NEW | IPCT_RELATED)) { type = IPCTNL_MSG_CT_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; - /* dump everything */ - events = ~0UL; group = NFNLGRP_CONNTRACK_NEW; } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { type = IPCTNL_MSG_CT_NEW; @@ -367,28 +365,35 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0) goto nfattr_failure; NFA_NEST_END(skb, nest_parms); - - /* NAT stuff is now a status flag */ - if ((events & IPCT_STATUS || events & IPCT_NATINFO) - && ctnetlink_dump_status(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_REFRESH - && ctnetlink_dump_timeout(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_PROTOINFO - && ctnetlink_dump_protoinfo(skb, ct) < 0) - goto nfattr_failure; - if (events & IPCT_HELPINFO - && ctnetlink_dump_helpinfo(skb, ct) < 0) - goto nfattr_failure; - if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || - ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) - goto nfattr_failure; + if (events & IPCT_DESTROY) { + if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || + ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) + goto nfattr_failure; + } else { + if (ctnetlink_dump_status(skb, ct) < 0) + goto nfattr_failure; - if (events & IPCT_MARK - && ctnetlink_dump_mark(skb, ct) < 0) - goto nfattr_failure; + if (ctnetlink_dump_timeout(skb, ct) < 0) + goto nfattr_failure; + + if (events & IPCT_PROTOINFO + && ctnetlink_dump_protoinfo(skb, ct) < 0) + goto nfattr_failure; + + if ((events & IPCT_HELPER || nfct_help(ct)) + && ctnetlink_dump_helpinfo(skb, ct) < 0) + goto nfattr_failure; + + if ((events & IPCT_MARK || ct->mark) + && ctnetlink_dump_mark(skb, ct) < 0) + goto nfattr_failure; + + if (events & IPCT_COUNTER_FILLING && + (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || + ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)) + goto nfattr_failure; + } nlh->nlmsg_len = skb->tail - b; nfnetlink_send(skb, 0, group, 0); -- cgit v1.2.3-70-g09d2 From 829e17a1a602572ffa3beefe582dc103ee9fb9c7 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Wed, 29 Nov 2006 02:35:33 +0100 Subject: [NETFILTER]: nfnetlink_queue: allow changing queue length through netlink Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- include/linux/netfilter/nfnetlink_queue.h | 1 + net/netfilter/nfnetlink_queue.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'net') diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 4beea3d6fda8..83e789633e35 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -82,6 +82,7 @@ enum nfqnl_attr_config { NFQA_CFG_UNSPEC, NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ + NFQA_CFG_QUEUE_MAXLEN, /* u_int32_t */ __NFQA_CFG_MAX }; #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 82e4454659bf..a88a017da22c 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -947,6 +947,14 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ntohl(params->copy_range)); } + if (nfqa[NFQA_CFG_QUEUE_MAXLEN-1]) { + __be32 *queue_maxlen; + queue_maxlen = NFA_DATA(nfqa[NFQA_CFG_QUEUE_MAXLEN-1]); + spin_lock_bh(&queue->lock); + queue->queue_maxlen = ntohl(*queue_maxlen); + spin_unlock_bh(&queue->lock); + } + out_put: instance_put(queue); return ret; -- cgit v1.2.3-70-g09d2 From d7a5c32442ed3d528b9ddfd3d5b837bad0ffa9da Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:34 +0100 Subject: [NETFILTER]: nfnetlink_log: remove useless prefix length limitation There is no reason for limiting netlink attributes in size. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nfnetlink_log.h | 2 -- net/netfilter/nfnetlink_log.c | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index 55a2a2b814ed..5966afa026e9 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -32,8 +32,6 @@ struct nfulnl_msg_packet_timestamp { aligned_be64 usec; }; -#define NFULNL_PREFIXLEN 30 /* just like old log target */ - enum nfulnl_attr_type { NFULA_UNSPEC, NFULA_PACKET_HDR, diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index bd3ffa6f1a6d..d1505dd25c66 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -408,7 +408,7 @@ __build_packet_message(struct nfulnl_instance *inst, const struct net_device *indev, const struct net_device *outdev, const struct nf_loginfo *li, - const char *prefix) + const char *prefix, unsigned int plen) { unsigned char *old_tail; struct nfulnl_msg_packet_hdr pmsg; @@ -432,12 +432,8 @@ __build_packet_message(struct nfulnl_instance *inst, NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg); - if (prefix) { - int slen = strlen(prefix); - if (slen > NFULNL_PREFIXLEN) - slen = NFULNL_PREFIXLEN; - NFA_PUT(inst->skb, NFULA_PREFIX, slen, prefix); - } + if (prefix) + NFA_PUT(inst->skb, NFULA_PREFIX, plen, prefix); if (indev) { tmp_uint = htonl(indev->ifindex); @@ -601,6 +597,7 @@ nfulnl_log_packet(unsigned int pf, const struct nf_loginfo *li; unsigned int qthreshold; unsigned int nlbufsiz; + unsigned int plen; if (li_user && li_user->type == NF_LOG_TYPE_ULOG) li = li_user; @@ -616,6 +613,10 @@ nfulnl_log_packet(unsigned int pf, return; } + plen = 0; + if (prefix) + plen = strlen(prefix); + /* all macros expand to constant values at compile time */ /* FIXME: do we want to make the size calculation conditional based on * what is actually present? way more branches and checks, but more @@ -630,7 +631,7 @@ nfulnl_log_packet(unsigned int pf, #endif + NFA_SPACE(sizeof(u_int32_t)) /* mark */ + NFA_SPACE(sizeof(u_int32_t)) /* uid */ - + NFA_SPACE(NFULNL_PREFIXLEN) /* prefix */ + + NFA_SPACE(plen) /* prefix */ + NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw)) + NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp)); @@ -701,7 +702,7 @@ nfulnl_log_packet(unsigned int pf, inst->qlen++; __build_packet_message(inst, skb, data_len, pf, - hooknum, in, out, li, prefix); + hooknum, in, out, li, prefix, plen); /* timer_pending always called within inst->lock, so there * is no chance of a race here */ -- cgit v1.2.3-70-g09d2 From 39b46fc6f0d1161a5585cd8af7b3a05e8118ab7e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:36 +0100 Subject: [NETFILTER]: x_tables: add port of hashlimit match for IPv4 and IPv6 Signed-off-by: Patrick McHardy --- include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_hashlimit.h | 40 ++ include/linux/netfilter_ipv4/ipt_hashlimit.h | 42 +- net/ipv4/netfilter/Kconfig | 14 - net/ipv4/netfilter/Makefile | 1 - net/ipv4/netfilter/ipt_hashlimit.c | 733 ------------------------- net/netfilter/Kconfig | 14 + net/netfilter/Makefile | 1 + net/netfilter/xt_hashlimit.c | 772 +++++++++++++++++++++++++++ 9 files changed, 836 insertions(+), 782 deletions(-) create mode 100644 include/linux/netfilter/xt_hashlimit.h delete mode 100644 net/ipv4/netfilter/ipt_hashlimit.c create mode 100644 net/netfilter/xt_hashlimit.c (limited to 'net') diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 312bd2ffee33..e379a2d89ea0 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -14,6 +14,7 @@ header-y += xt_dscp.h header-y += xt_DSCP.h header-y += xt_esp.h header-y += xt_helper.h +header-y += xt_hashlimit.h header-y += xt_length.h header-y += xt_limit.h header-y += xt_mac.h diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h new file mode 100644 index 000000000000..b4556b8edbfd --- /dev/null +++ b/include/linux/netfilter/xt_hashlimit.h @@ -0,0 +1,40 @@ +#ifndef _XT_HASHLIMIT_H +#define _XT_HASHLIMIT_H + +/* timings are in milliseconds. */ +#define XT_HASHLIMIT_SCALE 10000 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 + seconds, or one every 59 hours. */ + +/* details of this structure hidden by the implementation */ +struct xt_hashlimit_htable; + +#define XT_HASHLIMIT_HASH_DIP 0x0001 +#define XT_HASHLIMIT_HASH_DPT 0x0002 +#define XT_HASHLIMIT_HASH_SIP 0x0004 +#define XT_HASHLIMIT_HASH_SPT 0x0008 + +struct hashlimit_cfg { + u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */ + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* user specified */ + u_int32_t size; /* how many buckets */ + u_int32_t max; /* max number of entries */ + u_int32_t gc_interval; /* gc interval */ + u_int32_t expire; /* when do entries expire? */ +}; + +struct xt_hashlimit_info { + char name [IFNAMSIZ]; /* name */ + struct hashlimit_cfg cfg; + struct xt_hashlimit_htable *hinfo; + + /* Used internally by the kernel */ + union { + void *ptr; + struct xt_hashlimit_info *master; + } u; +}; +#endif /*_XT_HASHLIMIT_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_hashlimit.h b/include/linux/netfilter_ipv4/ipt_hashlimit.h index ac2cb64ecd76..5662120a3d7b 100644 --- a/include/linux/netfilter_ipv4/ipt_hashlimit.h +++ b/include/linux/netfilter_ipv4/ipt_hashlimit.h @@ -1,40 +1,14 @@ #ifndef _IPT_HASHLIMIT_H #define _IPT_HASHLIMIT_H -/* timings are in milliseconds. */ -#define IPT_HASHLIMIT_SCALE 10000 -/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 - seconds, or one every 59 hours. */ +#include -/* details of this structure hidden by the implementation */ -struct ipt_hashlimit_htable; +#define IPT_HASHLIMIT_SCALE XT_HASHLIMIT_SCALE +#define IPT_HASHLIMIT_HASH_DIP XT_HASHLIMIT_HASH_DIP +#define IPT_HASHLIMIT_HASH_DPT XT_HASHLIMIT_HASH_DPT +#define IPT_HASHLIMIT_HASH_SIP XT_HASHLIMIT_HASH_SIP +#define IPT_HASHLIMIT_HASH_SPT XT_HASHLIMIT_HASH_SPT -#define IPT_HASHLIMIT_HASH_DIP 0x0001 -#define IPT_HASHLIMIT_HASH_DPT 0x0002 -#define IPT_HASHLIMIT_HASH_SIP 0x0004 -#define IPT_HASHLIMIT_HASH_SPT 0x0008 +#define ipt_hashlimit_info xt_hashlimit_info -struct hashlimit_cfg { - u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */ - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ - - /* user specified */ - u_int32_t size; /* how many buckets */ - u_int32_t max; /* max number of entries */ - u_int32_t gc_interval; /* gc interval */ - u_int32_t expire; /* when do entries expire? */ -}; - -struct ipt_hashlimit_info { - char name [IFNAMSIZ]; /* name */ - struct hashlimit_cfg cfg; - struct ipt_hashlimit_htable *hinfo; - - /* Used internally by the kernel */ - union { - void *ptr; - struct ipt_hashlimit_info *master; - } u; -}; -#endif /*_IPT_HASHLIMIT_H*/ +#endif /* _IPT_HASHLIMIT_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 4ac5b5c4678d..bc298a3f236f 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -326,20 +326,6 @@ config IP_NF_MATCH_ADDRTYPE If you want to compile it as a module, say M here and read . If unsure, say `N'. -config IP_NF_MATCH_HASHLIMIT - tristate 'hashlimit match support' - depends on IP_NF_IPTABLES - help - This option adds a new iptables `hashlimit' match. - - As opposed to `limit', this match dynamically creates a hash table - of limit buckets, based on your selection of source/destination - ip addresses and/or ports. - - It enables you to express policies like `10kpps for any given - destination IP' or `500pps from any given source IP' with a single - IPtables rule. - # `filter', generic and specific targets config IP_NF_FILTER tristate "Packet filtering" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 4ce20ebc4d6c..21359d83f0c7 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -53,7 +53,6 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches -obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c deleted file mode 100644 index 33ccdbf8e794..000000000000 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ /dev/null @@ -1,733 +0,0 @@ -/* iptables match extension to limit the number of packets per second - * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) - * - * (C) 2003-2004 by Harald Welte - * - * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $ - * - * Development of this code was funded by Astaro AG, http://www.astaro.com/ - * - * based on ipt_limit.c by: - * Jérôme de Vivie - * Hervé Eychenne - * Rusty Russell - * - * The general idea is to create a hash table for every dstip and have a - * seperate limit counter per tuple. This way you can do something like 'limit - * the number of syn packets for each of my internal addresses. - * - * Ideally this would just be implemented as a general 'hash' match, which would - * allow us to attach any iptables target to it's hash buckets. But this is - * not possible in the current iptables architecture. As always, pkttables for - * 2.7.x will help ;) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* FIXME: this is just for IP_NF_ASSERRT */ -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("iptables match for limiting per hash-bucket"); - -/* need to declare this at the top */ -static struct proc_dir_entry *hashlimit_procdir; -static struct file_operations dl_file_ops; - -/* hash table crap */ - -struct dsthash_dst { - __be32 src_ip; - __be32 dst_ip; - /* ports have to be consecutive !!! */ - __be16 src_port; - __be16 dst_port; -}; - -struct dsthash_ent { - /* static / read-only parts in the beginning */ - struct hlist_node node; - struct dsthash_dst dst; - - /* modified structure members in the end */ - unsigned long expires; /* precalculated expiry time */ - struct { - unsigned long prev; /* last modification */ - u_int32_t credit; - u_int32_t credit_cap, cost; - } rateinfo; -}; - -struct ipt_hashlimit_htable { - struct hlist_node node; /* global list of all htables */ - atomic_t use; - - struct hashlimit_cfg cfg; /* config */ - - /* used internally */ - spinlock_t lock; /* lock for list_head */ - u_int32_t rnd; /* random seed for hash */ - int rnd_initialized; - struct timer_list timer; /* timer for gc */ - atomic_t count; /* number entries in table */ - - /* seq_file stuff */ - struct proc_dir_entry *pde; - - struct hlist_head hash[0]; /* hashtable itself */ -}; - -static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ -static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ -static HLIST_HEAD(hashlimit_htables); -static kmem_cache_t *hashlimit_cachep __read_mostly; - -static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b) -{ - return (ent->dst.dst_ip == b->dst_ip - && ent->dst.dst_port == b->dst_port - && ent->dst.src_port == b->src_port - && ent->dst.src_ip == b->src_ip); -} - -static inline u_int32_t -hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst) -{ - return (jhash_3words((__force u32)dst->dst_ip, - ((__force u32)dst->dst_port<<16 | - (__force u32)dst->src_port), - (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size); -} - -static inline struct dsthash_ent * -__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst) -{ - struct dsthash_ent *ent; - struct hlist_node *pos; - u_int32_t hash = hash_dst(ht, dst); - - if (!hlist_empty(&ht->hash[hash])) - hlist_for_each_entry(ent, pos, &ht->hash[hash], node) { - if (dst_cmp(ent, dst)) { - return ent; - } - } - - return NULL; -} - -/* allocate dsthash_ent, initialize dst, put in htable and lock it */ -static struct dsthash_ent * -__dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst) -{ - struct dsthash_ent *ent; - - /* initialize hash with random val at the time we allocate - * the first hashtable entry */ - if (!ht->rnd_initialized) { - get_random_bytes(&ht->rnd, 4); - ht->rnd_initialized = 1; - } - - if (ht->cfg.max && - atomic_read(&ht->count) >= ht->cfg.max) { - /* FIXME: do something. question is what.. */ - if (net_ratelimit()) - printk(KERN_WARNING - "ipt_hashlimit: max count of %u reached\n", - ht->cfg.max); - return NULL; - } - - ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC); - if (!ent) { - if (net_ratelimit()) - printk(KERN_ERR - "ipt_hashlimit: can't allocate dsthash_ent\n"); - return NULL; - } - - atomic_inc(&ht->count); - - ent->dst.dst_ip = dst->dst_ip; - ent->dst.dst_port = dst->dst_port; - ent->dst.src_ip = dst->src_ip; - ent->dst.src_port = dst->src_port; - - hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]); - - return ent; -} - -static inline void -__dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent) -{ - hlist_del(&ent->node); - kmem_cache_free(hashlimit_cachep, ent); - atomic_dec(&ht->count); -} -static void htable_gc(unsigned long htlong); - -static int htable_create(struct ipt_hashlimit_info *minfo) -{ - int i; - unsigned int size; - struct ipt_hashlimit_htable *hinfo; - - if (minfo->cfg.size) - size = minfo->cfg.size; - else { - size = (((num_physpages << PAGE_SHIFT) / 16384) - / sizeof(struct list_head)); - if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE)) - size = 8192; - if (size < 16) - size = 16; - } - /* FIXME: don't use vmalloc() here or anywhere else -HW */ - hinfo = vmalloc(sizeof(struct ipt_hashlimit_htable) - + (sizeof(struct list_head) * size)); - if (!hinfo) { - printk(KERN_ERR "ipt_hashlimit: Unable to create hashtable\n"); - return -1; - } - minfo->hinfo = hinfo; - - /* copy match config into hashtable config */ - memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); - hinfo->cfg.size = size; - if (!hinfo->cfg.max) - hinfo->cfg.max = 8 * hinfo->cfg.size; - else if (hinfo->cfg.max < hinfo->cfg.size) - hinfo->cfg.max = hinfo->cfg.size; - - for (i = 0; i < hinfo->cfg.size; i++) - INIT_HLIST_HEAD(&hinfo->hash[i]); - - atomic_set(&hinfo->count, 0); - atomic_set(&hinfo->use, 1); - hinfo->rnd_initialized = 0; - spin_lock_init(&hinfo->lock); - hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir); - if (!hinfo->pde) { - vfree(hinfo); - return -1; - } - hinfo->pde->proc_fops = &dl_file_ops; - hinfo->pde->data = hinfo; - - init_timer(&hinfo->timer); - hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); - hinfo->timer.data = (unsigned long )hinfo; - hinfo->timer.function = htable_gc; - add_timer(&hinfo->timer); - - spin_lock_bh(&hashlimit_lock); - hlist_add_head(&hinfo->node, &hashlimit_htables); - spin_unlock_bh(&hashlimit_lock); - - return 0; -} - -static int select_all(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he) -{ - return 1; -} - -static int select_gc(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he) -{ - return (jiffies >= he->expires); -} - -static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht, - int (*select)(struct ipt_hashlimit_htable *ht, - struct dsthash_ent *he)) -{ - int i; - - IP_NF_ASSERT(ht->cfg.size && ht->cfg.max); - - /* lock hash table and iterate over it */ - spin_lock_bh(&ht->lock); - for (i = 0; i < ht->cfg.size; i++) { - struct dsthash_ent *dh; - struct hlist_node *pos, *n; - hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) { - if ((*select)(ht, dh)) - __dsthash_free(ht, dh); - } - } - spin_unlock_bh(&ht->lock); -} - -/* hash table garbage collector, run by timer */ -static void htable_gc(unsigned long htlong) -{ - struct ipt_hashlimit_htable *ht = (struct ipt_hashlimit_htable *)htlong; - - htable_selective_cleanup(ht, select_gc); - - /* re-add the timer accordingly */ - ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval); - add_timer(&ht->timer); -} - -static void htable_destroy(struct ipt_hashlimit_htable *hinfo) -{ - /* remove timer, if it is pending */ - if (timer_pending(&hinfo->timer)) - del_timer(&hinfo->timer); - - /* remove proc entry */ - remove_proc_entry(hinfo->pde->name, hashlimit_procdir); - - htable_selective_cleanup(hinfo, select_all); - vfree(hinfo); -} - -static struct ipt_hashlimit_htable *htable_find_get(char *name) -{ - struct ipt_hashlimit_htable *hinfo; - struct hlist_node *pos; - - spin_lock_bh(&hashlimit_lock); - hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) { - if (!strcmp(name, hinfo->pde->name)) { - atomic_inc(&hinfo->use); - spin_unlock_bh(&hashlimit_lock); - return hinfo; - } - } - spin_unlock_bh(&hashlimit_lock); - - return NULL; -} - -static void htable_put(struct ipt_hashlimit_htable *hinfo) -{ - if (atomic_dec_and_test(&hinfo->use)) { - spin_lock_bh(&hashlimit_lock); - hlist_del(&hinfo->node); - spin_unlock_bh(&hashlimit_lock); - htable_destroy(hinfo); - } -} - - -/* The algorithm used is the Simple Token Bucket Filter (TBF) - * see net/sched/sch_tbf.c in the linux source tree - */ - -/* Rusty: This is my (non-mathematically-inclined) understanding of - this algorithm. The `average rate' in jiffies becomes your initial - amount of credit `credit' and the most credit you can ever have - `credit_cap'. The `peak rate' becomes the cost of passing the - test, `cost'. - - `prev' tracks the last packet hit: you gain one credit per jiffy. - If you get credit balance more than this, the extra credit is - discarded. Every time the match passes, you lose `cost' credits; - if you don't have that many, the test fails. - - See Alexey's formal explanation in net/sched/sch_tbf.c. - - To get the maximum range, we multiply by this factor (ie. you get N - credits per jiffy). We want to allow a rate as low as 1 per day - (slowest userspace tool allows), which means - CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie. -*/ -#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24)) - -/* Repeated shift and or gives us all 1s, final shift and add 1 gives - * us the power of 2 below the theoretical max, so GCC simply does a - * shift. */ -#define _POW2_BELOW2(x) ((x)|((x)>>1)) -#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2)) -#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4)) -#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8)) -#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16)) -#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1) - -#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) - -/* Precision saver. */ -static inline u_int32_t -user2credits(u_int32_t user) -{ - /* If multiplying would overflow... */ - if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) - /* Divide first. */ - return (user / IPT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; - - return (user * HZ * CREDITS_PER_JIFFY) / IPT_HASHLIMIT_SCALE; -} - -static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) -{ - dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) - * CREDITS_PER_JIFFY; - if (dh->rateinfo.credit > dh->rateinfo.credit_cap) - dh->rateinfo.credit = dh->rateinfo.credit_cap; -} - -static int -hashlimit_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct ipt_hashlimit_info *r = - ((struct ipt_hashlimit_info *)matchinfo)->u.master; - struct ipt_hashlimit_htable *hinfo = r->hinfo; - unsigned long now = jiffies; - struct dsthash_ent *dh; - struct dsthash_dst dst; - - /* build 'dst' according to hinfo->cfg and current packet */ - memset(&dst, 0, sizeof(dst)); - if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DIP) - dst.dst_ip = skb->nh.iph->daddr; - if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SIP) - dst.src_ip = skb->nh.iph->saddr; - if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT - ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) { - __be16 _ports[2], *ports; - - switch (skb->nh.iph->protocol) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_SCTP: - case IPPROTO_DCCP: - ports = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_ports), &_ports); - break; - default: - _ports[0] = _ports[1] = 0; - ports = _ports; - break; - } - if (!ports) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - *hotdrop = 1; - return 0; - } - if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) - dst.src_port = ports[0]; - if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT) - dst.dst_port = ports[1]; - } - - spin_lock_bh(&hinfo->lock); - dh = __dsthash_find(hinfo, &dst); - if (!dh) { - dh = __dsthash_alloc_init(hinfo, &dst); - - if (!dh) { - /* enomem... don't match == DROP */ - if (net_ratelimit()) - printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__); - spin_unlock_bh(&hinfo->lock); - return 0; - } - - dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); - - dh->rateinfo.prev = jiffies; - dh->rateinfo.credit = user2credits(hinfo->cfg.avg * - hinfo->cfg.burst); - dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * - hinfo->cfg.burst); - dh->rateinfo.cost = user2credits(hinfo->cfg.avg); - } else { - /* update expiration timeout */ - dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); - rateinfo_recalc(dh, now); - } - - if (dh->rateinfo.credit >= dh->rateinfo.cost) { - /* We're underlimit. */ - dh->rateinfo.credit -= dh->rateinfo.cost; - spin_unlock_bh(&hinfo->lock); - return 1; - } - - spin_unlock_bh(&hinfo->lock); - - /* default case: we're overlimit, thus don't match */ - return 0; -} - -static int -hashlimit_checkentry(const char *tablename, - const void *inf, - const struct xt_match *match, - void *matchinfo, - unsigned int hook_mask) -{ - struct ipt_hashlimit_info *r = matchinfo; - - /* Check for overflow. */ - if (r->cfg.burst == 0 - || user2credits(r->cfg.avg * r->cfg.burst) < - user2credits(r->cfg.avg)) { - printk(KERN_ERR "ipt_hashlimit: Overflow, try lower: %u/%u\n", - r->cfg.avg, r->cfg.burst); - return 0; - } - - if (r->cfg.mode == 0 - || r->cfg.mode > (IPT_HASHLIMIT_HASH_DPT - |IPT_HASHLIMIT_HASH_DIP - |IPT_HASHLIMIT_HASH_SIP - |IPT_HASHLIMIT_HASH_SPT)) - return 0; - - if (!r->cfg.gc_interval) - return 0; - - if (!r->cfg.expire) - return 0; - - if (r->name[sizeof(r->name) - 1] != '\0') - return 0; - - /* This is the best we've got: We cannot release and re-grab lock, - * since checkentry() is called before ip_tables.c grabs ipt_mutex. - * We also cannot grab the hashtable spinlock, since htable_create will - * call vmalloc, and that can sleep. And we cannot just re-search - * the list of htable's in htable_create(), since then we would - * create duplicate proc files. -HW */ - mutex_lock(&hlimit_mutex); - r->hinfo = htable_find_get(r->name); - if (!r->hinfo && (htable_create(r) != 0)) { - mutex_unlock(&hlimit_mutex); - return 0; - } - mutex_unlock(&hlimit_mutex); - - /* Ugly hack: For SMP, we only want to use one set */ - r->u.master = r; - - return 1; -} - -static void -hashlimit_destroy(const struct xt_match *match, void *matchinfo) -{ - struct ipt_hashlimit_info *r = matchinfo; - - htable_put(r->hinfo); -} - -#ifdef CONFIG_COMPAT -struct compat_ipt_hashlimit_info { - char name[IFNAMSIZ]; - struct hashlimit_cfg cfg; - compat_uptr_t hinfo; - compat_uptr_t master; -}; - -static void compat_from_user(void *dst, void *src) -{ - int off = offsetof(struct compat_ipt_hashlimit_info, hinfo); - - memcpy(dst, src, off); - memset(dst + off, 0, sizeof(struct compat_ipt_hashlimit_info) - off); -} - -static int compat_to_user(void __user *dst, void *src) -{ - int off = offsetof(struct compat_ipt_hashlimit_info, hinfo); - - return copy_to_user(dst, src, off) ? -EFAULT : 0; -} -#endif - -static struct ipt_match ipt_hashlimit = { - .name = "hashlimit", - .match = hashlimit_match, - .matchsize = sizeof(struct ipt_hashlimit_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_ipt_hashlimit_info), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif - .checkentry = hashlimit_checkentry, - .destroy = hashlimit_destroy, - .me = THIS_MODULE -}; - -/* PROC stuff */ - -static void *dl_seq_start(struct seq_file *s, loff_t *pos) -{ - struct proc_dir_entry *pde = s->private; - struct ipt_hashlimit_htable *htable = pde->data; - unsigned int *bucket; - - spin_lock_bh(&htable->lock); - if (*pos >= htable->cfg.size) - return NULL; - - bucket = kmalloc(sizeof(unsigned int), GFP_ATOMIC); - if (!bucket) - return ERR_PTR(-ENOMEM); - - *bucket = *pos; - return bucket; -} - -static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - struct proc_dir_entry *pde = s->private; - struct ipt_hashlimit_htable *htable = pde->data; - unsigned int *bucket = (unsigned int *)v; - - *pos = ++(*bucket); - if (*pos >= htable->cfg.size) { - kfree(v); - return NULL; - } - return bucket; -} - -static void dl_seq_stop(struct seq_file *s, void *v) -{ - struct proc_dir_entry *pde = s->private; - struct ipt_hashlimit_htable *htable = pde->data; - unsigned int *bucket = (unsigned int *)v; - - kfree(bucket); - - spin_unlock_bh(&htable->lock); -} - -static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s) -{ - /* recalculate to show accurate numbers */ - rateinfo_recalc(ent, jiffies); - - return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n", - (long)(ent->expires - jiffies)/HZ, - NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port), - NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port), - ent->rateinfo.credit, ent->rateinfo.credit_cap, - ent->rateinfo.cost); -} - -static int dl_seq_show(struct seq_file *s, void *v) -{ - struct proc_dir_entry *pde = s->private; - struct ipt_hashlimit_htable *htable = pde->data; - unsigned int *bucket = (unsigned int *)v; - struct dsthash_ent *ent; - struct hlist_node *pos; - - if (!hlist_empty(&htable->hash[*bucket])) - hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) { - if (dl_seq_real_show(ent, s)) { - /* buffer was filled and unable to print that tuple */ - return 1; - } - } - - return 0; -} - -static struct seq_operations dl_seq_ops = { - .start = dl_seq_start, - .next = dl_seq_next, - .stop = dl_seq_stop, - .show = dl_seq_show -}; - -static int dl_proc_open(struct inode *inode, struct file *file) -{ - int ret = seq_open(file, &dl_seq_ops); - - if (!ret) { - struct seq_file *sf = file->private_data; - sf->private = PDE(inode); - } - return ret; -} - -static struct file_operations dl_file_ops = { - .owner = THIS_MODULE, - .open = dl_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release -}; - -static int init_or_fini(int fini) -{ - int ret = 0; - - if (fini) - goto cleanup; - - if (ipt_register_match(&ipt_hashlimit)) { - ret = -EINVAL; - goto cleanup_nothing; - } - - hashlimit_cachep = kmem_cache_create("ipt_hashlimit", - sizeof(struct dsthash_ent), 0, - 0, NULL, NULL); - if (!hashlimit_cachep) { - printk(KERN_ERR "Unable to create ipt_hashlimit slab cache\n"); - ret = -ENOMEM; - goto cleanup_unreg_match; - } - - hashlimit_procdir = proc_mkdir("ipt_hashlimit", proc_net); - if (!hashlimit_procdir) { - printk(KERN_ERR "Unable to create proc dir entry\n"); - ret = -ENOMEM; - goto cleanup_free_slab; - } - - return ret; - -cleanup: - remove_proc_entry("ipt_hashlimit", proc_net); -cleanup_free_slab: - kmem_cache_destroy(hashlimit_cachep); -cleanup_unreg_match: - ipt_unregister_match(&ipt_hashlimit); -cleanup_nothing: - return ret; - -} - -static int __init ipt_hashlimit_init(void) -{ - return init_or_fini(0); -} - -static void __exit ipt_hashlimit_fini(void) -{ - init_or_fini(1); -} - -module_init(ipt_hashlimit_init); -module_exit(ipt_hashlimit_fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f619c6527266..7e6125467c12 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -464,5 +464,19 @@ config NETFILTER_XT_MATCH_TCPMSS To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_MATCH_HASHLIMIT + tristate '"hashlimit" match support' + depends on NETFILTER_XTABLES + help + This option adds a `hashlimit' match. + + As opposed to `limit', this match dynamically creates a hash table + of limit buckets, based on your selection of source/destination + addresses and/or ports. + + It enables you to express policies like `10kpps for any given + destination address' or `500pps from any given source address' + with a single rule. + endmenu diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 84d529ded952..f85811bfcfe5 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o +obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c new file mode 100644 index 000000000000..46de566d3721 --- /dev/null +++ b/net/netfilter/xt_hashlimit.c @@ -0,0 +1,772 @@ +/* iptables match extension to limit the number of packets per second + * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) + * + * (C) 2003-2004 by Harald Welte + * + * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $ + * + * Development of this code was funded by Astaro AG, http://www.astaro.com/ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("iptables match for limiting per hash-bucket"); +MODULE_ALIAS("ipt_hashlimit"); +MODULE_ALIAS("ip6t_hashlimit"); + +/* need to declare this at the top */ +static struct proc_dir_entry *hashlimit_procdir4; +static struct proc_dir_entry *hashlimit_procdir6; +static struct file_operations dl_file_ops; + +/* hash table crap */ +struct dsthash_dst { + union { + struct { + __be32 src; + __be32 dst; + } ip; + struct { + __be32 src[4]; + __be32 dst[4]; + } ip6; + } addr; + __be16 src_port; + __be16 dst_port; +}; + +struct dsthash_ent { + /* static / read-only parts in the beginning */ + struct hlist_node node; + struct dsthash_dst dst; + + /* modified structure members in the end */ + unsigned long expires; /* precalculated expiry time */ + struct { + unsigned long prev; /* last modification */ + u_int32_t credit; + u_int32_t credit_cap, cost; + } rateinfo; +}; + +struct xt_hashlimit_htable { + struct hlist_node node; /* global list of all htables */ + atomic_t use; + int family; + + struct hashlimit_cfg cfg; /* config */ + + /* used internally */ + spinlock_t lock; /* lock for list_head */ + u_int32_t rnd; /* random seed for hash */ + int rnd_initialized; + unsigned int count; /* number entries in table */ + struct timer_list timer; /* timer for gc */ + + /* seq_file stuff */ + struct proc_dir_entry *pde; + + struct hlist_head hash[0]; /* hashtable itself */ +}; + +static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ +static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ +static HLIST_HEAD(hashlimit_htables); +static kmem_cache_t *hashlimit_cachep __read_mostly; + +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b) +{ + return !memcmp(&ent->dst, b, sizeof(ent->dst)); +} + +static u_int32_t +hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst) +{ + return jhash(dst, sizeof(*dst), ht->rnd) % ht->cfg.size; +} + +static struct dsthash_ent * +dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst) +{ + struct dsthash_ent *ent; + struct hlist_node *pos; + u_int32_t hash = hash_dst(ht, dst); + + if (!hlist_empty(&ht->hash[hash])) { + hlist_for_each_entry(ent, pos, &ht->hash[hash], node) + if (dst_cmp(ent, dst)) + return ent; + } + return NULL; +} + +/* allocate dsthash_ent, initialize dst, put in htable and lock it */ +static struct dsthash_ent * +dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst) +{ + struct dsthash_ent *ent; + + /* initialize hash with random val at the time we allocate + * the first hashtable entry */ + if (!ht->rnd_initialized) { + get_random_bytes(&ht->rnd, 4); + ht->rnd_initialized = 1; + } + + if (ht->cfg.max && ht->count >= ht->cfg.max) { + /* FIXME: do something. question is what.. */ + if (net_ratelimit()) + printk(KERN_WARNING + "xt_hashlimit: max count of %u reached\n", + ht->cfg.max); + return NULL; + } + + ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC); + if (!ent) { + if (net_ratelimit()) + printk(KERN_ERR + "xt_hashlimit: can't allocate dsthash_ent\n"); + return NULL; + } + memcpy(&ent->dst, dst, sizeof(ent->dst)); + + hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]); + ht->count++; + return ent; +} + +static inline void +dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) +{ + hlist_del(&ent->node); + kmem_cache_free(hashlimit_cachep, ent); + ht->count--; +} +static void htable_gc(unsigned long htlong); + +static int htable_create(struct xt_hashlimit_info *minfo, int family) +{ + struct xt_hashlimit_htable *hinfo; + unsigned int size; + unsigned int i; + + if (minfo->cfg.size) + size = minfo->cfg.size; + else { + size = ((num_physpages << PAGE_SHIFT) / 16384) / + sizeof(struct list_head); + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE)) + size = 8192; + if (size < 16) + size = 16; + } + /* FIXME: don't use vmalloc() here or anywhere else -HW */ + hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) + + sizeof(struct list_head) * size); + if (!hinfo) { + printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n"); + return -1; + } + minfo->hinfo = hinfo; + + /* copy match config into hashtable config */ + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); + hinfo->cfg.size = size; + if (!hinfo->cfg.max) + hinfo->cfg.max = 8 * hinfo->cfg.size; + else if (hinfo->cfg.max < hinfo->cfg.size) + hinfo->cfg.max = hinfo->cfg.size; + + for (i = 0; i < hinfo->cfg.size; i++) + INIT_HLIST_HEAD(&hinfo->hash[i]); + + atomic_set(&hinfo->use, 1); + hinfo->count = 0; + hinfo->family = family; + hinfo->rnd_initialized = 0; + spin_lock_init(&hinfo->lock); + hinfo->pde = create_proc_entry(minfo->name, 0, + family == AF_INET ? hashlimit_procdir4 : + hashlimit_procdir6); + if (!hinfo->pde) { + vfree(hinfo); + return -1; + } + hinfo->pde->proc_fops = &dl_file_ops; + hinfo->pde->data = hinfo; + + init_timer(&hinfo->timer); + hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); + hinfo->timer.data = (unsigned long )hinfo; + hinfo->timer.function = htable_gc; + add_timer(&hinfo->timer); + + spin_lock_bh(&hashlimit_lock); + hlist_add_head(&hinfo->node, &hashlimit_htables); + spin_unlock_bh(&hashlimit_lock); + + return 0; +} + +static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he) +{ + return 1; +} + +static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he) +{ + return (jiffies >= he->expires); +} + +static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, + int (*select)(struct xt_hashlimit_htable *ht, + struct dsthash_ent *he)) +{ + unsigned int i; + + /* lock hash table and iterate over it */ + spin_lock_bh(&ht->lock); + for (i = 0; i < ht->cfg.size; i++) { + struct dsthash_ent *dh; + struct hlist_node *pos, *n; + hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) { + if ((*select)(ht, dh)) + dsthash_free(ht, dh); + } + } + spin_unlock_bh(&ht->lock); +} + +/* hash table garbage collector, run by timer */ +static void htable_gc(unsigned long htlong) +{ + struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong; + + htable_selective_cleanup(ht, select_gc); + + /* re-add the timer accordingly */ + ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval); + add_timer(&ht->timer); +} + +static void htable_destroy(struct xt_hashlimit_htable *hinfo) +{ + /* remove timer, if it is pending */ + if (timer_pending(&hinfo->timer)) + del_timer(&hinfo->timer); + + /* remove proc entry */ + remove_proc_entry(hinfo->pde->name, + hinfo->family == AF_INET ? hashlimit_procdir4 : + hashlimit_procdir6); + htable_selective_cleanup(hinfo, select_all); + vfree(hinfo); +} + +static struct xt_hashlimit_htable *htable_find_get(char *name, int family) +{ + struct xt_hashlimit_htable *hinfo; + struct hlist_node *pos; + + spin_lock_bh(&hashlimit_lock); + hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) { + if (!strcmp(name, hinfo->pde->name) && + hinfo->family == family) { + atomic_inc(&hinfo->use); + spin_unlock_bh(&hashlimit_lock); + return hinfo; + } + } + spin_unlock_bh(&hashlimit_lock); + return NULL; +} + +static void htable_put(struct xt_hashlimit_htable *hinfo) +{ + if (atomic_dec_and_test(&hinfo->use)) { + spin_lock_bh(&hashlimit_lock); + hlist_del(&hinfo->node); + spin_unlock_bh(&hashlimit_lock); + htable_destroy(hinfo); + } +} + +/* The algorithm used is the Simple Token Bucket Filter (TBF) + * see net/sched/sch_tbf.c in the linux source tree + */ + +/* Rusty: This is my (non-mathematically-inclined) understanding of + this algorithm. The `average rate' in jiffies becomes your initial + amount of credit `credit' and the most credit you can ever have + `credit_cap'. The `peak rate' becomes the cost of passing the + test, `cost'. + + `prev' tracks the last packet hit: you gain one credit per jiffy. + If you get credit balance more than this, the extra credit is + discarded. Every time the match passes, you lose `cost' credits; + if you don't have that many, the test fails. + + See Alexey's formal explanation in net/sched/sch_tbf.c. + + To get the maximum range, we multiply by this factor (ie. you get N + credits per jiffy). We want to allow a rate as low as 1 per day + (slowest userspace tool allows), which means + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie. +*/ +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24)) + +/* Repeated shift and or gives us all 1s, final shift and add 1 gives + * us the power of 2 below the theoretical max, so GCC simply does a + * shift. */ +#define _POW2_BELOW2(x) ((x)|((x)>>1)) +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2)) +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4)) +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8)) +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16)) +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1) + +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) + +/* Precision saver. */ +static inline u_int32_t +user2credits(u_int32_t user) +{ + /* If multiplying would overflow... */ + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) + /* Divide first. */ + return (user / XT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; + + return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE; +} + +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) +{ + dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY; + if (dh->rateinfo.credit > dh->rateinfo.credit_cap) + dh->rateinfo.credit = dh->rateinfo.credit_cap; + dh->rateinfo.prev = now; +} + +static int +hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst, + const struct sk_buff *skb, unsigned int protoff) +{ + __be16 _ports[2], *ports; + int nexthdr; + + memset(dst, 0, sizeof(*dst)); + + switch (hinfo->family) { + case AF_INET: + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) + dst->addr.ip.dst = skb->nh.iph->daddr; + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) + dst->addr.ip.src = skb->nh.iph->saddr; + + if (!(hinfo->cfg.mode & + (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) + return 0; + nexthdr = skb->nh.iph->protocol; + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) + memcpy(&dst->addr.ip6.dst, &skb->nh.ipv6h->daddr, + sizeof(dst->addr.ip6.dst)); + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) + memcpy(&dst->addr.ip6.src, &skb->nh.ipv6h->saddr, + sizeof(dst->addr.ip6.src)); + + if (!(hinfo->cfg.mode & + (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) + return 0; + nexthdr = ipv6_find_hdr(skb, &protoff, -1, NULL); + if (nexthdr < 0) + return -1; + break; +#endif + default: + BUG(); + return 0; + } + + switch (nexthdr) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_SCTP: + case IPPROTO_DCCP: + ports = skb_header_pointer(skb, protoff, sizeof(_ports), + &_ports); + break; + default: + _ports[0] = _ports[1] = 0; + ports = _ports; + break; + } + if (!ports) + return -1; + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SPT) + dst->src_port = ports[0]; + if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DPT) + dst->dst_port = ports[1]; + return 0; +} + +static int +hashlimit_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct xt_hashlimit_info *r = + ((struct xt_hashlimit_info *)matchinfo)->u.master; + struct xt_hashlimit_htable *hinfo = r->hinfo; + unsigned long now = jiffies; + struct dsthash_ent *dh; + struct dsthash_dst dst; + + if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0) + goto hotdrop; + + spin_lock_bh(&hinfo->lock); + dh = dsthash_find(hinfo, &dst); + if (!dh) { + dh = dsthash_alloc_init(hinfo, &dst); + if (!dh) { + spin_unlock_bh(&hinfo->lock); + goto hotdrop; + } + + dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); + dh->rateinfo.prev = jiffies; + dh->rateinfo.credit = user2credits(hinfo->cfg.avg * + hinfo->cfg.burst); + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * + hinfo->cfg.burst); + dh->rateinfo.cost = user2credits(hinfo->cfg.avg); + } else { + /* update expiration timeout */ + dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); + rateinfo_recalc(dh, now); + } + + if (dh->rateinfo.credit >= dh->rateinfo.cost) { + /* We're underlimit. */ + dh->rateinfo.credit -= dh->rateinfo.cost; + spin_unlock_bh(&hinfo->lock); + return 1; + } + + spin_unlock_bh(&hinfo->lock); + + /* default case: we're overlimit, thus don't match */ + return 0; + +hotdrop: + *hotdrop = 1; + return 0; +} + +static int +hashlimit_checkentry(const char *tablename, + const void *inf, + const struct xt_match *match, + void *matchinfo, + unsigned int hook_mask) +{ + struct xt_hashlimit_info *r = matchinfo; + + /* Check for overflow. */ + if (r->cfg.burst == 0 || + user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) { + printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", + r->cfg.avg, r->cfg.burst); + return 0; + } + if (r->cfg.mode == 0 || + r->cfg.mode > (XT_HASHLIMIT_HASH_DPT | + XT_HASHLIMIT_HASH_DIP | + XT_HASHLIMIT_HASH_SIP | + XT_HASHLIMIT_HASH_SPT)) + return 0; + if (!r->cfg.gc_interval) + return 0; + if (!r->cfg.expire) + return 0; + if (r->name[sizeof(r->name) - 1] != '\0') + return 0; + + /* This is the best we've got: We cannot release and re-grab lock, + * since checkentry() is called before x_tables.c grabs xt_mutex. + * We also cannot grab the hashtable spinlock, since htable_create will + * call vmalloc, and that can sleep. And we cannot just re-search + * the list of htable's in htable_create(), since then we would + * create duplicate proc files. -HW */ + mutex_lock(&hlimit_mutex); + r->hinfo = htable_find_get(r->name, match->family); + if (!r->hinfo && htable_create(r, match->family) != 0) { + mutex_unlock(&hlimit_mutex); + return 0; + } + mutex_unlock(&hlimit_mutex); + + /* Ugly hack: For SMP, we only want to use one set */ + r->u.master = r; + return 1; +} + +static void +hashlimit_destroy(const struct xt_match *match, void *matchinfo) +{ + struct xt_hashlimit_info *r = matchinfo; + + htable_put(r->hinfo); +} + +#ifdef CONFIG_COMPAT +struct compat_xt_hashlimit_info { + char name[IFNAMSIZ]; + struct hashlimit_cfg cfg; + compat_uptr_t hinfo; + compat_uptr_t master; +}; + +static void compat_from_user(void *dst, void *src) +{ + int off = offsetof(struct compat_xt_hashlimit_info, hinfo); + + memcpy(dst, src, off); + memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off); +} + +static int compat_to_user(void __user *dst, void *src) +{ + int off = offsetof(struct compat_xt_hashlimit_info, hinfo); + + return copy_to_user(dst, src, off) ? -EFAULT : 0; +} +#endif + +static struct xt_match xt_hashlimit[] = { + { + .name = "hashlimit", + .family = AF_INET, + .match = hashlimit_match, + .matchsize = sizeof(struct xt_hashlimit_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_xt_hashlimit_info), + .compat_from_user = compat_from_user, + .compat_to_user = compat_to_user, +#endif + .checkentry = hashlimit_checkentry, + .destroy = hashlimit_destroy, + .me = THIS_MODULE + }, + { + .name = "hashlimit", + .family = AF_INET6, + .match = hashlimit_match, + .matchsize = sizeof(struct xt_hashlimit_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_xt_hashlimit_info), + .compat_from_user = compat_from_user, + .compat_to_user = compat_to_user, +#endif + .checkentry = hashlimit_checkentry, + .destroy = hashlimit_destroy, + .me = THIS_MODULE + }, +}; + +/* PROC stuff */ +static void *dl_seq_start(struct seq_file *s, loff_t *pos) +{ + struct proc_dir_entry *pde = s->private; + struct xt_hashlimit_htable *htable = pde->data; + unsigned int *bucket; + + spin_lock_bh(&htable->lock); + if (*pos >= htable->cfg.size) + return NULL; + + bucket = kmalloc(sizeof(unsigned int), GFP_ATOMIC); + if (!bucket) + return ERR_PTR(-ENOMEM); + + *bucket = *pos; + return bucket; +} + +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct proc_dir_entry *pde = s->private; + struct xt_hashlimit_htable *htable = pde->data; + unsigned int *bucket = (unsigned int *)v; + + *pos = ++(*bucket); + if (*pos >= htable->cfg.size) { + kfree(v); + return NULL; + } + return bucket; +} + +static void dl_seq_stop(struct seq_file *s, void *v) +{ + struct proc_dir_entry *pde = s->private; + struct xt_hashlimit_htable *htable = pde->data; + unsigned int *bucket = (unsigned int *)v; + + kfree(bucket); + spin_unlock_bh(&htable->lock); +} + +static int dl_seq_real_show(struct dsthash_ent *ent, int family, + struct seq_file *s) +{ + /* recalculate to show accurate numbers */ + rateinfo_recalc(ent, jiffies); + + switch (family) { + case AF_INET: + return seq_printf(s, "%ld %u.%u.%u.%u:%u->" + "%u.%u.%u.%u:%u %u %u %u\n", + (long)(ent->expires - jiffies)/HZ, + NIPQUAD(ent->dst.addr.ip.src), + ntohs(ent->dst.src_port), + NIPQUAD(ent->dst.addr.ip.dst), + ntohs(ent->dst.dst_port), + ent->rateinfo.credit, ent->rateinfo.credit_cap, + ent->rateinfo.cost); + case AF_INET6: + return seq_printf(s, "%ld " NIP6_FMT ":%u->" + NIP6_FMT ":%u %u %u %u\n", + (long)(ent->expires - jiffies)/HZ, + NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.src), + ntohs(ent->dst.src_port), + NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.dst), + ntohs(ent->dst.dst_port), + ent->rateinfo.credit, ent->rateinfo.credit_cap, + ent->rateinfo.cost); + default: + BUG(); + return 0; + } +} + +static int dl_seq_show(struct seq_file *s, void *v) +{ + struct proc_dir_entry *pde = s->private; + struct xt_hashlimit_htable *htable = pde->data; + unsigned int *bucket = (unsigned int *)v; + struct dsthash_ent *ent; + struct hlist_node *pos; + + if (!hlist_empty(&htable->hash[*bucket])) { + hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) + if (dl_seq_real_show(ent, htable->family, s)) + return 1; + } + return 0; +} + +static struct seq_operations dl_seq_ops = { + .start = dl_seq_start, + .next = dl_seq_next, + .stop = dl_seq_stop, + .show = dl_seq_show +}; + +static int dl_proc_open(struct inode *inode, struct file *file) +{ + int ret = seq_open(file, &dl_seq_ops); + + if (!ret) { + struct seq_file *sf = file->private_data; + sf->private = PDE(inode); + } + return ret; +} + +static struct file_operations dl_file_ops = { + .owner = THIS_MODULE, + .open = dl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +static int __init xt_hashlimit_init(void) +{ + int err; + + err = xt_register_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit)); + if (err < 0) + goto err1; + + err = -ENOMEM; + hashlimit_cachep = kmem_cache_create("xt_hashlimit", + sizeof(struct dsthash_ent), 0, 0, + NULL, NULL); + if (!hashlimit_cachep) { + printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n"); + goto err2; + } + hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net); + if (!hashlimit_procdir4) { + printk(KERN_ERR "xt_hashlimit: unable to create proc dir " + "entry\n"); + goto err3; + } + hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net); + if (!hashlimit_procdir6) { + printk(KERN_ERR "xt_hashlimit: tnable to create proc dir " + "entry\n"); + goto err4; + } + return 0; +err4: + remove_proc_entry("ipt_hashlimit", proc_net); +err3: + kmem_cache_destroy(hashlimit_cachep); +err2: + xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit)); +err1: + return err; + +} + +static void __exit xt_hashlimit_fini(void) +{ + remove_proc_entry("ipt_hashlimit", proc_net); + remove_proc_entry("ip6t_hashlimit", proc_net); + kmem_cache_destroy(hashlimit_cachep); + xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit)); +} + +module_init(xt_hashlimit_init); +module_exit(xt_hashlimit_fini); -- cgit v1.2.3-70-g09d2 From baf7b1e11282127e068d149825cccec002091d61 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:38 +0100 Subject: [NETFILTER]: x_tables: add NFLOG target Add new NFLOG target to allow use of nfnetlink_log for both IPv4 and IPv6. Currently we have two (unsupported by userspace) hacks in the LOG and ULOG targets to optionally call to the nflog API. They lack a few features, namely the IPv4 and IPv6 LOG targets can not specify a number of arguments related to nfnetlink_log, while the ULOG target is only available for IPv4. Remove those hacks and add a clean way to use nfnetlink_log. Signed-off-by: Patrick McHardy --- include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_NFLOG.h | 18 +++++++ include/linux/netfilter_ipv4/ipt_LOG.h | 2 +- include/linux/netfilter_ipv6/ip6t_LOG.h | 2 +- net/ipv4/netfilter/ipt_LOG.c | 9 +--- net/ipv6/netfilter/ip6t_LOG.c | 9 +--- net/netfilter/Kconfig | 11 +++++ net/netfilter/Makefile | 1 + net/netfilter/xt_NFLOG.c | 86 +++++++++++++++++++++++++++++++++ 9 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 include/linux/netfilter/xt_NFLOG.h create mode 100644 net/netfilter/xt_NFLOG.c (limited to 'net') diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index e379a2d89ea0..6328175a1c3a 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -22,6 +22,7 @@ header-y += xt_mark.h header-y += xt_MARK.h header-y += xt_multiport.h header-y += xt_NFQUEUE.h +header-y += xt_NFLOG.h header-y += xt_pkttype.h header-y += xt_policy.h header-y += xt_realm.h diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h new file mode 100644 index 000000000000..cdcd0ed58f7a --- /dev/null +++ b/include/linux/netfilter/xt_NFLOG.h @@ -0,0 +1,18 @@ +#ifndef _XT_NFLOG_TARGET +#define _XT_NFLOG_TARGET + +#define XT_NFLOG_DEFAULT_GROUP 0x1 +#define XT_NFLOG_DEFAULT_THRESHOLD 1 + +#define XT_NFLOG_MASK 0x0 + +struct xt_nflog_info { + u_int32_t len; + u_int16_t group; + u_int16_t threshold; + u_int16_t flags; + u_int16_t pad; + char prefix[64]; +}; + +#endif /* _XT_NFLOG_TARGET */ diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h index 892f9a33fea8..90fa6525ef9c 100644 --- a/include/linux/netfilter_ipv4/ipt_LOG.h +++ b/include/linux/netfilter_ipv4/ipt_LOG.h @@ -6,7 +6,7 @@ #define IPT_LOG_TCPOPT 0x02 /* Log TCP options */ #define IPT_LOG_IPOPT 0x04 /* Log IP options */ #define IPT_LOG_UID 0x08 /* Log UID owning local socket */ -#define IPT_LOG_NFLOG 0x10 /* Log using nf_log backend */ +#define IPT_LOG_NFLOG 0x10 /* Unsupported, don't reuse */ #define IPT_LOG_MASK 0x1f struct ipt_log_info { diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h index 060c1a1c6c60..0d0119b0458c 100644 --- a/include/linux/netfilter_ipv6/ip6t_LOG.h +++ b/include/linux/netfilter_ipv6/ip6t_LOG.h @@ -6,7 +6,7 @@ #define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */ #define IP6T_LOG_IPOPT 0x04 /* Log IP options */ #define IP6T_LOG_UID 0x08 /* Log UID owning local socket */ -#define IP6T_LOG_NFLOG 0x10 /* Log using nf_log backend */ +#define IP6T_LOG_NFLOG 0x10 /* Unsupported, don't use */ #define IP6T_LOG_MASK 0x1f struct ip6t_log_info { diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 46eee64a11f6..c96de16fefae 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -430,13 +430,8 @@ ipt_log_target(struct sk_buff **pskb, li.u.log.level = loginfo->level; li.u.log.logflags = loginfo->logflags; - if (loginfo->logflags & IPT_LOG_NFLOG) - nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, - "%s", loginfo->prefix); - else - ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, - loginfo->prefix); - + ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, + loginfo->prefix); return IPT_CONTINUE; } diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index f4857cf97f05..33b1faa90d74 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -440,13 +440,8 @@ ip6t_log_target(struct sk_buff **pskb, li.u.log.level = loginfo->level; li.u.log.logflags = loginfo->logflags; - if (loginfo->logflags & IP6T_LOG_NFLOG) - nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, - "%s", loginfo->prefix); - else - ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, - loginfo->prefix); - + ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, + loginfo->prefix); return IP6T_CONTINUE; } diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 7e6125467c12..d191dacead5e 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -184,6 +184,17 @@ config NETFILTER_XT_TARGET_NFQUEUE To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_TARGET_NFLOG + tristate '"NFLOG" target support' + depends on NETFILTER_XTABLES + help + This option enables the NFLOG target, which allows to LOG + messages through the netfilter logging API, which can use + either the old LOG target, the old ULOG target or nfnetlink_log + as backend. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_TARGET_NOTRACK tristate '"NOTRACK" target support' depends on NETFILTER_XTABLES diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index f85811bfcfe5..7f0089c584bf 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c new file mode 100644 index 000000000000..901ed7abaa1b --- /dev/null +++ b/net/netfilter/xt_NFLOG.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006 Patrick McHardy + * + * 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 + +MODULE_AUTHOR("Patrick McHardy "); +MODULE_DESCRIPTION("x_tables NFLOG target"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_NFLOG"); +MODULE_ALIAS("ip6t_NFLOG"); + +static unsigned int +nflog_target(struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, + const void *targinfo) +{ + const struct xt_nflog_info *info = targinfo; + struct nf_loginfo li; + + li.type = NF_LOG_TYPE_ULOG; + li.u.ulog.copy_len = info->len; + li.u.ulog.group = info->group; + li.u.ulog.qthreshold = info->threshold; + + nf_log_packet(target->family, hooknum, *pskb, in, out, &li, + "%s", info->prefix); + return XT_CONTINUE; +} + +static int +nflog_checkentry(const char *tablename, const void *entry, + const struct xt_target *target, void *targetinfo, + unsigned int hookmask) +{ + struct xt_nflog_info *info = targetinfo; + + if (info->flags & ~XT_NFLOG_MASK) + return 0; + if (info->prefix[sizeof(info->prefix) - 1] != '\0') + return 0; + return 1; +} + +static struct xt_target xt_nflog_target[] = { + { + .name = "NFLOG", + .family = AF_INET, + .checkentry = nflog_checkentry, + .target = nflog_target, + .targetsize = sizeof(struct xt_nflog_info), + .me = THIS_MODULE, + }, + { + .name = "NFLOG", + .family = AF_INET6, + .checkentry = nflog_checkentry, + .target = nflog_target, + .targetsize = sizeof(struct xt_nflog_info), + .me = THIS_MODULE, + }, +}; + +static int __init xt_nflog_init(void) +{ + return xt_register_targets(xt_nflog_target, + ARRAY_SIZE(xt_nflog_target)); +} + +static void __exit xt_nflog_fini(void) +{ + xt_unregister_targets(xt_nflog_target, ARRAY_SIZE(xt_nflog_target)); +} + +module_init(xt_nflog_init); +module_exit(xt_nflog_fini); -- cgit v1.2.3-70-g09d2 From d12cdc3ccf140bd2febef1c1be92284571da983f Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Wed, 29 Nov 2006 02:35:40 +0100 Subject: [NETFILTER]: ebtables: add --snap-arp option The attached patch adds --snat-arp support, which makes it possible to change the source mac address in both the mac header and the arp header with one rule. Signed-off-by: Bart De Schuymer Signed-off-by: Patrick McHardy --- include/linux/netfilter_bridge/ebt_nat.h | 1 + include/linux/netfilter_bridge/ebtables.h | 4 ++++ net/bridge/netfilter/ebt_mark.c | 6 +++--- net/bridge/netfilter/ebt_snat.c | 27 ++++++++++++++++++++++++--- 4 files changed, 32 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h index 26fd90da4cd6..435b886a51aa 100644 --- a/include/linux/netfilter_bridge/ebt_nat.h +++ b/include/linux/netfilter_bridge/ebt_nat.h @@ -1,6 +1,7 @@ #ifndef __LINUX_BRIDGE_EBT_NAT_H #define __LINUX_BRIDGE_EBT_NAT_H +#define NAT_ARP_BIT (0x00000010) struct ebt_nat_info { unsigned char mac[ETH_ALEN]; diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index e6ea70de24d5..87775264ff0b 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -26,6 +26,10 @@ #define EBT_CONTINUE -3 #define EBT_RETURN -4 #define NUM_STANDARD_TARGETS 4 +/* ebtables target modules store the verdict inside an int. We can + * reclaim a part of this int for backwards compatible extensions. + * The 4 lsb are more than enough to store the verdict. */ +#define EBT_VERDICT_BITS 0x0000000F struct ebt_counter { diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 2458638561cb..62d23c7b25e6 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -33,7 +33,7 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, else (*pskb)->mark ^= info->mark; - return info->target | -16; + return info->target | ~EBT_VERDICT_BITS; } static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, @@ -44,13 +44,13 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) return -EINVAL; - tmp = info->target | -16; + tmp = info->target | ~EBT_VERDICT_BITS; if (BASE_CHAIN && tmp == EBT_RETURN) return -EINVAL; CLEAR_BASE_CHAIN_BIT; if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) return -EINVAL; - tmp = info->target & -16; + tmp = info->target & ~EBT_VERDICT_BITS; if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) return -EINVAL; diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index cbb33e24ca8a..a50722182bfe 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, @@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, *pskb = nskb; } memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN); - return info->target; + if (!(info->target & NAT_ARP_BIT) && + eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) { + struct arphdr _ah, *ap; + + ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah); + if (ap == NULL) + return EBT_DROP; + if (ap->ar_hln != ETH_ALEN) + goto out; + if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN)) + return EBT_DROP; + } +out: + return info->target | ~EBT_VERDICT_BITS; } static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { struct ebt_nat_info *info = (struct ebt_nat_info *) data; + int tmp; if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) return -EINVAL; - if (BASE_CHAIN && info->target == EBT_RETURN) + tmp = info->target | ~EBT_VERDICT_BITS; + if (BASE_CHAIN && tmp == EBT_RETURN) return -EINVAL; CLEAR_BASE_CHAIN_BIT; if (strcmp(tablename, "nat")) return -EINVAL; if (hookmask & ~(1 << NF_BR_POST_ROUTING)) return -EINVAL; - if (INVALID_TARGET) + + if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) + return -EINVAL; + tmp = info->target | EBT_VERDICT_BITS; + if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) return -EINVAL; return 0; } -- cgit v1.2.3-70-g09d2 From 65195686ff2f088a73c1764f4d30be5c7e0eb089 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:41 +0100 Subject: [NETFILTER]: remove remaining ASSERT_{READ,WRITE}_LOCK Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_core.c | 6 ------ net/ipv4/netfilter/ip_conntrack_proto_gre.c | 2 -- net/ipv4/netfilter/ip_conntrack_standalone.c | 4 ---- net/ipv4/netfilter/ipt_CLUSTERIP.c | 3 --- net/netfilter/nf_conntrack_helper.c | 3 --- 5 files changed, 18 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 4d1f954d459b..f4b0e68a16d2 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -40,9 +40,6 @@ /* ip_conntrack_lock protects the main hash table, protocol/helper/expected registrations, conntrack timers*/ -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) - #include #include #include @@ -201,7 +198,6 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse, /* ip_conntrack_expect helper functions */ void ip_ct_unlink_expect(struct ip_conntrack_expect *exp) { - ASSERT_WRITE_LOCK(&ip_conntrack_lock); IP_NF_ASSERT(!timer_pending(&exp->timeout)); list_del(&exp->list); CONNTRACK_STAT_INC(expect_delete); @@ -294,7 +290,6 @@ static void clean_from_lists(struct ip_conntrack *ct) { DEBUGP("clean_from_lists(%p)\n", ct); - ASSERT_WRITE_LOCK(&ip_conntrack_lock); list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); @@ -373,7 +368,6 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, struct ip_conntrack_tuple_hash *h; unsigned int hash = hash_conntrack(tuple); - ASSERT_READ_LOCK(&ip_conntrack_lock); list_for_each_entry(h, &ip_conntrack_hash[hash], list) { if (tuplehash_to_ctrack(h) != ignored_conntrack && ip_ct_tuple_equal(tuple, &h->tuple)) { diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c index 5fe026f467d3..ac1c49ef36a9 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -34,8 +34,6 @@ #include static DEFINE_RWLOCK(ip_ct_gre_lock); -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) #include #include diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 2df67538ffb0..86efb5449676 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -28,9 +28,6 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) - #include #include #include @@ -139,7 +136,6 @@ static int ct_seq_show(struct seq_file *s, void *v) const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash); struct ip_conntrack_protocol *proto; - ASSERT_READ_LOCK(&ip_conntrack_lock); IP_NF_ASSERT(conntrack); /* we only want to print DIR_ORIGINAL */ diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 7a29d6e7baa7..5d43a63e5656 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -40,8 +40,6 @@ #define DEBUGP #endif -#define ASSERT_READ_LOCK(x) - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("iptables target for CLUSTERIP"); @@ -123,7 +121,6 @@ __clusterip_config_find(__be32 clusterip) { struct list_head *pos; - ASSERT_READ_LOCK(&clusterip_lock); list_for_each(pos, &clusterip_configs) { struct clusterip_config *c = list_entry(pos, struct clusterip_config, list); diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 5cbe55f66c15..03b3ed8fca9e 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -21,9 +21,6 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) - #include #include #include -- cgit v1.2.3-70-g09d2 From 76592584be7828cd314bc8d5dc7773ff1692fb99 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:42 +0100 Subject: [NETFILTER]: Fix PROC_FS=n warnings Fix some unused function/variable warnings. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 22 +++++++++++++++------- net/ipv6/netfilter/ip6_queue.c | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 5d43a63e5656..098365062234 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -167,7 +167,6 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, struct net_device *dev) { struct clusterip_config *c; - char buffer[16]; c = kzalloc(sizeof(*c), GFP_ATOMIC); if (!c) @@ -184,12 +183,17 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, atomic_set(&c->entries, 1); #ifdef CONFIG_PROC_FS - /* create proc dir entry */ - sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); - c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, clusterip_procdir); - if (!c->pde) { - kfree(c); - return NULL; + { + char buffer[16]; + + /* create proc dir entry */ + sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); + c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, + clusterip_procdir); + if (!c->pde) { + kfree(c); + return NULL; + } } c->pde->proc_fops = &clusterip_proc_fops; c->pde->data = c; @@ -202,6 +206,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, return c; } +#ifdef CONFIG_PROC_FS static int clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) { @@ -229,6 +234,7 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) return 1; } +#endif static inline u_int32_t clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) @@ -734,8 +740,10 @@ static int __init ipt_clusterip_init(void) CLUSTERIP_VERSION); return 0; +#ifdef CONFIG_PROC_FS cleanup_hook: nf_unregister_hook(&cip_arp_ops); +#endif /* CONFIG_PROC_FS */ cleanup_target: ipt_unregister_target(&clusterip_tgt); return ret; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 21908c9a10da..d4d9f182441a 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -620,6 +620,7 @@ static ctl_table ipq_root_table[] = { { .ctl_name = 0 } }; +#ifdef CONFIG_PROC_FS static int ipq_get_info(char *buffer, char **start, off_t offset, int length) { @@ -653,6 +654,7 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length) len = 0; return len; } +#endif /* CONFIG_PROC_FS */ static struct nf_queue_handler nfqh = { .name = "ip6_queue", -- cgit v1.2.3-70-g09d2 From ef91fd522ba3c88d9c68261c243567bc4c5a8f55 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Nov 2006 02:35:43 +0100 Subject: [NETFILTER]: remove the reference to ipchains from Kconfig It is time to move on :-) Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/Kconfig b/net/Kconfig index 867f95032513..7dfc94920697 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -75,7 +75,7 @@ config NETWORK_SECMARK If you are unsure how to answer this question, answer N. menuconfig NETFILTER - bool "Network packet filtering (replaces ipchains)" + bool "Network packet filtering framework (Netfilter)" ---help--- Netfilter is a framework for filtering and mangling network packets that pass through your Linux box. -- cgit v1.2.3-70-g09d2 From 02752760359db6b00a3ffb1acfc13ef8d9eb1e3f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 29 Nov 2006 13:18:18 -0500 Subject: NetLabel: convert to an extensibile/sparse category bitmap The original NetLabel category bitmap was a straight char bitmap which worked fine for the initial release as it only supported 240 bits due to limitations in the CIPSO restricted bitmap tag (tag type 0x01). This patch converts that straight char bitmap into an extensibile/sparse bitmap in order to lay the foundation for other CIPSO tag types and protocols. This patch also has a nice side effect in that all of the security attributes passed by NetLabel into the LSM are now in a format which is in the host's native byte/bit ordering which makes the LSM specific code much simpler; look at the changes in security/selinux/ss/ebitmap.c as an example. Signed-off-by: Paul Moore Signed-off-by: James Morris --- include/net/netlabel.h | 102 ++++++++++++++++++++- net/ipv4/cipso_ipv4.c | 168 ++++++++++++++-------------------- net/netlabel/netlabel_kapi.c | 201 +++++++++++++++++++++++++++++++++++++++++ security/selinux/ss/ebitmap.c | 198 ++++++++++++++++++---------------------- security/selinux/ss/ebitmap.h | 26 ++++-- security/selinux/ss/mls.c | 156 +++++++++++--------------------- security/selinux/ss/mls.h | 46 +++++++--- security/selinux/ss/services.c | 23 ++--- 8 files changed, 568 insertions(+), 352 deletions(-) (limited to 'net') diff --git a/include/net/netlabel.h b/include/net/netlabel.h index d605d7954013..83da7e1f0d3d 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -111,6 +111,22 @@ struct netlbl_lsm_cache { void (*free) (const void *data); void *data; }; +/* The catmap bitmap field MUST be a power of two in length and large + * enough to hold at least 240 bits. Special care (i.e. check the code!) + * should be used when changing these values as the LSM implementation + * probably has functions which rely on the sizes of these types to speed + * processing. */ +#define NETLBL_CATMAP_MAPTYPE u64 +#define NETLBL_CATMAP_MAPCNT 4 +#define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8) +#define NETLBL_CATMAP_SIZE (NETLBL_CATMAP_MAPSIZE * \ + NETLBL_CATMAP_MAPCNT) +#define NETLBL_CATMAP_BIT (NETLBL_CATMAP_MAPTYPE)0x01 +struct netlbl_lsm_secattr_catmap { + u32 startbit; + NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT]; + struct netlbl_lsm_secattr_catmap *next; +}; #define NETLBL_SECATTR_NONE 0x00000000 #define NETLBL_SECATTR_DOMAIN 0x00000001 #define NETLBL_SECATTR_CACHE 0x00000002 @@ -122,8 +138,7 @@ struct netlbl_lsm_secattr { char *domain; u32 mls_lvl; - unsigned char *mls_cat; - size_t mls_cat_len; + struct netlbl_lsm_secattr_catmap *mls_cat; struct netlbl_lsm_cache *cache; }; @@ -170,6 +185,41 @@ static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache) kfree(cache); } +/** + * netlbl_secattr_catmap_alloc - Allocate a LSM secattr catmap + * @flags: memory allocation flags + * + * Description: + * Allocate memory for a LSM secattr catmap, returns a pointer on success, NULL + * on failure. + * + */ +static inline struct netlbl_lsm_secattr_catmap *netlbl_secattr_catmap_alloc( + gfp_t flags) +{ + return kzalloc(sizeof(struct netlbl_lsm_secattr_catmap), flags); +} + +/** + * netlbl_secattr_catmap_free - Free a LSM secattr catmap + * @catmap: the category bitmap + * + * Description: + * Free a LSM secattr catmap. + * + */ +static inline void netlbl_secattr_catmap_free( + struct netlbl_lsm_secattr_catmap *catmap) +{ + struct netlbl_lsm_secattr_catmap *iter; + + do { + iter = catmap; + catmap = catmap->next; + kfree(iter); + } while (catmap); +} + /** * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct * @secattr: the struct to initialize @@ -200,7 +250,8 @@ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr) if (secattr->cache) netlbl_secattr_cache_free(secattr->cache); kfree(secattr->domain); - kfree(secattr->mls_cat); + if (secattr->mls_cat) + netlbl_secattr_catmap_free(secattr->mls_cat); } /** @@ -231,6 +282,51 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr) kfree(secattr); } +#ifdef CONFIG_NETLABEL +int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset); +int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset); +int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, + u32 bit, + gfp_t flags); +int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, + u32 start, + u32 end, + gfp_t flags); +#else +static inline int netlbl_secattr_catmap_walk( + struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + return -ENOENT; +} + +static inline int netlbl_secattr_catmap_walk_rng( + struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + return -ENOENT; +} + +static inline int netlbl_secattr_catmap_setbit( + struct netlbl_lsm_secattr_catmap *catmap, + u32 bit, + gfp_t flags) +{ + return 0; +} + +static inline int netlbl_secattr_catmap_setrng( + struct netlbl_lsm_secattr_catmap *catmap, + u32 start, + u32 end, + gfp_t flags) +{ + return 0; +} +#endif + /* * LSM protocol operations */ diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index f3957cfaed42..08144f8fc911 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -819,8 +819,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, /** * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network * @doi_def: the DOI definition - * @host_cat: the category bitmap in host format - * @host_cat_len: the length of the host's category bitmap in bytes + * @secattr: the security attributes * @net_cat: the zero'd out category bitmap in network/CIPSO format * @net_cat_len: the length of the CIPSO bitmap in bytes * @@ -831,61 +830,51 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, * */ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, - const unsigned char *host_cat, - u32 host_cat_len, + const struct netlbl_lsm_secattr *secattr, unsigned char *net_cat, u32 net_cat_len) { int host_spot = -1; - u32 net_spot; + u32 net_spot = CIPSO_V4_INV_CAT; u32 net_spot_max = 0; - u32 host_clen_bits = host_cat_len * 8; u32 net_clen_bits = net_cat_len * 8; - u32 host_cat_size; - u32 *host_cat_array; + u32 host_cat_size = 0; + u32 *host_cat_array = NULL; - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - net_spot_max = host_cat_len; - while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0) - net_spot_max--; - if (net_spot_max > net_cat_len) - return -EINVAL; - memcpy(net_cat, host_cat, net_spot_max); - return net_spot_max; - case CIPSO_V4_MAP_STD: + if (doi_def->type == CIPSO_V4_MAP_STD) { host_cat_size = doi_def->map.std->cat.local_size; host_cat_array = doi_def->map.std->cat.local; - for (;;) { - host_spot = cipso_v4_bitmap_walk(host_cat, - host_clen_bits, - host_spot + 1, - 1); - if (host_spot < 0) - break; + } + + for (;;) { + host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat, + host_spot + 1); + if (host_spot < 0) + break; + + switch (doi_def->type) { + case CIPSO_V4_MAP_PASS: + net_spot = host_spot; + break; + case CIPSO_V4_MAP_STD: if (host_spot >= host_cat_size) return -EPERM; - net_spot = host_cat_array[host_spot]; if (net_spot >= CIPSO_V4_INV_CAT) return -EPERM; - if (net_spot >= net_clen_bits) - return -ENOSPC; - cipso_v4_bitmap_setbit(net_cat, net_spot, 1); - - if (net_spot > net_spot_max) - net_spot_max = net_spot; + break; } + if (net_spot >= net_clen_bits) + return -ENOSPC; + cipso_v4_bitmap_setbit(net_cat, net_spot, 1); - if (host_spot == -2) - return -EFAULT; - - if (++net_spot_max % 8) - return net_spot_max / 8 + 1; - return net_spot_max / 8; + if (net_spot > net_spot_max) + net_spot_max = net_spot; } - return -EINVAL; + if (++net_spot_max % 8) + return net_spot_max / 8 + 1; + return net_spot_max / 8; } /** @@ -893,66 +882,59 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, * @doi_def: the DOI definition * @net_cat: the category bitmap in network/CIPSO format * @net_cat_len: the length of the CIPSO bitmap in bytes - * @host_cat: the zero'd out category bitmap in host format - * @host_cat_len: the length of the host's category bitmap in bytes + * @secattr: the security attributes * * Description: * Perform a label mapping to translate a CIPSO bitmap to the correct local - * MLS category bitmap using the given DOI definition. Returns the minimum - * size in bytes of the host bitmap on success, negative values otherwise. + * MLS category bitmap using the given DOI definition. Returns zero on + * success, negative values on failure. * */ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, const unsigned char *net_cat, u32 net_cat_len, - unsigned char *host_cat, - u32 host_cat_len) + struct netlbl_lsm_secattr *secattr) { - u32 host_spot; - u32 host_spot_max = 0; + int ret_val; int net_spot = -1; + u32 host_spot = CIPSO_V4_INV_CAT; u32 net_clen_bits = net_cat_len * 8; - u32 host_clen_bits = host_cat_len * 8; - u32 net_cat_size; - u32 *net_cat_array; + u32 net_cat_size = 0; + u32 *net_cat_array = NULL; - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - if (net_cat_len > host_cat_len) - return -EINVAL; - memcpy(host_cat, net_cat, net_cat_len); - return net_cat_len; - case CIPSO_V4_MAP_STD: + if (doi_def->type == CIPSO_V4_MAP_STD) { net_cat_size = doi_def->map.std->cat.cipso_size; net_cat_array = doi_def->map.std->cat.cipso; - for (;;) { - net_spot = cipso_v4_bitmap_walk(net_cat, - net_clen_bits, - net_spot + 1, - 1); - if (net_spot < 0) - break; - if (net_spot >= net_cat_size || - net_cat_array[net_spot] >= CIPSO_V4_INV_CAT) - return -EPERM; + } + for (;;) { + net_spot = cipso_v4_bitmap_walk(net_cat, + net_clen_bits, + net_spot + 1, + 1); + if (net_spot < 0) { + if (net_spot == -2) + return -EFAULT; + return 0; + } + + switch (doi_def->type) { + case CIPSO_V4_MAP_PASS: + host_spot = net_spot; + break; + case CIPSO_V4_MAP_STD: + if (net_spot >= net_cat_size) + return -EPERM; host_spot = net_cat_array[net_spot]; if (host_spot >= CIPSO_V4_INV_CAT) return -EPERM; - if (host_spot >= host_clen_bits) - return -ENOSPC; - cipso_v4_bitmap_setbit(host_cat, host_spot, 1); - - if (host_spot > host_spot_max) - host_spot_max = host_spot; + break; } - - if (net_spot == -2) - return -EFAULT; - - if (++host_spot_max % 8) - return host_spot_max / 8 + 1; - return host_spot_max / 8; + ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, + host_spot, + GFP_ATOMIC); + if (ret_val != 0) + return ret_val; } return -EINVAL; @@ -1016,8 +998,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { ret_val = cipso_v4_map_cat_rbm_hton(doi_def, - secattr->mls_cat, - secattr->mls_cat_len, + secattr, &buffer[4], buffer_len - 4); if (ret_val < 0) @@ -1067,31 +1048,20 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, secattr->flags |= NETLBL_SECATTR_MLS_LVL; if (tag_len > 4) { - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - secattr->mls_cat_len = tag_len - 4; - break; - case CIPSO_V4_MAP_STD: - secattr->mls_cat_len = - doi_def->map.std->cat.local_size; - break; - } - secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC); + secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); if (secattr->mls_cat == NULL) return -ENOMEM; ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, &tag[4], tag_len - 4, - secattr->mls_cat, - secattr->mls_cat_len); - if (ret_val < 0) { - kfree(secattr->mls_cat); + secattr); + if (ret_val != 0) { + netlbl_secattr_catmap_free(secattr->mls_cat); return ret_val; - } else if (ret_val > 0) { - secattr->mls_cat_len = ret_val; - secattr->flags |= NETLBL_SECATTR_MLS_CAT; } + + secattr->flags |= NETLBL_SECATTR_MLS_CAT; } return 0; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index b35ebf94918c..e03a3282c551 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -39,6 +39,207 @@ #include "netlabel_unlabeled.h" #include "netlabel_user.h" +/* + * Security Attribute Functions + */ + +/** + * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit + * @catmap: the category bitmap + * @offset: the offset to start searching at, in bits + * + * Description: + * This function walks a LSM secattr category bitmap starting at @offset and + * returns the spot of the first set bit or -ENOENT if no bits are set. + * + */ +int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_idx; + u32 node_bit; + NETLBL_CATMAP_MAPTYPE bitmap; + + if (offset > iter->startbit) { + while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter = iter->next; + if (iter == NULL) + return -ENOENT; + } + node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = offset - iter->startbit - + (NETLBL_CATMAP_MAPSIZE * node_idx); + } else { + node_idx = 0; + node_bit = 0; + } + bitmap = iter->bitmap[node_idx] >> node_bit; + + for (;;) { + if (bitmap != 0) { + while ((bitmap & NETLBL_CATMAP_BIT) == 0) { + bitmap >>= 1; + node_bit++; + } + return iter->startbit + + (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit; + } + if (++node_idx >= NETLBL_CATMAP_MAPCNT) { + if (iter->next != NULL) { + iter = iter->next; + node_idx = 0; + } else + return -ENOENT; + } + bitmap = iter->bitmap[node_idx]; + node_bit = 0; + } + + return -ENOENT; +} + +/** + * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits + * @catmap: the category bitmap + * @offset: the offset to start searching at, in bits + * + * Description: + * This function walks a LSM secattr category bitmap starting at @offset and + * returns the spot of the first cleared bit or -ENOENT if the offset is past + * the end of the bitmap. + * + */ +int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_idx; + u32 node_bit; + NETLBL_CATMAP_MAPTYPE bitmask; + NETLBL_CATMAP_MAPTYPE bitmap; + + if (offset > iter->startbit) { + while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter = iter->next; + if (iter == NULL) + return -ENOENT; + } + node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = offset - iter->startbit - + (NETLBL_CATMAP_MAPSIZE * node_idx); + } else { + node_idx = 0; + node_bit = 0; + } + bitmask = NETLBL_CATMAP_BIT << node_bit; + + for (;;) { + bitmap = iter->bitmap[node_idx]; + while (bitmask != 0 && (bitmap & bitmask) != 0) { + bitmask <<= 1; + node_bit++; + } + + if (bitmask != 0) + return iter->startbit + + (NETLBL_CATMAP_MAPSIZE * node_idx) + + node_bit - 1; + else if (++node_idx >= NETLBL_CATMAP_MAPCNT) { + if (iter->next == NULL) + return iter->startbit + NETLBL_CATMAP_SIZE - 1; + iter = iter->next; + node_idx = 0; + } + bitmask = NETLBL_CATMAP_BIT; + node_bit = 0; + } + + return -ENOENT; +} + +/** + * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap + * @catmap: the category bitmap + * @bit: the bit to set + * @flags: memory allocation flags + * + * Description: + * Set the bit specified by @bit in @catmap. Returns zero on success, + * negative values on failure. + * + */ +int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, + u32 bit, + gfp_t flags) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_bit; + u32 node_idx; + + while (iter->next != NULL && + bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) + iter = iter->next; + if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter->next = netlbl_secattr_catmap_alloc(flags); + if (iter->next == NULL) + return -ENOMEM; + iter = iter->next; + iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); + } + + /* gcc always rounds to zero when doing integer division */ + node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx); + iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit; + + return 0; +} + +/** + * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap + * @catmap: the category bitmap + * @start: the starting bit + * @end: the last bit in the string + * @flags: memory allocation flags + * + * Description: + * Set a range of bits, starting at @start and ending with @end. Returns zero + * on success, negative values on failure. + * + */ +int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, + u32 start, + u32 end, + gfp_t flags) +{ + int ret_val = 0; + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 iter_max_spot; + u32 spot; + + /* XXX - This could probably be made a bit faster by combining writes + * to the catmap instead of setting a single bit each time, but for + * right now skipping to the start of the range in the catmap should + * be a nice improvement over calling the individual setbit function + * repeatedly from a loop. */ + + while (iter->next != NULL && + start >= (iter->startbit + NETLBL_CATMAP_SIZE)) + iter = iter->next; + iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; + + for (spot = start; spot <= end && ret_val == 0; spot++) { + if (spot >= iter_max_spot && iter->next != NULL) { + iter = iter->next; + iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; + } + ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC); + } + + return ret_val; +} + /* * LSM Functions */ diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d539346ab3a2..ce492a6b38ed 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -6,7 +6,7 @@ /* * Updated: Hewlett-Packard * - * Added ebitmap_export() and ebitmap_import() + * Added support to import/export the NetLabel category bitmap * * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 */ @@ -14,6 +14,7 @@ #include #include #include +#include #include "ebitmap.h" #include "policydb.h" @@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) return 0; } +#ifdef CONFIG_NETLABEL /** - * ebitmap_export - Export an ebitmap to a unsigned char bitmap string - * @src: the ebitmap to export - * @dst: the resulting bitmap string - * @dst_len: length of dst in bytes + * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap + * @ebmap: the ebitmap to export + * @catmap: the NetLabel category bitmap * * Description: - * Allocate a buffer at least src->highbit bits long and export the extensible - * bitmap into the buffer. The bitmap string will be in little endian format, - * i.e. LSB first. The value returned in dst_len may not the true size of the - * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE. - * The caller must free the buffer when finished. Returns zero on success, - * negative values on failure. + * Export a SELinux extensibile bitmap into a NetLabel category bitmap. + * Returns zero on success, negative values on error. * */ -int ebitmap_export(const struct ebitmap *src, - unsigned char **dst, - size_t *dst_len) +int ebitmap_netlbl_export(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap **catmap) { - size_t bitmap_len; - unsigned char *bitmap; - struct ebitmap_node *iter_node; - MAPTYPE node_val; - size_t bitmap_byte; - unsigned char bitmask; - - if (src->highbit == 0) { - *dst = NULL; - *dst_len = 0; + struct ebitmap_node *e_iter = ebmap->node; + struct netlbl_lsm_secattr_catmap *c_iter; + u32 cmap_idx; + + /* This function is a much simpler because SELinux's MAPTYPE happens + * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is + * changed from a u64 this function will most likely need to be changed + * as well. It's not ideal but I think the tradeoff in terms of + * neatness and speed is worth it. */ + + if (e_iter == NULL) { + *catmap = NULL; return 0; } - bitmap_len = src->highbit / 8; - if (src->highbit % 7) - bitmap_len += 1; - - bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + - sizeof(MAPTYPE), - GFP_ATOMIC); - if (bitmap == NULL) + c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC); + if (c_iter == NULL) return -ENOMEM; + *catmap = c_iter; + c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); + + while (e_iter != NULL) { + if (e_iter->startbit >= + (c_iter->startbit + NETLBL_CATMAP_SIZE)) { + c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC); + if (c_iter->next == NULL) + goto netlbl_export_failure; + c_iter = c_iter->next; + c_iter->startbit = e_iter->startbit & + ~(NETLBL_CATMAP_SIZE - 1); + } + cmap_idx = (e_iter->startbit - c_iter->startbit) / + NETLBL_CATMAP_MAPSIZE; + c_iter->bitmap[cmap_idx] = e_iter->map; + e_iter = e_iter->next; + } - iter_node = src->node; - do { - bitmap_byte = iter_node->startbit / 8; - bitmask = 0x80; - node_val = iter_node->map; - do { - if (bitmask == 0) { - bitmap_byte++; - bitmask = 0x80; - } - if (node_val & (MAPTYPE)0x01) - bitmap[bitmap_byte] |= bitmask; - node_val >>= 1; - bitmask >>= 1; - } while (node_val > 0); - iter_node = iter_node->next; - } while (iter_node); - - *dst = bitmap; - *dst_len = bitmap_len; return 0; + +netlbl_export_failure: + netlbl_secattr_catmap_free(*catmap); + return -ENOMEM; } /** - * ebitmap_import - Import an unsigned char bitmap string into an ebitmap - * @src: the bitmap string - * @src_len: the bitmap length in bytes - * @dst: the empty ebitmap + * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap + * @ebmap: the ebitmap to export + * @catmap: the NetLabel category bitmap * * Description: - * This function takes a little endian bitmap string in src and imports it into - * the ebitmap pointed to by dst. Returns zero on success, negative values on - * failure. + * Import a NetLabel category bitmap into a SELinux extensibile bitmap. + * Returns zero on success, negative values on error. * */ -int ebitmap_import(const unsigned char *src, - size_t src_len, - struct ebitmap *dst) +int ebitmap_netlbl_import(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap *catmap) { - size_t src_off = 0; - size_t node_limit; - struct ebitmap_node *node_new; - struct ebitmap_node *node_last = NULL; - u32 i_byte; - u32 i_bit; - unsigned char src_byte; - - while (src_off < src_len) { - if (src_len - src_off >= sizeof(MAPTYPE)) { - if (*(MAPTYPE *)&src[src_off] == 0) { - src_off += sizeof(MAPTYPE); - continue; - } - node_limit = sizeof(MAPTYPE); - } else { - for (src_byte = 0, i_byte = src_off; - i_byte < src_len && src_byte == 0; - i_byte++) - src_byte |= src[i_byte]; - if (src_byte == 0) - break; - node_limit = src_len - src_off; - } + struct ebitmap_node *e_iter = NULL; + struct ebitmap_node *emap_prev = NULL; + struct netlbl_lsm_secattr_catmap *c_iter = catmap; + u32 c_idx; - node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); - if (unlikely(node_new == NULL)) { - ebitmap_destroy(dst); - return -ENOMEM; - } - node_new->startbit = src_off * 8; - for (i_byte = 0; i_byte < node_limit; i_byte++) { - src_byte = src[src_off++]; - for (i_bit = i_byte * 8; src_byte != 0; i_bit++) { - if (src_byte & 0x80) - node_new->map |= MAPBIT << i_bit; - src_byte <<= 1; - } - } + /* This function is a much simpler because SELinux's MAPTYPE happens + * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is + * changed from a u64 this function will most likely need to be changed + * as well. It's not ideal but I think the tradeoff in terms of + * neatness and speed is worth it. */ - if (node_last != NULL) - node_last->next = node_new; - else - dst->node = node_new; - node_last = node_new; - } + do { + for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) { + if (c_iter->bitmap[c_idx] == 0) + continue; + + e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); + if (e_iter == NULL) + goto netlbl_import_failure; + if (emap_prev == NULL) + ebmap->node = e_iter; + else + emap_prev->next = e_iter; + emap_prev = e_iter; - if (likely(node_last != NULL)) - dst->highbit = node_last->startbit + MAPSIZE; + e_iter->startbit = c_iter->startbit + + NETLBL_CATMAP_MAPSIZE * c_idx; + e_iter->map = c_iter->bitmap[c_idx]; + } + c_iter = c_iter->next; + } while (c_iter != NULL); + if (e_iter != NULL) + ebmap->highbit = e_iter->startbit + MAPSIZE; else - ebitmap_init(dst); + ebitmap_destroy(ebmap); return 0; + +netlbl_import_failure: + ebitmap_destroy(ebmap); + return -ENOMEM; } +#endif /* CONFIG_NETLABEL */ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) { diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index da2d4651b10d..1270e34b61c1 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -14,6 +14,8 @@ #ifndef _SS_EBITMAP_H_ #define _SS_EBITMAP_H_ +#include + #define MAPTYPE u64 /* portion of bitmap in each node */ #define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ #define MAPBIT 1ULL /* a bit in the node bitmap */ @@ -69,16 +71,28 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n, int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); -int ebitmap_export(const struct ebitmap *src, - unsigned char **dst, - size_t *dst_len); -int ebitmap_import(const unsigned char *src, - size_t src_len, - struct ebitmap *dst); int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); void ebitmap_destroy(struct ebitmap *e); int ebitmap_read(struct ebitmap *e, void *fp); +#ifdef CONFIG_NETLABEL +int ebitmap_netlbl_export(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap **catmap); +int ebitmap_netlbl_import(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap *catmap); +#else +static inline int ebitmap_netlbl_export(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap **catmap) +{ + return -ENOMEM; +} +static inline int ebitmap_netlbl_import(struct ebitmap *ebmap, + struct netlbl_lsm_secattr_catmap *catmap) +{ + return -ENOMEM; +} +#endif + #endif /* _SS_EBITMAP_H_ */ diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 2cca8e251624..b4f682dc13ff 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -13,7 +13,7 @@ /* * Updated: Hewlett-Packard * - * Added support to import/export the MLS label + * Added support to import/export the MLS label from NetLabel * * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 */ @@ -22,6 +22,7 @@ #include #include #include +#include #include "sidtab.h" #include "mls.h" #include "policydb.h" @@ -571,163 +572,108 @@ int mls_compute_sid(struct context *scontext, return -EINVAL; } +#ifdef CONFIG_NETLABEL /** - * mls_export_lvl - Export the MLS sensitivity levels + * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel * @context: the security context - * @low: the low sensitivity level - * @high: the high sensitivity level + * @secattr: the NetLabel security attributes * * Description: - * Given the security context copy the low MLS sensitivity level into lvl_low - * and the high sensitivity level in lvl_high. The MLS levels are only - * exported if the pointers are not NULL, if they are NULL then that level is - * not exported. + * Given the security context copy the low MLS sensitivity level into the + * NetLabel MLS sensitivity level field. * */ -void mls_export_lvl(const struct context *context, u32 *low, u32 *high) +void mls_export_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) { if (!selinux_mls_enabled) return; - if (low != NULL) - *low = context->range.level[0].sens - 1; - if (high != NULL) - *high = context->range.level[1].sens - 1; + secattr->mls_lvl = context->range.level[0].sens - 1; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; } /** - * mls_import_lvl - Import the MLS sensitivity levels + * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels * @context: the security context - * @low: the low sensitivity level - * @high: the high sensitivity level + * @secattr: the NetLabel security attributes * * Description: - * Given the security context and the two sensitivty levels, set the MLS levels - * in the context according the two given as parameters. Returns zero on - * success, negative values on failure. + * Given the security context and the NetLabel security attributes, copy the + * NetLabel MLS sensitivity level into the context. * */ -void mls_import_lvl(struct context *context, u32 low, u32 high) +void mls_import_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) { if (!selinux_mls_enabled) return; - context->range.level[0].sens = low + 1; - context->range.level[1].sens = high + 1; + context->range.level[0].sens = secattr->mls_lvl + 1; + context->range.level[1].sens = context->range.level[0].sens; } /** - * mls_export_cat - Export the MLS categories + * mls_export_netlbl_cat - Export the MLS categories to NetLabel * @context: the security context - * @low: the low category - * @low_len: length of the cat_low bitmap in bytes - * @high: the high category - * @high_len: length of the cat_high bitmap in bytes + * @secattr: the NetLabel security attributes * * Description: - * Given the security context export the low MLS category bitmap into cat_low - * and the high category bitmap into cat_high. The MLS categories are only - * exported if the pointers are not NULL, if they are NULL then that level is - * not exported. The caller is responsibile for freeing the memory when - * finished. Returns zero on success, negative values on failure. + * Given the security context copy the low MLS categories into the NetLabel + * MLS category field. Returns zero on success, negative values on failure. * */ -int mls_export_cat(const struct context *context, - unsigned char **low, - size_t *low_len, - unsigned char **high, - size_t *high_len) +int mls_export_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) { - int rc = -EPERM; + int rc; - if (!selinux_mls_enabled) { - *low = NULL; - *low_len = 0; - *high = NULL; - *high_len = 0; + if (!selinux_mls_enabled) return 0; - } - if (low != NULL) { - rc = ebitmap_export(&context->range.level[0].cat, - low, - low_len); - if (rc != 0) - goto export_cat_failure; - } - if (high != NULL) { - rc = ebitmap_export(&context->range.level[1].cat, - high, - high_len); - if (rc != 0) - goto export_cat_failure; - } - - return 0; + rc = ebitmap_netlbl_export(&context->range.level[0].cat, + &secattr->mls_cat); + if (rc == 0 && secattr->mls_cat != NULL) + secattr->flags |= NETLBL_SECATTR_MLS_CAT; -export_cat_failure: - if (low != NULL) { - kfree(*low); - *low = NULL; - *low_len = 0; - } - if (high != NULL) { - kfree(*high); - *high = NULL; - *high_len = 0; - } return rc; } /** - * mls_import_cat - Import the MLS categories + * mls_import_netlbl_cat - Import the MLS categories from NetLabel * @context: the security context - * @low: the low category - * @low_len: length of the cat_low bitmap in bytes - * @high: the high category - * @high_len: length of the cat_high bitmap in bytes + * @secattr: the NetLabel security attributes * * Description: - * Given the security context and the two category bitmap strings import the - * categories into the security context. The MLS categories are only imported - * if the pointers are not NULL, if they are NULL they are skipped. Returns - * zero on success, negative values on failure. + * Copy the NetLabel security attributes into the SELinux context; since the + * NetLabel security attribute only contains a single MLS category use it for + * both the low and high categories of the context. Returns zero on success, + * negative values on failure. * */ -int mls_import_cat(struct context *context, - const unsigned char *low, - size_t low_len, - const unsigned char *high, - size_t high_len) +int mls_import_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) { - int rc = -EPERM; + int rc; if (!selinux_mls_enabled) return 0; - if (low != NULL) { - rc = ebitmap_import(low, - low_len, - &context->range.level[0].cat); - if (rc != 0) - goto import_cat_failure; - } - if (high != NULL) { - if (high == low) - rc = ebitmap_cpy(&context->range.level[1].cat, - &context->range.level[0].cat); - else - rc = ebitmap_import(high, - high_len, - &context->range.level[1].cat); - if (rc != 0) - goto import_cat_failure; - } + rc = ebitmap_netlbl_import(&context->range.level[0].cat, + secattr->mls_cat); + if (rc != 0) + goto import_netlbl_cat_failure; + + rc = ebitmap_cpy(&context->range.level[1].cat, + &context->range.level[0].cat); + if (rc != 0) + goto import_netlbl_cat_failure; return 0; -import_cat_failure: +import_netlbl_cat_failure: ebitmap_destroy(&context->range.level[0].cat); ebitmap_destroy(&context->range.level[1].cat); return rc; } +#endif /* CONFIG_NETLABEL */ diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index df6032c6d492..661d6fc76966 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -13,7 +13,7 @@ /* * Updated: Hewlett-Packard * - * Added support to import/export the MLS label + * Added support to import/export the MLS label from NetLabel * * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 */ @@ -69,19 +69,37 @@ int mls_compute_sid(struct context *scontext, int mls_setup_user_range(struct context *fromcon, struct user_datum *user, struct context *usercon); -void mls_export_lvl(const struct context *context, u32 *low, u32 *high); -void mls_import_lvl(struct context *context, u32 low, u32 high); - -int mls_export_cat(const struct context *context, - unsigned char **low, - size_t *low_len, - unsigned char **high, - size_t *high_len); -int mls_import_cat(struct context *context, - const unsigned char *low, - size_t low_len, - const unsigned char *high, - size_t high_len); +#ifdef CONFIG_NETLABEL +void mls_export_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr); +void mls_import_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr); +int mls_export_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr); +int mls_import_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr); +#else +static inline void mls_export_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + return; +} +static inline void mls_import_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + return; +} +static inline int mls_export_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + return -ENOMEM; +} +static inline int mls_import_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + return -ENOMEM; +} +#endif #endif /* _SS_MLS_H */ diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b43dd803fd5e..bdb7070dd3dc 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -55,6 +55,7 @@ #include "objsec.h" #include "selinux_netlabel.h" #include "xfrm.h" +#include "ebitmap.h" extern void selnl_notify_policyload(u32 seqno); unsigned int policydb_loaded_version; @@ -2384,13 +2385,10 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ctx_new.user = ctx->user; ctx_new.role = ctx->role; ctx_new.type = ctx->type; - mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); + mls_import_netlbl_lvl(&ctx_new, secattr); if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { - if (mls_import_cat(&ctx_new, - secattr->mls_cat, - secattr->mls_cat_len, - NULL, - 0) != 0) + if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, + secattr->mls_cat) != 0) goto netlbl_secattr_to_sid_return; ctx_new.range.level[1].cat.highbit = ctx_new.range.level[0].cat.highbit; @@ -2486,19 +2484,12 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], GFP_ATOMIC); - mls_export_lvl(ctx, &secattr.mls_lvl, NULL); - rc = mls_export_cat(ctx, - &secattr.mls_cat, - &secattr.mls_cat_len, - NULL, - NULL); + secattr.flags |= NETLBL_SECATTR_DOMAIN; + mls_export_netlbl_lvl(ctx, &secattr); + rc = mls_export_netlbl_cat(ctx, &secattr); if (rc != 0) goto netlbl_socket_setsid_return; - secattr.flags |= NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; - if (secattr.mls_cat) - secattr.flags |= NETLBL_SECATTR_MLS_CAT; - rc = netlbl_socket_setattr(sock, &secattr); if (rc == 0) { spin_lock(&sksec->nlbl_lock); -- cgit v1.2.3-70-g09d2 From 654bbc2a2b87185630d05b79cc0db0e9364bb7e0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 29 Nov 2006 13:18:19 -0500 Subject: NetLabel: add the enumerated tag to the CIPSOv4 protocol Add support for the enumerated tag (tag type #2) to the CIPSOv4 protocol. The enumerated tag allows for 15 categories to be specified in a CIPSO option, where each category is an unsigned 16 bit field with a maximum value of 65534. See Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt for more details. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 08144f8fc911..70858dccaca2 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -459,6 +459,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) if (iter == 0) return -EINVAL; break; + case CIPSO_V4_TAG_ENUM: + if (doi_def->type != CIPSO_V4_MAP_PASS) + return -EINVAL; + break; default: return -EINVAL; } @@ -940,6 +944,107 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, return -EINVAL; } +/** + * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid + * @doi_def: the DOI definition + * @enumcat: category list + * @enumcat_len: length of the category list in bytes + * + * Description: + * Checks the given categories against the given DOI definition and returns a + * negative value if any of the categories do not have a valid mapping and a + * zero value if all of the categories are valid. + * + */ +static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def, + const unsigned char *enumcat, + u32 enumcat_len) +{ + u16 cat; + int cat_prev = -1; + u32 iter; + + if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01) + return -EFAULT; + + for (iter = 0; iter < enumcat_len; iter += 2) { + cat = ntohs(*((__be16 *)&enumcat[iter])); + if (cat <= cat_prev) + return -EFAULT; + cat_prev = cat; + } + + return 0; +} + +/** + * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network + * @doi_def: the DOI definition + * @secattr: the security attributes + * @net_cat: the zero'd out category list in network/CIPSO format + * @net_cat_len: the length of the CIPSO category list in bytes + * + * Description: + * Perform a label mapping to translate a local MLS category bitmap to the + * correct CIPSO category list using the given DOI definition. Returns the + * size in bytes of the network category bitmap on success, negative values + * otherwise. + * + */ +static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr, + unsigned char *net_cat, + u32 net_cat_len) +{ + int cat = -1; + u32 cat_iter = 0; + + for (;;) { + cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1); + if (cat < 0) + break; + if ((cat_iter + 2) > net_cat_len) + return -ENOSPC; + + *((__be16 *)&net_cat[cat_iter]) = htons(cat); + cat_iter += 2; + } + + return cat_iter; +} + +/** + * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host + * @doi_def: the DOI definition + * @net_cat: the category list in network/CIPSO format + * @net_cat_len: the length of the CIPSO bitmap in bytes + * @secattr: the security attributes + * + * Description: + * Perform a label mapping to translate a CIPSO category list to the correct + * local MLS category bitmap using the given DOI definition. Returns zero on + * success, negative values on failure. + * + */ +static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def, + const unsigned char *net_cat, + u32 net_cat_len, + struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + u32 iter; + + for (iter = 0; iter < net_cat_len; iter += 2) { + ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, + ntohs(*((__be16 *)&net_cat[iter])), + GFP_ATOMIC); + if (ret_val != 0) + return ret_val; + } + + return 0; +} + /* * Protocol Handling Functions */ @@ -1067,6 +1172,99 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, return 0; } +/** + * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2) + * @doi_def: the DOI definition + * @secattr: the security attributes + * @buffer: the option buffer + * @buffer_len: length of buffer in bytes + * + * Description: + * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the + * size of the tag on success, negative values on failure. + * + */ +static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr, + unsigned char *buffer, + u32 buffer_len) +{ + int ret_val; + u32 tag_len; + u32 level; + + if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL)) + return -EPERM; + + ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); + if (ret_val != 0) + return ret_val; + + if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { + ret_val = cipso_v4_map_cat_enum_hton(doi_def, + secattr, + &buffer[4], + buffer_len - 4); + if (ret_val < 0) + return ret_val; + + tag_len = 4 + ret_val; + } else + tag_len = 4; + + buffer[0] = 0x02; + buffer[1] = tag_len; + buffer[3] = level; + + return tag_len; +} + +/** + * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag + * @doi_def: the DOI definition + * @tag: the CIPSO tag + * @secattr: the security attributes + * + * Description: + * Parse a CIPSO enumerated tag (tag type #2) and return the security + * attributes in @secattr. Return zero on success, negatives values on + * failure. + * + */ +static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def, + const unsigned char *tag, + struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + u8 tag_len = tag[1]; + u32 level; + + ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); + if (ret_val != 0) + return ret_val; + secattr->mls_lvl = level; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; + + if (tag_len > 4) { + secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); + if (secattr->mls_cat == NULL) + return -ENOMEM; + + ret_val = cipso_v4_map_cat_enum_ntoh(doi_def, + &tag[4], + tag_len - 4, + secattr); + if (ret_val != 0) { + netlbl_secattr_catmap_free(secattr->mls_cat); + return ret_val; + } + + secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +} + /** * cipso_v4_validate - Validate a CIPSO option * @option: the start of the option, on error it is set to point to the error @@ -1156,6 +1354,25 @@ int cipso_v4_validate(unsigned char **option) } } break; + case CIPSO_V4_TAG_ENUM: + if (tag_len < 4) { + err_offset = opt_iter + 1; + goto validate_return_locked; + } + + if (cipso_v4_map_lvl_valid(doi_def, + tag[3]) < 0) { + err_offset = opt_iter + 3; + goto validate_return_locked; + } + if (tag_len > 4 && + cipso_v4_map_cat_enum_valid(doi_def, + &tag[4], + tag_len - 4) < 0) { + err_offset = opt_iter + 4; + goto validate_return_locked; + } + break; default: err_offset = opt_iter; goto validate_return_locked; @@ -1269,6 +1486,12 @@ int cipso_v4_socket_setattr(const struct socket *sock, &buf[CIPSO_V4_HDR_LEN], buf_len - CIPSO_V4_HDR_LEN); break; + case CIPSO_V4_TAG_ENUM: + ret_val = cipso_v4_gentag_enum(doi_def, + secattr, + &buf[CIPSO_V4_HDR_LEN], + buf_len - CIPSO_V4_HDR_LEN); + break; default: ret_val = -EPERM; goto socket_setattr_failure; @@ -1365,6 +1588,11 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) &cipso_ptr[6], secattr); break; + case CIPSO_V4_TAG_ENUM: + ret_val = cipso_v4_parsetag_enum(doi_def, + &cipso_ptr[6], + secattr); + break; } rcu_read_unlock(); @@ -1431,6 +1659,11 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, &cipso_ptr[6], secattr); break; + case CIPSO_V4_TAG_ENUM: + ret_val = cipso_v4_parsetag_enum(doi_def, + &cipso_ptr[6], + secattr); + break; } skbuff_getattr_return: -- cgit v1.2.3-70-g09d2 From 484b366932be0b73a22c74a82748ca10a721643e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 29 Nov 2006 13:18:20 -0500 Subject: NetLabel: add the ranged tag to the CIPSOv4 protocol Add support for the ranged tag (tag type #5) to the CIPSOv4 protocol. The ranged tag allows for seven, or eight if zero is the lowest category, category ranges to be specified in a CIPSO option. Each range is specified by two unsigned 16 bit fields, each with a maximum value of 65534. The two values specify the start and end of the category range; if the start of the category range is zero then it is omitted. See Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt for more details. Signed-off-by: Paul Moore Signed-off-by: James Morris --- net/ipv4/cipso_ipv4.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 70858dccaca2..60aafb4a8adf 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -455,6 +455,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) switch (doi_def->tags[iter]) { case CIPSO_V4_TAG_RBITMAP: break; + case CIPSO_V4_TAG_RANGE: + if (doi_def->type != CIPSO_V4_MAP_PASS) + return -EINVAL; + break; case CIPSO_V4_TAG_INVALID: if (iter == 0) return -EINVAL; @@ -1045,6 +1049,148 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def, return 0; } +/** + * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid + * @doi_def: the DOI definition + * @rngcat: category list + * @rngcat_len: length of the category list in bytes + * + * Description: + * Checks the given categories against the given DOI definition and returns a + * negative value if any of the categories do not have a valid mapping and a + * zero value if all of the categories are valid. + * + */ +static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def, + const unsigned char *rngcat, + u32 rngcat_len) +{ + u16 cat_high; + u16 cat_low; + u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1; + u32 iter; + + if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01) + return -EFAULT; + + for (iter = 0; iter < rngcat_len; iter += 4) { + cat_high = ntohs(*((__be16 *)&rngcat[iter])); + if ((iter + 4) <= rngcat_len) + cat_low = ntohs(*((__be16 *)&rngcat[iter + 2])); + else + cat_low = 0; + + if (cat_high > cat_prev) + return -EFAULT; + + cat_prev = cat_low; + } + + return 0; +} + +/** + * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network + * @doi_def: the DOI definition + * @secattr: the security attributes + * @net_cat: the zero'd out category list in network/CIPSO format + * @net_cat_len: the length of the CIPSO category list in bytes + * + * Description: + * Perform a label mapping to translate a local MLS category bitmap to the + * correct CIPSO category list using the given DOI definition. Returns the + * size in bytes of the network category bitmap on success, negative values + * otherwise. + * + */ +static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr, + unsigned char *net_cat, + u32 net_cat_len) +{ + /* The constant '16' is not random, it is the maximum number of + * high/low category range pairs as permitted by the CIPSO draft based + * on a maximum IPv4 header length of 60 bytes - the BUG_ON() assertion + * does a sanity check to make sure we don't overflow the array. */ + int iter = -1; + u16 array[16]; + u32 array_cnt = 0; + u32 cat_size = 0; + + BUG_ON(net_cat_len > 30); + + for (;;) { + iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1); + if (iter < 0) + break; + cat_size += (iter == 0 ? 0 : sizeof(u16)); + if (cat_size > net_cat_len) + return -ENOSPC; + array[array_cnt++] = iter; + + iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter); + if (iter < 0) + return -EFAULT; + cat_size += sizeof(u16); + if (cat_size > net_cat_len) + return -ENOSPC; + array[array_cnt++] = iter; + } + + for (iter = 0; array_cnt > 0;) { + *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]); + iter += 2; + array_cnt--; + if (array[array_cnt] != 0) { + *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]); + iter += 2; + } + } + + return cat_size; +} + +/** + * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host + * @doi_def: the DOI definition + * @net_cat: the category list in network/CIPSO format + * @net_cat_len: the length of the CIPSO bitmap in bytes + * @secattr: the security attributes + * + * Description: + * Perform a label mapping to translate a CIPSO category list to the correct + * local MLS category bitmap using the given DOI definition. Returns zero on + * success, negative values on failure. + * + */ +static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def, + const unsigned char *net_cat, + u32 net_cat_len, + struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + u32 net_iter; + u16 cat_low; + u16 cat_high; + + for(net_iter = 0; net_iter < net_cat_len; net_iter += 4) { + cat_high = ntohs(*((__be16 *)&net_cat[net_iter])); + if ((net_iter + 4) <= net_cat_len) + cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2])); + else + cat_low = 0; + + ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat, + cat_low, + cat_high, + GFP_ATOMIC); + if (ret_val != 0) + return ret_val; + } + + return 0; +} + /* * Protocol Handling Functions */ @@ -1265,6 +1411,98 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def, return 0; } +/** + * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5) + * @doi_def: the DOI definition + * @secattr: the security attributes + * @buffer: the option buffer + * @buffer_len: length of buffer in bytes + * + * Description: + * Generate a CIPSO option using the ranged tag, tag type #5. Returns the + * size of the tag on success, negative values on failure. + * + */ +static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr, + unsigned char *buffer, + u32 buffer_len) +{ + int ret_val; + u32 tag_len; + u32 level; + + if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL)) + return -EPERM; + + ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); + if (ret_val != 0) + return ret_val; + + if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { + ret_val = cipso_v4_map_cat_rng_hton(doi_def, + secattr, + &buffer[4], + buffer_len - 4); + if (ret_val < 0) + return ret_val; + + tag_len = 4 + ret_val; + } else + tag_len = 4; + + buffer[0] = 0x05; + buffer[1] = tag_len; + buffer[3] = level; + + return tag_len; +} + +/** + * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag + * @doi_def: the DOI definition + * @tag: the CIPSO tag + * @secattr: the security attributes + * + * Description: + * Parse a CIPSO ranged tag (tag type #5) and return the security attributes + * in @secattr. Return zero on success, negatives values on failure. + * + */ +static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, + const unsigned char *tag, + struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + u8 tag_len = tag[1]; + u32 level; + + ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); + if (ret_val != 0) + return ret_val; + secattr->mls_lvl = level; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; + + if (tag_len > 4) { + secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); + if (secattr->mls_cat == NULL) + return -ENOMEM; + + ret_val = cipso_v4_map_cat_rng_ntoh(doi_def, + &tag[4], + tag_len - 4, + secattr); + if (ret_val != 0) { + netlbl_secattr_catmap_free(secattr->mls_cat); + return ret_val; + } + + secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +} + /** * cipso_v4_validate - Validate a CIPSO option * @option: the start of the option, on error it is set to point to the error @@ -1373,6 +1611,25 @@ int cipso_v4_validate(unsigned char **option) goto validate_return_locked; } break; + case CIPSO_V4_TAG_RANGE: + if (tag_len < 4) { + err_offset = opt_iter + 1; + goto validate_return_locked; + } + + if (cipso_v4_map_lvl_valid(doi_def, + tag[3]) < 0) { + err_offset = opt_iter + 3; + goto validate_return_locked; + } + if (tag_len > 4 && + cipso_v4_map_cat_rng_valid(doi_def, + &tag[4], + tag_len - 4) < 0) { + err_offset = opt_iter + 4; + goto validate_return_locked; + } + break; default: err_offset = opt_iter; goto validate_return_locked; @@ -1492,6 +1749,12 @@ int cipso_v4_socket_setattr(const struct socket *sock, &buf[CIPSO_V4_HDR_LEN], buf_len - CIPSO_V4_HDR_LEN); break; + case CIPSO_V4_TAG_RANGE: + ret_val = cipso_v4_gentag_rng(doi_def, + secattr, + &buf[CIPSO_V4_HDR_LEN], + buf_len - CIPSO_V4_HDR_LEN); + break; default: ret_val = -EPERM; goto socket_setattr_failure; @@ -1593,6 +1856,11 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) &cipso_ptr[6], secattr); break; + case CIPSO_V4_TAG_RANGE: + ret_val = cipso_v4_parsetag_rng(doi_def, + &cipso_ptr[6], + secattr); + break; } rcu_read_unlock(); -- cgit v1.2.3-70-g09d2 From 814a175e7b1531a4bcaa63be47bf58cacdcb5010 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:34:50 -0800 Subject: [NET_SCHED]: sch_htb: perform qlen adjustment immediately in ->delete qlen adjustment should happen immediately in ->delete and not in the class destroy function because the reference count will not hit zero in ->delete (sch_api holds a reference) but in ->put. Since the qdisc lock is released between deletion of the class and final destruction this creates an externally visible error in the qlen counter. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 4b52fa78935a..08fa4d083615 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1269,9 +1269,9 @@ static void htb_destroy_filters(struct tcf_proto **fl) static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) { struct htb_sched *q = qdisc_priv(sch); + if (!cl->level) { BUG_TRAP(cl->un.leaf.q); - sch->q.qlen -= cl->un.leaf.q->q.qlen; qdisc_destroy(cl->un.leaf.q); } qdisc_put_rtab(cl->rate); @@ -1334,6 +1334,11 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) /* delete from hash and active; remainder in destroy_class */ hlist_del_init(&cl->hlist); + if (!cl->level) { + sch->q.qlen -= cl->un.leaf.q->q.qlen; + qdisc_reset(cl->un.leaf.q); + } + if (cl->prio_activity) htb_deactivate(q, cl); -- cgit v1.2.3-70-g09d2 From 9f9afec48221fe4a19f84a9341f5b304bf7d7783 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:35:18 -0800 Subject: [NET_SCHED]: Set parent classid in default qdiscs Set parent classids in default qdiscs to allow walking up the tree from outside the qdiscs. This is needed by the next patch. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 +- net/sched/sch_atm.c | 5 +++-- net/sched/sch_cbq.c | 8 +++++--- net/sched/sch_dsmark.c | 5 +++-- net/sched/sch_generic.c | 7 +++++-- net/sched/sch_hfsc.c | 8 +++++--- net/sched/sch_htb.c | 7 ++++--- net/sched/sch_netem.c | 3 ++- net/sched/sch_prio.c | 3 ++- net/sched/sch_red.c | 8 +++++--- net/sched/sch_tbf.c | 8 +++++--- 11 files changed, 40 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 6b3829480b3a..b37572db12ab 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -174,7 +174,7 @@ extern void qdisc_reset(struct Qdisc *qdisc); extern void qdisc_destroy(struct Qdisc *qdisc); extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, - struct Qdisc_ops *ops); + struct Qdisc_ops *ops, u32 parentid); static inline void tcf_destroy(struct tcf_proto *tp) diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index dbf44da0912f..edc7bb0b9c8b 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -316,7 +316,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, } memset(flow,0,sizeof(*flow)); flow->filter_list = NULL; - if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) + if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid))) flow->q = &noop_qdisc; DPRINTK("atm_tc_change: qdisc %p\n",flow->q); flow->sock = sock; @@ -576,7 +576,8 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); p->flows = &p->link; - if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) + if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops, + sch->handle))) p->link.q = &noop_qdisc; DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q); p->link.filter_list = NULL; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index bac881bfe362..908b10d0d61f 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1429,7 +1429,8 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt) q->link.sibling = &q->link; q->link.classid = sch->handle; q->link.qdisc = sch; - if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) + if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + sch->handle))) q->link.q = &noop_qdisc; q->link.priority = TC_CBQ_MAXPRIO-1; @@ -1674,7 +1675,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, if (cl) { if (new == NULL) { - if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)) == NULL) + if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + cl->classid)) == NULL) return -ENOBUFS; } else { #ifdef CONFIG_NET_CLS_POLICE @@ -1932,7 +1934,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t cl->R_tab = rtab; rtab = NULL; cl->refcnt = 1; - if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) + if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid))) cl->q = &noop_qdisc; cl->classid = classid; cl->tparent = parent; diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 0b7c0e82d600..afedd92b7496 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -88,7 +88,8 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg, sch, p, new, old); if (new == NULL) { - new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + sch->handle); if (new == NULL) new = &noop_qdisc; } @@ -387,7 +388,7 @@ static int dsmark_init(struct Qdisc *sch, struct rtattr *opt) p->default_index = default_index; p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]); - p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, sch->handle); if (p->q == NULL) p->q = &noop_qdisc; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 88c6a99ce53c..deafeb9cb70e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -450,13 +450,15 @@ errout: return ERR_PTR(-err); } -struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) +struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, + unsigned int parentid) { struct Qdisc *sch; sch = qdisc_alloc(dev, ops); if (IS_ERR(sch)) goto errout; + sch->parent = parentid; if (!ops->init || ops->init(sch, NULL) == 0) return sch; @@ -520,7 +522,8 @@ void dev_activate(struct net_device *dev) if (dev->qdisc_sleeping == &noop_qdisc) { struct Qdisc *qdisc; if (dev->tx_queue_len) { - qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops); + qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops, + TC_H_ROOT); if (qdisc == NULL) { printk(KERN_INFO "%s: activation failed\n", dev->name); return; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 6a6735a2ed35..1142d298ecf6 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1138,7 +1138,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, cl->classid = classid; cl->sched = q; cl->cl_parent = parent; - cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + 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; @@ -1271,7 +1271,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, if (cl->level > 0) return -EINVAL; if (new == NULL) { - new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + cl->classid); if (new == NULL) new = &noop_qdisc; } @@ -1514,7 +1515,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) q->root.refcnt = 1; q->root.classid = sch->handle; q->root.sched = q; - q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + sch->handle); if (q->root.qdisc == NULL) q->root.qdisc = &noop_qdisc; q->root.stats_lock = &sch->dev->queue_lock; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 08fa4d083615..3b36e9d60c20 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1223,8 +1223,9 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct htb_class *cl = (struct htb_class *)arg; if (cl && !cl->level) { - if (new == NULL && (new = qdisc_create_dflt(sch->dev, - &pfifo_qdisc_ops)) + if (new == NULL && + (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + cl->classid)) == NULL) return -ENOBUFS; sch_tree_lock(sch); @@ -1415,7 +1416,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) so that can't be used inside of sch_tree_lock -- thanks to Karlis Peisenieks */ - new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); sch_tree_lock(sch); if (parent && !parent->level) { /* turn parent into inner node */ diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 0441876aa1e7..90aeeb7b7167 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -574,7 +574,8 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; - q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops); + q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops, + TC_H_MAKE(sch->handle, 1)); if (!q->qdisc) { pr_debug("netem: qdisc create failed\n"); return -ENOMEM; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index a5fa03c0c19b..3fc0c0fa5bcc 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -230,7 +230,8 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt) for (i=0; ibands; i++) { if (q->queues[i] == &noop_qdisc) { struct Qdisc *child; - child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + TC_H_MAKE(sch->handle, i + 1)); if (child) { sch_tree_lock(sch); child = xchg(&q->queues[i], child); diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index d65cadddea69..ee66c5ca80c6 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -175,12 +175,14 @@ static void red_destroy(struct Qdisc *sch) qdisc_destroy(q->qdisc); } -static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit) +static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit) { - struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); + struct Qdisc *q; struct rtattr *rta; int ret; + q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, + TC_H_MAKE(sch->handle, 1)); if (q) { rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); @@ -219,7 +221,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); if (ctl->limit > 0) { - child = red_create_dflt(sch->dev, ctl->limit); + child = red_create_dflt(sch, ctl->limit); if (child == NULL) return -ENOMEM; } diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index d9a5d298d755..2562a6040b76 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -273,12 +273,14 @@ static void tbf_reset(struct Qdisc* sch) del_timer(&q->wd_timer); } -static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit) +static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) { - struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); + struct Qdisc *q; struct rtattr *rta; int ret; + q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, + TC_H_MAKE(sch->handle, 1)); if (q) { rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { @@ -341,7 +343,7 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt) goto done; if (qopt->limit > 0) { - if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) + if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL) goto done; } -- cgit v1.2.3-70-g09d2 From 43effa1e57fc4635e0301b27d78f9d83afe78974 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:35:48 -0800 Subject: [NET_SCHED]: Fix endless loops caused by inaccurate qlen counters (part 1) There are multiple problems related to qlen adjustment that can lead to an upper qdisc getting out of sync with the real number of packets queued, leading to endless dequeueing attempts by the upper layer code. All qdiscs must maintain an accurate q.qlen counter. There are basically two groups of operations affecting the qlen: operations that propagate down the tree (enqueue, dequeue, requeue, drop, reset) beginning at the root qdisc and operations only affecting a subtree or single qdisc (change, graft, delete class). Since qlen changes during operations from the second group don't propagate to ancestor qdiscs, their qlen values become desynchronized. This patch adds a function to propagate qlen changes up the qdisc tree, optionally calling a callback function to perform qdisc-internal maintenance when the child qdisc becomes empty. The follow-up patches will convert all qdiscs to use this function where necessary. Noticed by Timo Steinbach . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 ++ net/sched/sch_api.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index b37572db12ab..82086392735a 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -60,6 +60,7 @@ struct Qdisc_class_ops int (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **); struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); + void (*qlen_notify)(struct Qdisc *, unsigned long); /* Class manipulation routines */ unsigned long (*get)(struct Qdisc *, u32 classid); @@ -172,6 +173,7 @@ extern void dev_activate(struct net_device *dev); extern void dev_deactivate(struct net_device *dev); extern void qdisc_reset(struct Qdisc *qdisc); extern void qdisc_destroy(struct Qdisc *qdisc); +extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n); extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, u32 parentid); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index d99802f3023d..05a93da6f057 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -191,21 +191,27 @@ int unregister_qdisc(struct Qdisc_ops *qops) (root qdisc, all its children, children of children etc.) */ -struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) +static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle) { struct Qdisc *q; - read_lock(&qdisc_tree_lock); list_for_each_entry(q, &dev->qdisc_list, list) { - if (q->handle == handle) { - read_unlock(&qdisc_tree_lock); + if (q->handle == handle) return q; - } } - read_unlock(&qdisc_tree_lock); return NULL; } +struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) +{ + struct Qdisc *q; + + read_lock(&qdisc_tree_lock); + q = __qdisc_lookup(dev, handle); + read_unlock(&qdisc_tree_lock); + return q; +} + static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) { unsigned long cl; @@ -348,6 +354,26 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) return oqdisc; } +void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) +{ + struct Qdisc_class_ops *cops; + unsigned long cl; + u32 parentid; + + if (n == 0) + return; + while ((parentid = sch->parent)) { + sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid)); + cops = sch->ops->cl_ops; + if (cops->qlen_notify) { + cl = cops->get(sch, parentid); + cops->qlen_notify(sch, cl); + cops->put(sch, cl); + } + sch->q.qlen -= n; + } +} +EXPORT_SYMBOL(qdisc_tree_decrease_qlen); /* Graft qdisc "new" to class "classid" of qdisc "parent" or to device "dev". -- cgit v1.2.3-70-g09d2 From 5e50da01d0ce7ef0ba3ed6cfabd62f327da0aca6 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:36:20 -0800 Subject: [NET_SCHED]: Fix endless loops (part 2): "simple" qdiscs Convert the "simple" qdiscs to use qdisc_tree_decrease_qlen() where necessary: - all graft operations - destruction of old child qdiscs in prio, red and tbf change operation - purging of queue in sfq change operation Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_cbq.c | 2 +- net/sched/sch_dsmark.c | 2 +- net/sched/sch_netem.c | 2 +- net/sched/sch_prio.c | 11 ++++++++--- net/sched/sch_red.c | 6 ++++-- net/sched/sch_sfq.c | 3 +++ net/sched/sch_tbf.c | 6 ++++-- 7 files changed, 22 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 908b10d0d61f..ba82dfab6043 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1687,7 +1687,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); *old = cl->q; cl->q = new; - sch->q.qlen -= (*old)->q.qlen; + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); sch_tree_unlock(sch); diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index afedd92b7496..d5421816f007 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -96,8 +96,8 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg, sch_tree_lock(sch); *old = xchg(&p->q, new); + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); - sch->q.qlen = 0; sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 90aeeb7b7167..672c35445793 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -662,8 +662,8 @@ static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); *old = xchg(&q->qdisc, new); + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); - sch->q.qlen = 0; sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 3fc0c0fa5bcc..2567b4c96c1e 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -222,8 +222,10 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt) for (i=q->bands; iqueues[i], &noop_qdisc); - if (child != &noop_qdisc) + if (child != &noop_qdisc) { + qdisc_tree_decrease_qlen(child, child->q.qlen); qdisc_destroy(child); + } } sch_tree_unlock(sch); @@ -236,8 +238,11 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt) sch_tree_lock(sch); child = xchg(&q->queues[i], child); - if (child != &noop_qdisc) + if (child != &noop_qdisc) { + qdisc_tree_decrease_qlen(child, + child->q.qlen); qdisc_destroy(child); + } sch_tree_unlock(sch); } } @@ -295,7 +300,7 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); *old = q->queues[band]; q->queues[band] = new; - sch->q.qlen -= (*old)->q.qlen; + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); sch_tree_unlock(sch); diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index ee66c5ca80c6..acddad08850f 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -229,8 +229,10 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) sch_tree_lock(sch); q->flags = ctl->flags; q->limit = ctl->limit; - if (child) + if (child) { + qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); qdisc_destroy(xchg(&q->qdisc, child)); + } red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, @@ -308,8 +310,8 @@ static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); *old = xchg(&q->qdisc, new); + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); - sch->q.qlen = 0; sch_tree_unlock(sch); return 0; } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index d0d6e595a78c..459cda258a5c 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -393,6 +393,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) { struct sfq_sched_data *q = qdisc_priv(sch); struct tc_sfq_qopt *ctl = RTA_DATA(opt); + unsigned int qlen; if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) return -EINVAL; @@ -403,8 +404,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) if (ctl->limit) q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); + qlen = sch->q.qlen; while (sch->q.qlen >= q->limit-1) sfq_drop(sch); + qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen); del_timer(&q->perturb_timer); if (q->perturb_period) { diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 2562a6040b76..23b7624354f5 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -348,8 +348,10 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt) } sch_tree_lock(sch); - if (child) + if (child) { + qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); qdisc_destroy(xchg(&q->qdisc, child)); + } q->limit = qopt->limit; q->mtu = qopt->mtu; q->max_size = max_size; @@ -451,8 +453,8 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); *old = xchg(&q->qdisc, new); + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); - sch->q.qlen = 0; sch_tree_unlock(sch); return 0; -- cgit v1.2.3-70-g09d2 From f973b913e18ab5a4795738ddf8a8666ac306ee12 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:36:43 -0800 Subject: [NET_SCHED]: Fix endless loops (part 3): HFSC Convert HFSC to use qdisc_tree_decrease_len() and add a callback for deactivating a class when its child queue becomes empty. All queue purging goes through hfsc_purge_queue(), which is used in three cases: grafting, class creation (when a leaf class is turned into an intermediate class by attaching a new class) and class deletion. In all cases qdisc_tree_decrease_len() is needed. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_hfsc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 1142d298ecf6..2d437447e085 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -957,11 +957,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl) unsigned int len = cl->qdisc->q.qlen; qdisc_reset(cl->qdisc); - if (len > 0) { - update_vf(cl, 0, 0); - set_passive(cl); - sch->q.qlen -= len; - } + qdisc_tree_decrease_qlen(cl->qdisc, len); } static void @@ -1295,6 +1291,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg) return NULL; } +static void +hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (cl->qdisc->q.qlen == 0) { + update_vf(cl, 0, 0); + set_passive(cl); + } +} + static unsigned long hfsc_get_class(struct Qdisc *sch, u32 classid) { @@ -1779,6 +1786,7 @@ static struct Qdisc_class_ops hfsc_class_ops = { .delete = hfsc_delete_class, .graft = hfsc_graft_class, .leaf = hfsc_class_leaf, + .qlen_notify = hfsc_qlen_notify, .get = hfsc_get_class, .put = hfsc_put_class, .bind_tcf = hfsc_bind_tcf, -- cgit v1.2.3-70-g09d2 From 256d61b87b2c2ac6fc333c1654d1abea61979006 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:37:05 -0800 Subject: [NET_SCHED]: Fix endless loops (part 4): HTB Convert HTB to use qdisc_tree_decrease_len() and add a callback for deactivating a class when its child queue becomes empty. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 3b36e9d60c20..215e68c2b615 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1230,11 +1230,7 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, return -ENOBUFS; sch_tree_lock(sch); if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { - if (cl->prio_activity) - htb_deactivate(qdisc_priv(sch), cl); - - /* TODO: is it correct ? Why CBQ doesn't do it ? */ - sch->q.qlen -= (*old)->q.qlen; + qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); qdisc_reset(*old); } sch_tree_unlock(sch); @@ -1249,6 +1245,14 @@ static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg) return (cl && !cl->level) ? cl->un.leaf.q : NULL; } +static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg) +{ + struct htb_class *cl = (struct htb_class *)arg; + + if (cl->un.leaf.q->q.qlen == 0) + htb_deactivate(qdisc_priv(sch), cl); +} + static unsigned long htb_get(struct Qdisc *sch, u32 classid) { struct htb_class *cl = htb_find(classid, sch); @@ -1323,6 +1327,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) { struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; + unsigned int qlen; // TODO: why don't allow to delete subtree ? references ? does // tc subsys quarantee us that in htb_destroy it holds no class @@ -1336,8 +1341,9 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) hlist_del_init(&cl->hlist); if (!cl->level) { - sch->q.qlen -= cl->un.leaf.q->q.qlen; + qlen = cl->un.leaf.q->q.qlen; qdisc_reset(cl->un.leaf.q); + qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen); } if (cl->prio_activity) @@ -1419,8 +1425,11 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); sch_tree_lock(sch); if (parent && !parent->level) { + unsigned int qlen = parent->un.leaf.q->q.qlen; + /* turn parent into inner node */ - sch->q.qlen -= parent->un.leaf.q->q.qlen; + qdisc_reset(parent->un.leaf.q); + qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen); qdisc_destroy(parent->un.leaf.q); if (parent->prio_activity) htb_deactivate(q, parent); @@ -1568,6 +1577,7 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) static struct Qdisc_class_ops htb_class_ops = { .graft = htb_graft, .leaf = htb_leaf, + .qlen_notify = htb_qlen_notify, .get = htb_get, .put = htb_put, .change = htb_change_class, -- cgit v1.2.3-70-g09d2 From e488eafcc50be296f0d1e1fd67c6b5d865183011 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:37:42 -0800 Subject: [NET_SCHED]: Fix endless loops (part 5): netem/tbf/hfsc ->requeue failures When peeking at the next packet in a child qdisc by calling dequeue/requeue, the upper qdisc qlen counter may get out of sync in case the requeue fails. The qdisc and the child qdisc both have their counter decremented, but since no packet is given to the upper qdisc it won't decrement its counter itself. requeue should not fail, so this is mostly for "correctness". Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_hfsc.c | 1 + net/sched/sch_netem.c | 5 +---- net/sched/sch_tbf.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 2d437447e085..6eefa6995777 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -946,6 +946,7 @@ qdisc_peek_len(struct Qdisc *sch) if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) { if (net_ratelimit()) printk("qdisc_peek_len: failed to requeue\n"); + qdisc_tree_decrease_qlen(sch, 1); return 0; } return len; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 672c35445793..79542af9dab1 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -287,13 +287,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now); if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { + qdisc_tree_decrease_qlen(q->qdisc, 1); sch->qstats.drops++; - - /* After this qlen is confused */ printk(KERN_ERR "netem: queue discpline %s could not requeue\n", q->qdisc->ops->id); - - sch->q.qlen--; } mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay)); diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 23b7624354f5..ed9b6d938540 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -250,7 +250,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { /* When requeue fails skb is dropped */ - sch->q.qlen--; + qdisc_tree_decrease_qlen(q->qdisc, 1); sch->qstats.drops++; } -- cgit v1.2.3-70-g09d2 From 08dd1a506bbc4528db60dfdfff61423a1608ed3f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Nov 2006 16:35:01 -0800 Subject: [TCP] MD5SIG: Kill CONFIG_TCP_MD5SIG_DEBUG. It just obfuscates the code and adds limited value. And as Adrian Bunk noticed, it lacked Kconfig help text too, so just kill it. Signed-off-by: David S. Miller --- net/ipv4/Kconfig | 4 ---- net/ipv4/tcp_ipv4.c | 41 +---------------------------------------- 2 files changed, 1 insertion(+), 44 deletions(-) (limited to 'net') diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 39e0cb763588..503e7059e312 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -630,9 +630,5 @@ config TCP_MD5SIG If unsure, say N. -config TCP_MD5SIG_DEBUG - bool "TCP: MD5 Signature Option debugging" - depends on TCP_MD5SIG - source "net/ipv4/ipvs/Kconfig" diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4913f25e5ad5..dd3509a59fe0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1017,9 +1017,6 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, struct scatterlist sg[4]; __u16 data_len; int block = 0; -#ifdef CONFIG_TCP_MD5SIG_DEBUG - int i; -#endif __sum16 old_checksum; struct tcp_md5sig_pool *hp; struct tcp4_pseudohdr *bp; @@ -1052,13 +1049,6 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, sg_set_buf(&sg[block++], bp, sizeof(*bp)); nbytes += sizeof(*bp); -#ifdef CONFIG_TCP_MD5SIG_DEBUG - printk("Calcuating hash for: "); - for (i = 0; i < sizeof(*bp); i++) - printk("%02x ", (unsigned int)((unsigned char *)bp)[i]); - printk(" "); -#endif - /* 2. the TCP header, excluding options, and assuming a * checksum of zero/ */ @@ -1066,10 +1056,7 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, th->check = 0; sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); nbytes += sizeof(struct tcphdr); -#ifdef CONFIG_TCP_MD5SIG_DEBUG - for (i = 0; i < sizeof(struct tcphdr); i++) - printk(" %02x", (unsigned int)((unsigned char *)th)[i]); -#endif + /* 3. the TCP segment data (if any) */ data_len = tcplen - (th->doff << 2); if (data_len > 0) { @@ -1084,12 +1071,6 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, sg_set_buf(&sg[block++], key->key, key->keylen); nbytes += key->keylen; -#ifdef CONFIG_TCP_MD5SIG_DEBUG - printk(" and password: "); - for (i = 0; i < key->keylen; i++) - printk("%02x ", (unsigned int)key->key[i]); -#endif - /* Now store the Hash into the packet */ err = crypto_hash_init(desc); if (err) @@ -1106,12 +1087,6 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, th->check = old_checksum; out: -#ifdef CONFIG_TCP_MD5SIG_DEBUG - printk(" result:"); - for (i = 0; i < 16; i++) - printk(" %02x", (unsigned int)(((u8*)md5_hash)[i])); - printk("\n"); -#endif return 0; clear_hash: tcp_put_md5sig_pool(); @@ -1241,20 +1216,6 @@ done_opts: NIPQUAD(iph->saddr), ntohs(th->source), NIPQUAD(iph->daddr), ntohs(th->dest), genhash ? " tcp_v4_calc_md5_hash failed" : ""); -#ifdef CONFIG_TCP_MD5SIG_DEBUG - do { - int i; - printk("Received: "); - for (i = 0; i < 16; i++) - printk("%02x ", - 0xff & (int)hash_location[i]); - printk("\n"); - printk("Calculated: "); - for (i = 0; i < 16; i++) - printk("%02x ", 0xff & (int)newhash[i]); - printk("\n"); - } while(0); -#endif } return 1; } -- cgit v1.2.3-70-g09d2 From 76b3f055f38954c67dab13844eb92203580038f8 Mon Sep 17 00:00:00 2001 From: Miika Komu Date: Thu, 30 Nov 2006 16:40:43 -0800 Subject: [IPSEC]: Add encapsulation family. Signed-off-by: Miika Komu Signed-off-by: Diego Beltrami Signed-off-by: Kazunori Miyazawa Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 ++ net/xfrm/xfrm_policy.c | 1 + 2 files changed, 3 insertions(+) (limited to 'net') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 984e5c45265c..15ec19dcf9c8 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -310,6 +310,8 @@ struct xfrm_tmpl /* Source address of tunnel. Ignored, if it is not a tunnel. */ xfrm_address_t saddr; + unsigned short encap_family; + __u32 reqid; /* Mode: transport, tunnel etc. */ diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index e5ea1347a4ff..64d3938f74c4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1211,6 +1211,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, if (tmpl->mode == XFRM_MODE_TUNNEL) { remote = &tmpl->id.daddr; local = &tmpl->saddr; + family = tmpl->encap_family; if (xfrm_addr_any(local, family)) { error = xfrm_get_saddr(&tmp, remote, family); if (error) -- cgit v1.2.3-70-g09d2 From 8511d01d7c70200ffd42debba9d7ac5c4f7f1031 Mon Sep 17 00:00:00 2001 From: Miika Komu Date: Thu, 30 Nov 2006 16:40:51 -0800 Subject: [IPSEC]: Add netlink interface for the encapsulation family. Signed-off-by: Miika Komu Signed-off-by: Diego Beltrami Signed-off-by: Kazunori Miyazawa Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6b461da0b51c..055b72fb37bc 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -858,6 +858,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, int i; xp->xfrm_nr = nr; + xp->family = ut->family; for (i = 0; i < nr; i++, ut++) { struct xfrm_tmpl *t = &xp->xfrm_vec[i]; @@ -871,6 +872,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, t->aalgos = ut->aalgos; t->ealgos = ut->ealgos; t->calgos = ut->calgos; + t->encap_family = ut->family; } } @@ -1024,7 +1026,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; memcpy(&up->id, &kp->id, sizeof(up->id)); - up->family = xp->family; + up->family = kp->encap_family; memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); up->reqid = kp->reqid; up->mode = kp->mode; -- cgit v1.2.3-70-g09d2 From 2718aa7c55ba7264dd463b8f7006f0975366fa7b Mon Sep 17 00:00:00 2001 From: Miika Komu Date: Thu, 30 Nov 2006 16:41:50 -0800 Subject: [IPSEC]: Add AF_KEY interface for encapsulation family. Signed-off-by: Miika Komu Signed-off-by: Diego Beltrami Signed-off-by: Kazunori Miyazawa --- net/key/af_key.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/key/af_key.c b/net/key/af_key.c index 4e1830999482..0e1dbfbb9b10 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1767,11 +1767,11 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) /* addresses present only in tunnel mode */ if (t->mode == XFRM_MODE_TUNNEL) { - switch (xp->family) { + struct sockaddr *sa; + sa = (struct sockaddr *)(rq+1); + switch(sa->sa_family) { case AF_INET: - sin = (void*)(rq+1); - if (sin->sin_family != AF_INET) - return -EINVAL; + sin = (struct sockaddr_in*)sa; t->saddr.a4 = sin->sin_addr.s_addr; sin++; if (sin->sin_family != AF_INET) @@ -1780,9 +1780,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: - sin6 = (void *)(rq+1); - if (sin6->sin6_family != AF_INET6) - return -EINVAL; + sin6 = (struct sockaddr_in6*)sa; memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); sin6++; if (sin6->sin6_family != AF_INET6) @@ -1793,7 +1791,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) default: return -EINVAL; } - } + t->encap_family = sa->sa_family; + } else + t->encap_family = xp->family; + /* No way to set this via kame pfkey */ t->aalgos = t->ealgos = t->calgos = ~0; xp->xfrm_nr++; @@ -1830,18 +1831,25 @@ static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp) static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) { + struct xfrm_tmpl *t; int sockaddr_size = pfkey_sockaddr_size(xp->family); - int socklen = (xp->family == AF_INET ? - sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6)); + int socklen = 0; + int i; + + for (i=0; ixfrm_nr; i++) { + t = xp->xfrm_vec + i; + socklen += (t->encap_family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)); + } return sizeof(struct sadb_msg) + (sizeof(struct sadb_lifetime) * 3) + (sizeof(struct sadb_address) * 2) + (sockaddr_size * 2) + sizeof(struct sadb_x_policy) + - (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) + - (socklen * 2))) + + (xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) + + (socklen * 2) + pfkey_xfrm_policy2sec_ctx_size(xp); } @@ -1999,7 +2007,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i req_size = sizeof(struct sadb_x_ipsecrequest); if (t->mode == XFRM_MODE_TUNNEL) - req_size += 2*socklen; + req_size += ((t->encap_family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)) * 2); else size -= 2*socklen; rq = (void*)skb_put(skb, req_size); @@ -2015,7 +2025,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; rq->sadb_x_ipsecrequest_reqid = t->reqid; if (t->mode == XFRM_MODE_TUNNEL) { - switch (xp->family) { + switch (t->encap_family) { case AF_INET: sin = (void*)(rq+1); sin->sin_family = AF_INET; -- cgit v1.2.3-70-g09d2 From f5b99bcdddfb2338227faad3489c24907f37ee8e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 30 Nov 2006 17:22:29 -0800 Subject: [NET]: Possible cleanups. This patch contains the following possible cleanups: - make the following needlessly global functions statis: - ipv4/tcp.c: __tcp_alloc_md5sig_pool() - ipv4/tcp_ipv4.c: tcp_v4_reqsk_md5_lookup() - ipv4/udplite.c: udplite_rcv() - ipv4/udplite.c: udplite_err() - make the following needlessly global structs static: - ipv4/tcp_ipv4.c: tcp_request_sock_ipv4_ops - ipv4/tcp_ipv4.c: tcp_sock_ipv4_specific - ipv6/tcp_ipv6.c: tcp_request_sock_ipv6_ops - net/ipv{4,6}/udplite.c: remove inline's from static functions (gcc should know best when to inline them) Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_ipv4.c | 8 ++++---- net/ipv4/udplite.c | 10 +++++----- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udplite.c | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a6b228914b8e..090c690627e5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2278,7 +2278,7 @@ void tcp_free_md5sig_pool(void) EXPORT_SYMBOL(tcp_free_md5sig_pool); -struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) +static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) { int cpu; struct tcp_md5sig_pool **pool; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dd3509a59fe0..7684297d80aa 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -840,8 +840,8 @@ struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, EXPORT_SYMBOL(tcp_v4_md5_lookup); -struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, - struct request_sock *req) +static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) { return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); } @@ -1233,7 +1233,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; -struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { +static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v4_reqsk_md5_lookup, #endif @@ -1820,7 +1820,7 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; -struct tcp_sock_af_ops tcp_sock_ipv4_specific = { +static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 561de6d8c734..b28fe1edf98b 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -18,23 +18,23 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly; struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; static int udplite_port_rover; -__inline__ int udplite_get_port(struct sock *sk, unsigned short p, - int (*c)(const struct sock *, const struct sock *)) +int udplite_get_port(struct sock *sk, unsigned short p, + int (*c)(const struct sock *, const struct sock *)) { return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); } -static __inline__ int udplite_v4_get_port(struct sock *sk, unsigned short snum) +static int udplite_v4_get_port(struct sock *sk, unsigned short snum) { return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); } -__inline__ int udplite_rcv(struct sk_buff *skb) +static int udplite_rcv(struct sk_buff *skb) { return __udp4_lib_rcv(skb, udplite_hash, 1); } -__inline__ void udplite_err(struct sk_buff *skb, u32 info) +static void udplite_err(struct sk_buff *skb, u32 info) { return __udp4_lib_err(skb, info, udplite_hash); } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 517c50024bfc..dd1a23b5a0f5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -929,7 +929,7 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; -struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v6_reqsk_md5_lookup, #endif diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index d4cafacc235b..629f97162fbc 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -17,14 +17,14 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; -static __inline__ int udplitev6_rcv(struct sk_buff **pskb) +static int udplitev6_rcv(struct sk_buff **pskb) { return __udp6_lib_rcv(pskb, udplite_hash, 1); } -static __inline__ void udplitev6_err(struct sk_buff *skb, - struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) +static void udplitev6_err(struct sk_buff *skb, + struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info) { return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); } @@ -35,7 +35,7 @@ static struct inet6_protocol udplitev6_protocol = { .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; -static __inline__ int udplite_v6_get_port(struct sock *sk, unsigned short snum) +static int udplite_v6_get_port(struct sock *sk, unsigned short snum) { return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); } -- cgit v1.2.3-70-g09d2 From b6332e6cf9c9198c0f3b0fe37c2c57514dafe1b8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 30 Nov 2006 19:16:28 -0800 Subject: [TCP]: Fix warnings with TCP_MD5SIG disabled. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 8 ++++---- net/ipv6/tcp_ipv6.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7684297d80aa..a1222d6968c4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1233,11 +1233,11 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; -static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { .md5_lookup = tcp_v4_reqsk_md5_lookup, -#endif }; +#endif static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp_timewait_sock), @@ -1820,14 +1820,14 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, .md5_add = tcp_v4_md5_add_func, .md5_parse = tcp_v4_parse_md5_keys, -#endif }; +#endif /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index dd1a23b5a0f5..c25e930c2c69 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -929,11 +929,11 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; -static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { .md5_lookup = tcp_v6_reqsk_md5_lookup, -#endif }; +#endif static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp6_timewait_sock), -- cgit v1.2.3-70-g09d2 From bb2ef25c2c62444b8fdb0346a23658a419803df9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:22:42 -0800 Subject: [EBTABLES]: Fix wraparounds in ebt_entries verification. We need to verify that a) we are not too close to the end of buffer to dereference b) next entry we'll be checking won't be _before_ our While we are at it, don't subtract unrelated pointers... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 9f85666f29f7..0dcebf20d6ce 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -401,13 +401,17 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) { + unsigned int offset = (char *)e - newinfo->entries; + size_t left = (limit - base) - offset; int i; + if (left < sizeof(unsigned int)) + goto Esmall; + for (i = 0; i < NF_BR_NUMHOOKS; i++) { if ((valid_hooks & (1 << i)) == 0) continue; - if ( (char *)hook_entries[i] - base == - (char *)e - newinfo->entries) + if ((char *)hook_entries[i] == base + offset) break; } /* beginning of a new chain @@ -428,11 +432,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, return -EINVAL; } /* before we look at the struct, be sure it is not too big */ - if ((char *)hook_entries[i] + sizeof(struct ebt_entries) - > limit) { - BUGPRINT("entries_size too small\n"); - return -EINVAL; - } + if (left < sizeof(struct ebt_entries)) + goto Esmall; if (((struct ebt_entries *)e)->policy != EBT_DROP && ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { /* only RETURN from udc */ @@ -455,6 +456,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, return 0; } /* a plain old entry, heh */ + if (left < sizeof(struct ebt_entry)) + goto Esmall; if (sizeof(struct ebt_entry) > e->watchers_offset || e->watchers_offset > e->target_offset || e->target_offset >= e->next_offset) { @@ -466,10 +469,16 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, BUGPRINT("target size too small\n"); return -EINVAL; } + if (left < e->next_offset) + goto Esmall; (*cnt)++; (*totalcnt)++; return 0; + +Esmall: + BUGPRINT("entries_size too small\n"); + return -EINVAL; } struct ebt_cl_stack -- cgit v1.2.3-70-g09d2 From 40642f95f5f818579bc4cc3ee084b033e662d5b3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:24:12 -0800 Subject: [EBTABLES]: Verify that ebt_entries have zero ->distinguisher. We need that for iterator to work; existing check had been too weak. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 0dcebf20d6ce..6ab7674ea454 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -417,7 +417,7 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, /* beginning of a new chain if i == NF_BR_NUMHOOKS it must be a user defined chain */ if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { - if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) { + if (e->bitmask != 0) { /* we make userspace set this right, so there is no misunderstanding */ BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " @@ -500,7 +500,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, int i; /* we're only interested in chain starts */ - if (e->bitmask & EBT_ENTRY_OR_ENTRIES) + if (e->bitmask) return 0; for (i = 0; i < NF_BR_NUMHOOKS; i++) { if ((valid_hooks & (1 << i)) == 0) @@ -550,7 +550,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) { struct ebt_entry_target *t; - if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) + if (e->bitmask == 0) return 0; /* we're done */ if (cnt && (*cnt)-- == 0) @@ -576,7 +576,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, int ret; /* don't mess with the struct ebt_entries */ - if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) + if (e->bitmask == 0) return 0; if (e->bitmask & ~EBT_F_MASK) { @@ -1309,7 +1309,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) char *hlp; struct ebt_entry_target *t; - if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) + if (e->bitmask == 0) return 0; hlp = ubase - base + (char *)e + e->target_offset; -- cgit v1.2.3-70-g09d2 From 98a0824a0f33d051f31ca8ff59e289755b244ede Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:24:49 -0800 Subject: [EBTABLES]: Deal with the worst-case behaviour in loop checks. No need to revisit a chain we'd already finished with during the check for current hook. It's either instant loop (which we'd just detected) or a duplicate work. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 6ab7674ea454..46ab9b759269 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -717,7 +717,9 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s BUGPRINT("loop\n"); return -1; } - /* this can't be 0, so the above test is correct */ + if (cl_s[i].hookmask & (1 << hooknr)) + goto letscontinue; + /* this can't be 0, so the loop test is correct */ cl_s[i].cs.n = pos + 1; pos = 0; cl_s[i].cs.e = ((void *)e + e->next_offset); -- cgit v1.2.3-70-g09d2 From 14197d5447afc41fce6b11a91592278cad1a09eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:25:21 -0800 Subject: [EBTABLES]: Prevent wraparounds in checks for entry components' sizes. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 46ab9b759269..136ed7d4bd73 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, const char *name, unsigned int hookmask, unsigned int *cnt) { struct ebt_match *match; + size_t left = ((char *)e + e->watchers_offset) - (char *)m; int ret; - if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) > - ((char *)e) + e->watchers_offset) + if (left < sizeof(struct ebt_entry_match) || + left - sizeof(struct ebt_entry_match) < m->match_size) return -EINVAL; match = find_match_lock(m->u.name, &ret, &ebt_mutex); if (!match) @@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, const char *name, unsigned int hookmask, unsigned int *cnt) { struct ebt_watcher *watcher; + size_t left = ((char *)e + e->target_offset) - (char *)w; int ret; - if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) > - ((char *)e) + e->target_offset) + if (left < sizeof(struct ebt_entry_watcher) || + left - sizeof(struct ebt_entry_watcher) < w->watcher_size) return -EINVAL; watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex); if (!watcher) @@ -573,6 +575,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, struct ebt_entry_target *t; struct ebt_target *target; unsigned int i, j, hook = 0, hookmask = 0; + size_t gap = e->next_offset - e->target_offset; int ret; /* don't mess with the struct ebt_entries */ @@ -634,8 +637,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, t->u.target = target; if (t->u.target == &ebt_standard_target) { - if (e->target_offset + sizeof(struct ebt_standard_target) > - e->next_offset) { + if (gap < sizeof(struct ebt_standard_target)) { BUGPRINT("Standard target size too big\n"); ret = -EFAULT; goto cleanup_watchers; @@ -646,8 +648,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ret = -EFAULT; goto cleanup_watchers; } - } else if ((e->target_offset + t->target_size + - sizeof(struct ebt_entry_target) > e->next_offset) || + } else if (t->target_size > gap - sizeof(struct ebt_entry_target) || (t->u.target->check && t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ module_put(t->u.target->me); -- cgit v1.2.3-70-g09d2 From 22b440bf9e717226d0fbaf4f29357cbdd5279de5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:25:51 -0800 Subject: [EBTABLES]: Split ebt_check_entry_size_and_hooks Split ebt_check_entry_size_and_hooks() in two parts - one that does sanity checks on pointers (basically, checks that we can safely use iterator from now on) and the rest of it (looking into details of entry). The loop applying ebt_check_entry_size_and_hooks() is split in two. Populating newinfo->hook_entry[] is done in the first part. Unused arguments killed. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 73 +++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 136ed7d4bd73..e79c0fbd9e89 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -393,15 +393,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, return 0; } -/* - * this one is very careful, as it is the first function - * to parse the userspace data - */ static inline int -ebt_check_entry_size_and_hooks(struct ebt_entry *e, +__ebt_verify_pointers(struct ebt_entry *e, struct ebt_table_info *newinfo, char *base, char *limit, - struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, - unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) + struct ebt_entries **hook_entries, + unsigned int valid_hooks) { unsigned int offset = (char *)e - newinfo->entries; size_t left = (limit - base) - offset; @@ -416,8 +412,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, if ((char *)hook_entries[i] == base + offset) break; } - /* beginning of a new chain - if i == NF_BR_NUMHOOKS it must be a user defined chain */ if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { if (e->bitmask != 0) { /* we make userspace set this right, @@ -426,6 +420,45 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, "in distinguisher\n"); return -EINVAL; } + if (left < sizeof(struct ebt_entries)) + goto Esmall; + if (i != NF_BR_NUMHOOKS) + newinfo->hook_entry[i] = (struct ebt_entries *)e; + return 0; + } + if (left < sizeof(struct ebt_entry)) + goto Esmall; + if (left < e->next_offset) + goto Esmall; + return 0; + +Esmall: + BUGPRINT("entries_size too small\n"); + return -EINVAL; +} + +/* + * this one is very careful, as it is the first function + * to parse the userspace data + */ +static inline int +ebt_check_entry_size_and_hooks(struct ebt_entry *e, + struct ebt_table_info *newinfo, char *base, + struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, + unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) +{ + unsigned int offset = (char *)e - newinfo->entries; + int i; + + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + if ((valid_hooks & (1 << i)) == 0) + continue; + if ((char *)hook_entries[i] == base + offset) + break; + } + /* beginning of a new chain + if i == NF_BR_NUMHOOKS it must be a user defined chain */ + if (i != NF_BR_NUMHOOKS || !e->bitmask) { /* this checks if the previous chain has as many entries as it said it has */ if (*n != *cnt) { @@ -433,9 +466,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, "in the chain\n"); return -EINVAL; } - /* before we look at the struct, be sure it is not too big */ - if (left < sizeof(struct ebt_entries)) - goto Esmall; if (((struct ebt_entries *)e)->policy != EBT_DROP && ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { /* only RETURN from udc */ @@ -447,8 +477,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, } if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */ (*udc_cnt)++; - else - newinfo->hook_entry[i] = (struct ebt_entries *)e; if (((struct ebt_entries *)e)->counter_offset != *totalcnt) { BUGPRINT("counter_offset != totalcnt"); return -EINVAL; @@ -458,8 +486,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, return 0; } /* a plain old entry, heh */ - if (left < sizeof(struct ebt_entry)) - goto Esmall; if (sizeof(struct ebt_entry) > e->watchers_offset || e->watchers_offset > e->target_offset || e->target_offset >= e->next_offset) { @@ -471,16 +497,9 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, BUGPRINT("target size too small\n"); return -EINVAL; } - if (left < e->next_offset) - goto Esmall; - (*cnt)++; (*totalcnt)++; return 0; - -Esmall: - BUGPRINT("entries_size too small\n"); - return -EINVAL; } struct ebt_cl_stack @@ -776,6 +795,12 @@ static int translate_table(struct ebt_replace *repl, newinfo->entries_size = repl->entries_size; newinfo->nentries = repl->nentries; + ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, + __ebt_verify_pointers, newinfo, repl->entries, + repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks); + if (ret != 0) + return ret; + /* do some early checkings and initialize some things */ i = 0; /* holds the expected nr. of entries for the chain */ j = 0; /* holds the up to now counted entries for the chain */ @@ -784,7 +809,7 @@ static int translate_table(struct ebt_replace *repl, udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ebt_check_entry_size_and_hooks, newinfo, repl->entries, - repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k, + repl->hook_entry, &i, &j, &k, &udc_cnt, repl->valid_hooks); if (ret != 0) -- cgit v1.2.3-70-g09d2 From 70fe9af47ee01a17fe7486f1739f6eac8a14868b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:26:14 -0800 Subject: [EBTABLES]: Pull the loop doing __ebt_verify_pointers() into a separate function. It's easier to expand the iterator here *and* we'll be able to move all uses of ebt_replace from translate_table() into this one. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 78 ++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 37 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index e79c0fbd9e89..2eba40f54233 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -393,48 +393,54 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, return 0; } -static inline int -__ebt_verify_pointers(struct ebt_entry *e, - struct ebt_table_info *newinfo, char *base, char *limit, - struct ebt_entries **hook_entries, - unsigned int valid_hooks) +static int ebt_verify_pointers(struct ebt_replace *repl, + struct ebt_table_info *newinfo) { - unsigned int offset = (char *)e - newinfo->entries; - size_t left = (limit - base) - offset; + unsigned int limit = repl->entries_size; + unsigned int valid_hooks = repl->valid_hooks; + unsigned int offset = 0; int i; - if (left < sizeof(unsigned int)) - goto Esmall; + while (offset < limit) { + size_t left = limit - offset; + struct ebt_entry *e = (void *)newinfo->entries + offset; - for (i = 0; i < NF_BR_NUMHOOKS; i++) { - if ((valid_hooks & (1 << i)) == 0) - continue; - if ((char *)hook_entries[i] == base + offset) + if (left < sizeof(unsigned int)) break; - } - if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { - if (e->bitmask != 0) { - /* we make userspace set this right, - so there is no misunderstanding */ - BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " - "in distinguisher\n"); - return -EINVAL; + + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + if ((valid_hooks & (1 << i)) == 0) + continue; + if ((char *)repl->hook_entry[i] == repl->entries + offset) + break; } - if (left < sizeof(struct ebt_entries)) - goto Esmall; - if (i != NF_BR_NUMHOOKS) - newinfo->hook_entry[i] = (struct ebt_entries *)e; - return 0; + + if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { + if (e->bitmask != 0) { + /* we make userspace set this right, + so there is no misunderstanding */ + BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " + "in distinguisher\n"); + return -EINVAL; + } + if (i != NF_BR_NUMHOOKS) + newinfo->hook_entry[i] = (struct ebt_entries *)e; + if (left < sizeof(struct ebt_entries)) + break; + offset += sizeof(struct ebt_entries); + } else { + if (left < sizeof(struct ebt_entry)) + break; + if (left < e->next_offset) + break; + offset += e->next_offset; + } + } + if (offset != limit) { + BUGPRINT("entries_size too small\n"); + return -EINVAL; } - if (left < sizeof(struct ebt_entry)) - goto Esmall; - if (left < e->next_offset) - goto Esmall; return 0; - -Esmall: - BUGPRINT("entries_size too small\n"); - return -EINVAL; } /* @@ -795,9 +801,7 @@ static int translate_table(struct ebt_replace *repl, newinfo->entries_size = repl->entries_size; newinfo->nentries = repl->nentries; - ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - __ebt_verify_pointers, newinfo, repl->entries, - repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks); + ret = ebt_verify_pointers(repl, newinfo); if (ret != 0) return ret; -- cgit v1.2.3-70-g09d2 From e4fd77deac764e17cb1eab8661bcf1413204d04d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:26:35 -0800 Subject: [EBTABLES]: Move more stuff into ebt_verify_pointers(). Take intialization of ->hook_entry[...], ->entries_size and ->nentries over there, pull the check for empty chains into the end of that sucker. Now it's self-contained, so we can move it up in the very beginning of translate_table() *and* we can rely on ->hook_entry[] being properly transliterated after it. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 2eba40f54233..7ce190c21dd7 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -401,6 +401,12 @@ static int ebt_verify_pointers(struct ebt_replace *repl, unsigned int offset = 0; int i; + for (i = 0; i < NF_BR_NUMHOOKS; i++) + newinfo->hook_entry[i] = NULL; + + newinfo->entries_size = repl->entries_size; + newinfo->nentries = repl->nentries; + while (offset < limit) { size_t left = limit - offset; struct ebt_entry *e = (void *)newinfo->entries + offset; @@ -440,6 +446,15 @@ static int ebt_verify_pointers(struct ebt_replace *repl, BUGPRINT("entries_size too small\n"); return -EINVAL; } + + /* check if all valid hooks have a chain */ + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + if (!newinfo->hook_entry[i] && + (valid_hooks & (1 << i))) { + BUGPRINT("Valid hook without chain\n"); + return -EINVAL; + } + } return 0; } @@ -772,6 +787,10 @@ static int translate_table(struct ebt_replace *repl, int ret; struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */ + ret = ebt_verify_pointers(repl, newinfo); + if (ret != 0) + return ret; + i = 0; while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i))) i++; @@ -795,16 +814,6 @@ static int translate_table(struct ebt_replace *repl, i = j; } - for (i = 0; i < NF_BR_NUMHOOKS; i++) - newinfo->hook_entry[i] = NULL; - - newinfo->entries_size = repl->entries_size; - newinfo->nentries = repl->nentries; - - ret = ebt_verify_pointers(repl, newinfo); - if (ret != 0) - return ret; - /* do some early checkings and initialize some things */ i = 0; /* holds the expected nr. of entries for the chain */ j = 0; /* holds the up to now counted entries for the chain */ @@ -829,15 +838,6 @@ static int translate_table(struct ebt_replace *repl, return -EINVAL; } - /* check if all valid hooks have a chain */ - for (i = 0; i < NF_BR_NUMHOOKS; i++) { - if (newinfo->hook_entry[i] == NULL && - (repl->valid_hooks & (1 << i))) { - BUGPRINT("Valid hook without chain\n"); - return -EINVAL; - } - } - /* get the location of the udc, put them in an array while we're at it, allocate the chainstack */ if (udc_cnt) { -- cgit v1.2.3-70-g09d2 From 1f072c96fdf1a0caa11c6e8078dd96925bd02db5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:26:53 -0800 Subject: [EBTABLES]: translate_table(): switch direct uses of repl->hook_info to newinfo Since newinfo->hook_table[] already has been set up, we can switch to using it instead of repl->{hook_info,valid_hooks}. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 7ce190c21dd7..3e1bf716509a 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -792,22 +792,22 @@ static int translate_table(struct ebt_replace *repl, return ret; i = 0; - while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i))) + while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i]) i++; if (i == NF_BR_NUMHOOKS) { BUGPRINT("No valid hooks specified\n"); return -EINVAL; } - if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) { + if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) { BUGPRINT("Chains don't start at beginning\n"); return -EINVAL; } /* make sure chains are ordered after each other in same order as their corresponding hooks */ for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { - if (!(repl->valid_hooks & (1 << j))) + if (!newinfo->hook_entry[j]) continue; - if ( repl->hook_entry[j] <= repl->hook_entry[i] ) { + if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) { BUGPRINT("Hook order must be followed\n"); return -EINVAL; } @@ -877,7 +877,7 @@ static int translate_table(struct ebt_replace *repl, /* Check for loops */ for (i = 0; i < NF_BR_NUMHOOKS; i++) - if (repl->valid_hooks & (1 << i)) + if (newinfo->hook_entry[i]) if (check_chainloops(newinfo->hook_entry[i], cl_s, udc_cnt, i, newinfo->entries)) { vfree(cl_s); -- cgit v1.2.3-70-g09d2 From 0e795531c5e6d0a7d407b8d9edde47cab13be3ec Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:27:13 -0800 Subject: [EBTABLES]: Switch ebt_check_entry_size_and_hooks() to use of newinfo->hook_entry[] kill unused arguments Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 3e1bf716509a..ec7709b5c568 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -464,17 +464,14 @@ static int ebt_verify_pointers(struct ebt_replace *repl, */ static inline int ebt_check_entry_size_and_hooks(struct ebt_entry *e, - struct ebt_table_info *newinfo, char *base, - struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, - unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) + struct ebt_table_info *newinfo, + unsigned int *n, unsigned int *cnt, + unsigned int *totalcnt, unsigned int *udc_cnt) { - unsigned int offset = (char *)e - newinfo->entries; int i; for (i = 0; i < NF_BR_NUMHOOKS; i++) { - if ((valid_hooks & (1 << i)) == 0) - continue; - if ((char *)hook_entries[i] == base + offset) + if ((void *)e == (void *)newinfo->hook_entry[i]) break; } /* beginning of a new chain @@ -821,9 +818,8 @@ static int translate_table(struct ebt_replace *repl, newinfo->nentries afterwards */ udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_check_entry_size_and_hooks, newinfo, repl->entries, - repl->hook_entry, &i, &j, &k, - &udc_cnt, repl->valid_hooks); + ebt_check_entry_size_and_hooks, newinfo, + &i, &j, &k, &udc_cnt); if (ret != 0) return ret; -- cgit v1.2.3-70-g09d2 From 177abc348a00738dbc985df8523d755bf87403d9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:27:32 -0800 Subject: [EBTABLES]: Clean ebt_get_udc_positions() up. Check for valid_hooks is redundant (newinfo->hook_entry[i] will be NULL if bit i is not set). Kill it, kill unused arguments. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index ec7709b5c568..4d1cf1492ca4 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -533,8 +533,7 @@ struct ebt_cl_stack */ static inline int ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, - struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks, - struct ebt_cl_stack *udc) + unsigned int *n, struct ebt_cl_stack *udc) { int i; @@ -542,8 +541,6 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, if (e->bitmask) return 0; for (i = 0; i < NF_BR_NUMHOOKS; i++) { - if ((valid_hooks & (1 << i)) == 0) - continue; if (newinfo->hook_entry[i] == (struct ebt_entries *)e) break; } @@ -861,8 +858,7 @@ static int translate_table(struct ebt_replace *repl, return -ENOMEM; i = 0; /* the i'th udc */ EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_get_udc_positions, newinfo, repl->hook_entry, &i, - repl->valid_hooks, cl_s); + ebt_get_udc_positions, newinfo, &i, cl_s); /* sanity check */ if (i != udc_cnt) { BUGPRINT("i != udc_cnt\n"); -- cgit v1.2.3-70-g09d2 From f7da79d99863c044e28483e32c10b394bbd78d21 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:27:48 -0800 Subject: [EBTABLES]: ebt_check_entry() doesn't need valid_hooks We can check newinfo->hook_entry[...] instead. Kill unused argument. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 4d1cf1492ca4..c4f10b8865a7 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -603,7 +603,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) static inline int ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, - const char *name, unsigned int *cnt, unsigned int valid_hooks, + const char *name, unsigned int *cnt, struct ebt_cl_stack *cl_s, unsigned int udc_cnt) { struct ebt_entry_target *t; @@ -630,7 +630,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, } /* what hook do we belong to? */ for (i = 0; i < NF_BR_NUMHOOKS; i++) { - if ((valid_hooks & (1 << i)) == 0) + if (!newinfo->hook_entry[i]) continue; if ((char *)newinfo->hook_entry[i] < (char *)e) hook = i; @@ -889,8 +889,7 @@ static int translate_table(struct ebt_replace *repl, /* used to know what we need to clean up if something goes wrong */ i = 0; ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks, - cl_s, udc_cnt); + ebt_check_entry, newinfo, repl->name, &i, cl_s, udc_cnt); if (ret != 0) { EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ebt_cleanup_entry, &i); -- cgit v1.2.3-70-g09d2 From 1bc2326cbe24766d9cb236e63c091cbaecfa2f29 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:28:08 -0800 Subject: [EBTABLES]: Move calls of ebt_verify_pointers() upstream. ... and pass just repl->name to translate_table() Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index c4f10b8865a7..f0d9ffd4c916 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -774,17 +774,12 @@ letscontinue: } /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ -static int translate_table(struct ebt_replace *repl, - struct ebt_table_info *newinfo) +static int translate_table(char *name, struct ebt_table_info *newinfo) { unsigned int i, j, k, udc_cnt; int ret; struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */ - ret = ebt_verify_pointers(repl, newinfo); - if (ret != 0) - return ret; - i = 0; while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i]) i++; @@ -889,7 +884,7 @@ static int translate_table(struct ebt_replace *repl, /* used to know what we need to clean up if something goes wrong */ i = 0; ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_check_entry, newinfo, repl->name, &i, cl_s, udc_cnt); + ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt); if (ret != 0) { EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ebt_cleanup_entry, &i); @@ -986,7 +981,11 @@ static int do_replace(void __user *user, unsigned int len) /* this can get initialized by translate_table() */ newinfo->chainstack = NULL; - ret = translate_table(&tmp, newinfo); + ret = ebt_verify_pointers(&tmp, newinfo); + if (ret != 0) + goto free_counterstmp; + + ret = translate_table(tmp.name, newinfo); if (ret != 0) goto free_counterstmp; @@ -1185,7 +1184,10 @@ int ebt_register_table(struct ebt_table *table) /* fill in newinfo and parse the entries */ newinfo->chainstack = NULL; - ret = translate_table(table->table, newinfo); + ret = ebt_verify_pointers(table->table, newinfo); + if (ret != 0) + goto free_chainstack; + ret = translate_table(table->table->name, newinfo); if (ret != 0) { BUGPRINT("Translate_table failed\n"); goto free_chainstack; -- cgit v1.2.3-70-g09d2 From df07a81e939a0176b125bc83cf22dbb5e380ae9f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:28:25 -0800 Subject: [EBTABLES]: Clean ebt_register_table() up. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index f0d9ffd4c916..00a89705c1c4 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1156,38 +1156,47 @@ int ebt_register_table(struct ebt_table *table) { struct ebt_table_info *newinfo; struct ebt_table *t; + struct ebt_replace *repl; int ret, i, countersize; + void *p; - if (!table || !table->table ||!table->table->entries || - table->table->entries_size == 0 || - table->table->counters || table->private) { + if (!table || !(repl = table->table) || !repl->entries || + repl->entries_size == 0 || + repl->counters || table->private) { BUGPRINT("Bad table data for ebt_register_table!!!\n"); return -EINVAL; } - countersize = COUNTER_OFFSET(table->table->nentries) * + countersize = COUNTER_OFFSET(repl->nentries) * (highest_possible_processor_id()+1); newinfo = vmalloc(sizeof(*newinfo) + countersize); ret = -ENOMEM; if (!newinfo) return -ENOMEM; - newinfo->entries = vmalloc(table->table->entries_size); - if (!(newinfo->entries)) + p = vmalloc(repl->entries_size); + if (!p) goto free_newinfo; - memcpy(newinfo->entries, table->table->entries, - table->table->entries_size); + memcpy(p, repl->entries, repl->entries_size); + newinfo->entries = p; + + newinfo->entries_size = repl->entries_size; + newinfo->nentries = repl->nentries; if (countersize) memset(newinfo->counters, 0, countersize); /* fill in newinfo and parse the entries */ newinfo->chainstack = NULL; - ret = ebt_verify_pointers(table->table, newinfo); - if (ret != 0) - goto free_chainstack; - ret = translate_table(table->table->name, newinfo); + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + if ((repl->valid_hooks & (1 << i)) == 0) + newinfo->hook_entry[i] = NULL; + else + newinfo->hook_entry[i] = p + + ((char *)repl->hook_entry[i] - repl->entries); + } + ret = translate_table(repl->name, newinfo); if (ret != 0) { BUGPRINT("Translate_table failed\n"); goto free_chainstack; -- cgit v1.2.3-70-g09d2 From 1e419cd9953f59d06d7b88d0e2911a68a0044f33 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 30 Nov 2006 19:28:48 -0800 Subject: [EBTABLES]: Split ebt_replace into user and kernel variants, annotate. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter_bridge/ebtables.h | 19 ++++++++++++++++++- net/bridge/netfilter/ebtable_broute.c | 2 +- net/bridge/netfilter/ebtable_filter.c | 2 +- net/bridge/netfilter/ebtable_nat.c | 2 +- net/bridge/netfilter/ebtables.c | 19 ++++++++++--------- 5 files changed, 31 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 87775264ff0b..94e0a7dc0cb2 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -38,6 +38,23 @@ struct ebt_counter }; struct ebt_replace +{ + char name[EBT_TABLE_MAXNAMELEN]; + unsigned int valid_hooks; + /* nr of rules in the table */ + unsigned int nentries; + /* total size of the entries */ + unsigned int entries_size; + /* start of the chains */ + struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS]; + /* nr of counters userspace expects back */ + unsigned int num_counters; + /* where the kernel will put the old counters */ + struct ebt_counter __user *counters; + char __user *entries; +}; + +struct ebt_replace_kernel { char name[EBT_TABLE_MAXNAMELEN]; unsigned int valid_hooks; @@ -255,7 +272,7 @@ struct ebt_table { struct list_head list; char name[EBT_TABLE_MAXNAMELEN]; - struct ebt_replace *table; + struct ebt_replace_kernel *table; unsigned int valid_hooks; rwlock_t lock; /* e.g. could be the table explicitly only allows certain diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 9a6e548e148b..d37ce0478938 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -23,7 +23,7 @@ static struct ebt_entries initial_chain = { .policy = EBT_ACCEPT, }; -static struct ebt_replace initial_table = +static struct ebt_replace_kernel initial_table = { .name = "broute", .valid_hooks = 1 << NF_BR_BROUTING, diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 3d5bd44f2395..127135ead2d5 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] = }, }; -static struct ebt_replace initial_table = +static struct ebt_replace_kernel initial_table = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 04dd42efda1d..9c50488b62eb 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] = } }; -static struct ebt_replace initial_table = +static struct ebt_replace_kernel initial_table = { .name = "nat", .valid_hooks = NAT_VALID_HOOKS, diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 00a89705c1c4..bee558a41800 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -417,7 +417,8 @@ static int ebt_verify_pointers(struct ebt_replace *repl, for (i = 0; i < NF_BR_NUMHOOKS; i++) { if ((valid_hooks & (1 << i)) == 0) continue; - if ((char *)repl->hook_entry[i] == repl->entries + offset) + if ((char __user *)repl->hook_entry[i] == + repl->entries + offset) break; } @@ -1156,7 +1157,7 @@ int ebt_register_table(struct ebt_table *table) { struct ebt_table_info *newinfo; struct ebt_table *t; - struct ebt_replace *repl; + struct ebt_replace_kernel *repl; int ret, i, countersize; void *p; @@ -1320,33 +1321,33 @@ free_tmp: } static inline int ebt_make_matchname(struct ebt_entry_match *m, - char *base, char *ubase) + char *base, char __user *ubase) { - char *hlp = ubase - base + (char *)m; + char __user *hlp = ubase + ((char *)m - base); if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) return -EFAULT; return 0; } static inline int ebt_make_watchername(struct ebt_entry_watcher *w, - char *base, char *ubase) + char *base, char __user *ubase) { - char *hlp = ubase - base + (char *)w; + char __user *hlp = ubase + ((char *)w - base); if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) return -EFAULT; return 0; } -static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) +static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase) { int ret; - char *hlp; + char __user *hlp; struct ebt_entry_target *t; if (e->bitmask == 0) return 0; - hlp = ubase - base + (char *)e + e->target_offset; + hlp = ubase + (((char *)e + e->target_offset) - base); t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase); -- cgit v1.2.3-70-g09d2 From 5f68e4c07c7b97a5b06f0b5e313528d36415a60d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 30 Nov 2006 19:50:36 -0800 Subject: [PKT_SCHED]: Remove unused exports. This patch removes the following unused EXPORT_SYMBOL's: - sch_api.c: qdisc_lookup - sch_generic.c: __netdev_watchdog_up - sch_generic.c: noop_qdisc_ops - sch_generic.c: qdisc_alloc Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/sched/sch_api.c | 1 - net/sched/sch_generic.c | 3 --- 2 files changed, 4 deletions(-) (limited to 'net') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 05a93da6f057..65825f4409d9 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1303,7 +1303,6 @@ static int __init pktsched_init(void) subsys_initcall(pktsched_init); -EXPORT_SYMBOL(qdisc_lookup); EXPORT_SYMBOL(qdisc_get_rtab); EXPORT_SYMBOL(qdisc_put_rtab); EXPORT_SYMBOL(register_qdisc); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index deafeb9cb70e..bc116bd6937c 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -609,13 +609,10 @@ void dev_shutdown(struct net_device *dev) qdisc_unlock_tree(dev); } -EXPORT_SYMBOL(__netdev_watchdog_up); EXPORT_SYMBOL(netif_carrier_on); EXPORT_SYMBOL(netif_carrier_off); EXPORT_SYMBOL(noop_qdisc); -EXPORT_SYMBOL(noop_qdisc_ops); EXPORT_SYMBOL(qdisc_create_dflt); -EXPORT_SYMBOL(qdisc_alloc); EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_reset); EXPORT_SYMBOL(qdisc_lock_tree); -- cgit v1.2.3-70-g09d2 From 1e9b3d5339d2afd6348e8211f0db695b00261e17 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 30 Nov 2006 19:54:05 -0800 Subject: [NET_SCHED]: policer: restore compatibility with old iproute binaries The tc actions increased the size of struct tc_police, which broke compatibility with old iproute binaries since both the act_police and the old NET_CLS_POLICE code check for an exact size match. Since the new members are not even used, the simple fix is to also accept the size of the old structure. Dumping is not affected since old userspace will receive a bigger structure, which is handled fine. Signed-off-by: Patrick McHardy Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/act_police.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sched/act_police.c b/net/sched/act_police.c index fed47b658837..af68e1e83251 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -46,6 +46,18 @@ static struct tcf_hashinfo police_hash_info = { .lock = &police_lock, }; +/* old policer structure from before tc actions */ +struct tc_police_compat +{ + u32 index; + int action; + u32 limit; + u32 burst; + u32 mtu; + struct tc_ratespec rate; + struct tc_ratespec peakrate; +}; + /* Each policer is serialized by its individual spinlock */ #ifdef CONFIG_NET_CLS_ACT @@ -131,12 +143,15 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, struct tc_police *parm; struct tcf_police *police; struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; + int size; if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) return -EINVAL; - if (tb[TCA_POLICE_TBF-1] == NULL || - RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) + if (tb[TCA_POLICE_TBF-1] == NULL) + return -EINVAL; + size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]); + if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) return -EINVAL; parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); @@ -415,12 +430,15 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) 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 || - RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) + 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]); -- cgit v1.2.3-70-g09d2 From c40a27f48ceee648e9cfdda040b69e7010d9f82c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Nov 2006 21:05:23 -0800 Subject: [ATM]: Kill ipcommon.[ch] All that remained was skb_migrate() and that was overkill for what the two call sites were trying to do. Signed-off-by: David S. Miller --- net/atm/Makefile | 3 --- net/atm/br2684.c | 28 +++++++++++++++++++----- net/atm/clip.c | 29 ++++++++++++++++++++----- net/atm/ipcommon.c | 63 ------------------------------------------------------ net/atm/ipcommon.h | 22 ------------------- 5 files changed, 47 insertions(+), 98 deletions(-) delete mode 100644 net/atm/ipcommon.c delete mode 100644 net/atm/ipcommon.h (limited to 'net') diff --git a/net/atm/Makefile b/net/atm/Makefile index 89656d6c0b90..cc50bd1ff1de 100644 --- a/net/atm/Makefile +++ b/net/atm/Makefile @@ -7,10 +7,7 @@ mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o obj-$(CONFIG_ATM) += atm.o obj-$(CONFIG_ATM_CLIP) += clip.o -atm-$(subst m,y,$(CONFIG_ATM_CLIP)) += ipcommon.o obj-$(CONFIG_ATM_BR2684) += br2684.o -atm-$(subst m,y,$(CONFIG_ATM_BR2684)) += ipcommon.o -atm-$(subst m,y,$(CONFIG_NET_SCH_ATM)) += ipcommon.o atm-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_ATM_LANE) += lec.o diff --git a/net/atm/br2684.c b/net/atm/br2684.c index b04162f10d85..83a1c1b1d6cd 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -23,7 +23,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include #include "common.h" -#include "ipcommon.h" /* * Define this to use a version of the code which interacts with the higher @@ -500,11 +499,12 @@ Note: we do not have explicit unassign, but look at _push() */ int err; struct br2684_vcc *brvcc; - struct sk_buff_head copy; struct sk_buff *skb; + struct sk_buff_head *rq; struct br2684_dev *brdev; struct net_device *net_dev; struct atm_backend_br2684 be; + unsigned long flags; if (copy_from_user(&be, arg, sizeof be)) return -EFAULT; @@ -554,12 +554,30 @@ Note: we do not have explicit unassign, but look at _push() brvcc->old_push = atmvcc->push; barrier(); atmvcc->push = br2684_push; - skb_queue_head_init(©); - skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, ©); - while ((skb = skb_dequeue(©)) != NULL) { + + rq = &sk_atm(atmvcc)->sk_receive_queue; + + spin_lock_irqsave(&rq->lock, flags); + if (skb_queue_empty(rq)) { + skb = NULL; + } else { + /* NULL terminate the list. */ + rq->prev->next = NULL; + skb = rq->next; + } + rq->prev = rq->next = (struct sk_buff *)rq; + rq->qlen = 0; + spin_unlock_irqrestore(&rq->lock, flags); + + while (skb) { + struct sk_buff *next = skb->next; + + skb->next = skb->prev = NULL; BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; BRPRIV(skb->dev)->stats.rx_packets--; br2684_push(atmvcc, skb); + + skb = next; } __module_get(THIS_MODULE); return 0; diff --git a/net/atm/clip.c b/net/atm/clip.c index 1c416934b7c1..5f8a1d222720 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -38,7 +38,6 @@ #include "common.h" #include "resources.h" -#include "ipcommon.h" #include @@ -469,8 +468,9 @@ static struct net_device_stats *clip_get_stats(struct net_device *dev) static int clip_mkip(struct atm_vcc *vcc, int timeout) { struct clip_vcc *clip_vcc; - struct sk_buff_head copy; struct sk_buff *skb; + struct sk_buff_head *rq; + unsigned long flags; if (!vcc->push) return -EBADFD; @@ -490,10 +490,26 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) clip_vcc->old_pop = vcc->pop; vcc->push = clip_push; vcc->pop = clip_pop; - skb_queue_head_init(©); - skb_migrate(&sk_atm(vcc)->sk_receive_queue, ©); + + rq = &sk_atm(vcc)->sk_receive_queue; + + spin_lock_irqsave(&rq->lock, flags); + if (skb_queue_empty(rq)) { + skb = NULL; + } else { + /* NULL terminate the list. */ + rq->prev->next = NULL; + skb = rq->next; + } + rq->prev = rq->next = (struct sk_buff *)rq; + rq->qlen = 0; + spin_unlock_irqrestore(&rq->lock, flags); + /* re-process everything received between connection setup and MKIP */ - while ((skb = skb_dequeue(©)) != NULL) + while (skb) { + struct sk_buff *next = skb->next; + + skb->next = skb->prev = NULL; if (!clip_devs) { atm_return(vcc, skb->truesize); kfree_skb(skb); @@ -506,6 +522,9 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) PRIV(skb->dev)->stats.rx_bytes -= len; kfree_skb(skb); } + + skb = next; + } return 0; } diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c deleted file mode 100644 index 1d3de42fada0..000000000000 --- a/net/atm/ipcommon.c +++ /dev/null @@ -1,63 +0,0 @@ -/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */ - -/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */ - - -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "ipcommon.h" - - -#if 0 -#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define DPRINTK(format,args...) -#endif - - -/* - * skb_migrate appends the list at "from" to "to", emptying "from" in the - * process. skb_migrate is atomic with respect to all other skb operations on - * "from" and "to". Note that it locks both lists at the same time, so to deal - * with the lock ordering, the locks are taken in address order. - * - * This function should live in skbuff.c or skbuff.h. - */ - - -void skb_migrate(struct sk_buff_head *from, struct sk_buff_head *to) -{ - unsigned long flags; - struct sk_buff *skb_from = (struct sk_buff *) from; - struct sk_buff *skb_to = (struct sk_buff *) to; - struct sk_buff *prev; - - if ((unsigned long) from < (unsigned long) to) { - spin_lock_irqsave(&from->lock, flags); - spin_lock_nested(&to->lock, SINGLE_DEPTH_NESTING); - } else { - spin_lock_irqsave(&to->lock, flags); - spin_lock_nested(&from->lock, SINGLE_DEPTH_NESTING); - } - prev = from->prev; - from->next->prev = to->prev; - prev->next = skb_to; - to->prev->next = from->next; - to->prev = from->prev; - to->qlen += from->qlen; - spin_unlock(&to->lock); - from->prev = skb_from; - from->next = skb_from; - from->qlen = 0; - spin_unlock_irqrestore(&from->lock, flags); -} - - -EXPORT_SYMBOL(skb_migrate); diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h deleted file mode 100644 index d72165f60939..000000000000 --- a/net/atm/ipcommon.h +++ /dev/null @@ -1,22 +0,0 @@ -/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ - -/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */ - - -#ifndef NET_ATM_IPCOMMON_H -#define NET_ATM_IPCOMMON_H - - -#include -#include -#include -#include - -/* - * Appends all skbs from "from" to "to". The operation is atomic with respect - * to all other skb operations on "from" or "to". - */ - -void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to); - -#endif -- cgit v1.2.3-70-g09d2 From a4d1366d5080fcb4514db58c320b9f60d78918e6 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 1 Dec 2006 20:07:42 -0800 Subject: [GENETLINK]: Add cmd dump completion. Remove assumption that generic netlink commands cannot have dump completion callbacks. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/genetlink.h | 2 ++ net/netlink/genetlink.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 7fd131c9a8cc..adff4c898d50 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -53,6 +53,7 @@ struct genl_info * @policy: attribute validation policy * @doit: standard command callback * @dumpit: callback for dumpers + * @done: completion callback for dumps * @ops_list: operations list */ struct genl_ops @@ -64,6 +65,7 @@ struct genl_ops struct genl_info *info); int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); struct list_head ops_list; }; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index cc874f0fcbdb..b9b03747c1f3 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -331,7 +331,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, } *errp = err = netlink_dump_start(genl_sock, skb, nlh, - ops->dumpit, NULL); + ops->dumpit, ops->done); if (err == 0) skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len)); -- cgit v1.2.3-70-g09d2 From a163148c1bec895c1332ea5be497bcda8ce110df Mon Sep 17 00:00:00 2001 From: Kim Nordlund Date: Fri, 1 Dec 2006 20:21:44 -0800 Subject: [PKT_SCHED] act_gact: division by zero Not returning -EINVAL, because someone might want to use the value zero in some future gact_prob algorithm? Signed-off-by: Kim Nordlund Signed-off-by: David S. Miller --- net/sched/act_gact.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 6cff56696a81..85de7efd5fea 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -48,14 +48,14 @@ static struct tcf_hashinfo gact_hash_info = { #ifdef CONFIG_GACT_PROB static int gact_net_rand(struct tcf_gact *gact) { - if (net_random() % gact->tcfg_pval) + if (!gact->tcfg_pval || net_random() % gact->tcfg_pval) return gact->tcf_action; return gact->tcfg_paction; } static int gact_determ(struct tcf_gact *gact) { - if (gact->tcf_bstats.packets % gact->tcfg_pval) + if (!gact->tcfg_pval || gact->tcf_bstats.packets % gact->tcfg_pval) return gact->tcf_action; return gact->tcfg_paction; } -- cgit v1.2.3-70-g09d2 From 9a7c9337a09b1ef07e55f95a4309957a2328a01f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:04:04 -0800 Subject: [NET]: Accept wildcard delimiters in in[46]_pton Accept -1 as delimiter to abort parsing without an error at the first unknown character. This is needed by the upcoming nf_conntrack SIP helper, where addresses are delimited by either '\r' or '\n' characters. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/inet.h | 4 ++-- net/core/utils.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/linux/inet.h b/include/linux/inet.h index b7c6da7d6d32..675a7dbe86f8 100644 --- a/include/linux/inet.h +++ b/include/linux/inet.h @@ -46,7 +46,7 @@ #include extern __be32 in_aton(const char *str); -extern int in4_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); -extern int in6_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); +extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end); +extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end); #endif #endif /* _LINUX_INET_H */ diff --git a/net/core/utils.c b/net/core/utils.c index d93fe64f6693..61556065f07e 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -88,7 +88,7 @@ EXPORT_SYMBOL(in_aton); #define IN6PTON_NULL 0x20000000 /* first/tail */ #define IN6PTON_UNKNOWN 0x40000000 -static inline int digit2bin(char c, char delim) +static inline int digit2bin(char c, int delim) { if (c == delim || c == '\0') return IN6PTON_DELIM; @@ -99,7 +99,7 @@ static inline int digit2bin(char c, char delim) return IN6PTON_UNKNOWN; } -static inline int xdigit2bin(char c, char delim) +static inline int xdigit2bin(char c, int delim) { if (c == delim || c == '\0') return IN6PTON_DELIM; @@ -113,12 +113,14 @@ static inline int xdigit2bin(char c, char delim) return (IN6PTON_XDIGIT | (c - 'a' + 10)); if (c >= 'A' && c <= 'F') return (IN6PTON_XDIGIT | (c - 'A' + 10)); + if (delim == -1) + return IN6PTON_DELIM; return IN6PTON_UNKNOWN; } int in4_pton(const char *src, int srclen, u8 *dst, - char delim, const char **end) + int delim, const char **end) { const char *s; u8 *d; @@ -173,7 +175,7 @@ EXPORT_SYMBOL(in4_pton); int in6_pton(const char *src, int srclen, u8 *dst, - char delim, const char **end) + int delim, const char **end) { const char *s, *tok = NULL; u8 *d, *dc = NULL; -- cgit v1.2.3-70-g09d2 From 0c4ca1bd8638d04796553b6e678063c4fadb92cc Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:04:24 -0800 Subject: [NETFILTER]: nf_conntrack: fix NF_CONNTRACK_PROC_COMPAT dependency NF_CONNTRACK_PROC_COMPAT depends on NF_CONNTRACK_IPV4, not NF_CONNTRACK. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index bc298a3f236f..06fec80a0089 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -21,7 +21,7 @@ config NF_CONNTRACK_IPV4 config NF_CONNTRACK_PROC_COMPAT bool "proc/sysctl compatibility with old connection tracking" - depends on NF_CONNTRACK + depends on NF_CONNTRACK_IPV4 default y help This option enables /proc and sysctl compatibility with the old -- cgit v1.2.3-70-g09d2 From f9aae95828d3478520f4bd73221bcb450ec1a5c0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:04:50 -0800 Subject: [NETFILTER]: nf_conntrack: fix helper structure alignment Adding the alignment to the size doesn't make any sense, what it should do is align the size of the conntrack structure to the alignment requirements of the helper structure and return an aligned pointer in nfct_help(). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 1 + net/netfilter/nf_conntrack_helper.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index d0d0e6491448..b4beb8c799e5 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -273,6 +273,7 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) 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); } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 03b3ed8fca9e..2628f4ba35ee 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -97,13 +97,14 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { - int ret; + 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", - sizeof(struct nf_conn) - + sizeof(struct nf_conn_help) - + __alignof__(struct nf_conn_help)); + size); if (ret < 0) { printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n"); return ret; -- cgit v1.2.3-70-g09d2 From bff9a89bcac5b68ac0a1ea856b1726a35ae1eabb Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:05:08 -0800 Subject: [NETFILTER]: nf_conntrack: endian annotations Resync with Al Viro's ip_conntrack annotations and fix a missed spot in ip_nat_proto_icmp.c. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_tuple.h | 18 ++++++------- net/ipv4/netfilter/ip_nat_proto_icmp.c | 4 +-- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 8 +++--- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 26 +++++++++--------- net/netfilter/nf_conntrack_core.c | 6 ++--- net/netfilter/nf_conntrack_ftp.c | 10 +++---- net/netfilter/nf_conntrack_netlink.c | 37 +++++++++++++------------- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 8 +++--- 11 files changed, 58 insertions(+), 65 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 530ef1f75283..be9dc9a0eb77 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -26,8 +26,8 @@ network order! */ union nf_conntrack_man_l3proto { u_int32_t all[NF_CT_TUPLE_L3SIZE]; - u_int32_t ip; - u_int32_t ip6[4]; + __be32 ip; + __be32 ip6[4]; }; /* The protocol-specific manipulable parts of the tuple: always in @@ -38,16 +38,16 @@ union nf_conntrack_man_proto u_int16_t all; struct { - u_int16_t port; + __be16 port; } tcp; struct { - u_int16_t port; + __be16 port; } udp; struct { - u_int16_t id; + __be16 id; } icmp; struct { - u_int16_t port; + __be16 port; } sctp; }; @@ -77,16 +77,16 @@ struct nf_conntrack_tuple u_int16_t all; struct { - u_int16_t port; + __be16 port; } tcp; struct { - u_int16_t port; + __be16 port; } udp; struct { u_int8_t type, code; } icmp; struct { - u_int16_t port; + __be16 port; } sctp; } u; diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c index 75266fe3e0fa..fb716edd5bc6 100644 --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c @@ -24,8 +24,8 @@ icmp_in_range(const struct ip_conntrack_tuple *tuple, const union ip_conntrack_manip_proto *min, const union ip_conntrack_manip_proto *max) { - return (tuple->src.u.icmp.id >= min->icmp.id - && tuple->src.u.icmp.id <= max->icmp.id); + return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) && + ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id); } static int diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index f24e872d4b90..2b73e3edd94d 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -41,7 +41,7 @@ static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) { - u_int32_t _addrs[2], *ap; + __be32 _addrs[2], *ap; ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), sizeof(u_int32_t) * 2, _addrs); if (ap == NULL) @@ -410,10 +410,8 @@ static int ipv4_nfattr_to_tuple(struct nfattr *tb[], if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; - t->src.u3.ip = - *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); - t->dst.u3.ip = - *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]); + t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); + t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]); return 0; } diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 46aa44abc078..d25002fb8176 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -311,7 +311,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], tuple->dst.u.icmp.code = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); tuple->src.u.icmp.id = - *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); + *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); if (tuple->dst.u.icmp.type >= sizeof(invmap) || !invmap[tuple->dst.u.icmp.type]) diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 1e8e700f6135..3905cacc69af 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -287,7 +287,7 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[], tuple->dst.u.icmp.code = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]); tuple->src.u.icmp.id = - *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]); + *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]); if (tuple->dst.u.icmp.type < 128 || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index bf93c1ea6be9..37e5fca923aa 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -72,7 +72,7 @@ struct nf_ct_frag6_queue struct hlist_node list; struct list_head lru_list; /* lru list member */ - __u32 id; /* fragment id */ + __be32 id; /* fragment id */ struct in6_addr saddr; struct in6_addr daddr; @@ -115,28 +115,28 @@ static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq) write_unlock(&nf_ct_frag6_lock); } -static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, +static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, struct in6_addr *daddr) { u32 a, b, c; - a = saddr->s6_addr32[0]; - b = saddr->s6_addr32[1]; - c = saddr->s6_addr32[2]; + a = (__force u32)saddr->s6_addr32[0]; + b = (__force u32)saddr->s6_addr32[1]; + c = (__force u32)saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += nf_ct_frag6_hash_rnd; __jhash_mix(a, b, c); - a += saddr->s6_addr32[3]; - b += daddr->s6_addr32[0]; - c += daddr->s6_addr32[1]; + a += (__force u32)saddr->s6_addr32[3]; + b += (__force u32)daddr->s6_addr32[0]; + c += (__force u32)daddr->s6_addr32[1]; __jhash_mix(a, b, c); - a += daddr->s6_addr32[2]; - b += daddr->s6_addr32[3]; - c += id; + a += (__force u32)daddr->s6_addr32[2]; + b += (__force u32)daddr->s6_addr32[3]; + c += (__force u32)id; __jhash_mix(a, b, c); return c & (FRAG6Q_HASHSZ - 1); @@ -338,7 +338,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, static struct nf_ct_frag6_queue * -nf_ct_frag6_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst) +nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst) { struct nf_ct_frag6_queue *fq; @@ -366,7 +366,7 @@ oom: } static __inline__ struct nf_ct_frag6_queue * -fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) +fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) { struct nf_ct_frag6_queue *fq; struct hlist_node *n; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a6728067780a..a401b1e31028 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -936,10 +936,8 @@ int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[], if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; - t->src.u.tcp.port = - *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]); - t->dst.u.tcp.port = - *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]); + t->src.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]); + t->dst.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]); return 0; } diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 2d2350152b90..fdac52beeb8c 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -173,7 +173,7 @@ static int try_rfc959(const char *data, size_t dlen, /* Grab port: number up to delimiter */ static int get_port(const char *data, int start, size_t dlen, char delim, - u_int16_t *port) + __be16 *port) { u_int16_t tmp_port = 0; int i; @@ -502,12 +502,12 @@ static int help(struct sk_buff **pskb, .u = { .tcp = { 0 }}, }, .dst = { .protonum = 0xFF, - .u = { .tcp = { 0xFFFF }}, + .u = { .tcp = { __constant_htons(0xFFFF) }}, }, }; if (cmd.l3num == PF_INET) { - exp->mask.src.u3.ip = 0xFFFFFFFF; - exp->mask.dst.u3.ip = 0xFFFFFFFF; + exp->mask.src.u3.ip = htonl(0xFFFFFFFF); + exp->mask.dst.u3.ip = htonl(0xFFFFFFFF); } else { memset(exp->mask.src.u3.ip6, 0xFF, sizeof(exp->mask.src.u3.ip6)); @@ -588,7 +588,7 @@ static int __init nf_conntrack_ftp_init(void) 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 = 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 */ diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e3a720472123..a693d3bd4c11 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -113,7 +113,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb, static inline int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) { - u_int32_t status = htonl((u_int32_t) ct->status); + __be32 status = htonl((u_int32_t) ct->status); NFA_PUT(skb, CTA_STATUS, sizeof(status), &status); return 0; @@ -125,7 +125,7 @@ static inline int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) { long timeout_l = ct->timeout.expires - jiffies; - u_int32_t timeout; + __be32 timeout; if (timeout_l < 0) timeout = 0; @@ -196,7 +196,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, { enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nfattr *nest_count = NFA_NEST(skb, type); - u_int32_t tmp; + __be32 tmp; tmp = htonl(ct->counters[dir].packets); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); @@ -219,7 +219,7 @@ nfattr_failure: static inline int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) { - u_int32_t mark = htonl(ct->mark); + __be32 mark = htonl(ct->mark); NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark); return 0; @@ -234,7 +234,7 @@ nfattr_failure: static inline int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) { - u_int32_t id = htonl(ct->id); + __be32 id = htonl(ct->id); NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id); return 0; @@ -245,7 +245,7 @@ nfattr_failure: static inline int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) { - u_int32_t use = htonl(atomic_read(&ct->ct_general.use)); + __be32 use = htonl(atomic_read(&ct->ct_general.use)); NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use); return 0; @@ -610,12 +610,12 @@ ctnetlink_parse_nat(struct nfattr *nat, return -EINVAL; if (tb[CTA_NAT_MINIP-1]) - range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); + range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]); if (!tb[CTA_NAT_MAXIP-1]) range->max_ip = range->min_ip; else - range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]); + range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]); if (range->min_ip) range->flags |= IP_NAT_RANGE_MAP_IPS; @@ -688,7 +688,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, ct = nf_ct_tuplehash_to_ctrack(h); if (cda[CTA_ID-1]) { - u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1])); + u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1])); if (ct->id != id) { nf_ct_put(ct); return -ENOENT; @@ -781,7 +781,7 @@ static inline int ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[]) { unsigned long d; - unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1])); + unsigned int status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1])); d = ct->status ^ status; if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) @@ -880,7 +880,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) static inline int ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[]) { - u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1])); + u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1])); if (!del_timer(&ct->timeout)) return -ETIME; @@ -942,7 +942,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[]) #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) - ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); + ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); #endif return 0; @@ -963,7 +963,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], if (!cda[CTA_TIMEOUT-1]) goto err; - ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1])); + ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1])); ct->timeout.expires = jiffies + ct->timeout.expires * HZ; ct->status |= IPS_CONFIRMED; @@ -982,7 +982,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) - ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); + ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); #endif help = nfct_help(ct); @@ -1117,8 +1117,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, const struct nf_conntrack_expect *exp) { struct nf_conn *master = exp->master; - u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ); - u_int32_t id = htonl(exp->id); + __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ); + __be32 id = htonl(exp->id); if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) goto nfattr_failure; @@ -1296,7 +1296,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { - u_int32_t id = *(u_int32_t *)NFA_DATA(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); return -ENOENT; @@ -1351,8 +1351,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { - u_int32_t id = - *(u_int32_t *)NFA_DATA(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); return -ENOENT; diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 7c64b9c1cf4a..02b9323e18b7 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -217,7 +217,7 @@ static int sctp_print_conntrack(struct seq_file *s, for (offset = dataoff + sizeof(sctp_sctphdr_t), count = 0; \ offset < skb->len && \ (sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch)); \ - offset += (htons(sch->length) + 3) & ~3, count++) + offset += (ntohs(sch->length) + 3) & ~3, count++) /* Some validity checks to make sure the chunks are fine */ static int do_basic_checks(struct nf_conn *conntrack, diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index d99c7c4176d4..71f492fc6413 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -474,8 +474,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, /* Fast path for timestamp-only option */ if (length == TCPOLEN_TSTAMP_ALIGNED*4 - && *(__u32 *)ptr == - __constant_ntohl((TCPOPT_NOP << 24) + && *(__be32 *)ptr == + __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) @@ -506,9 +506,7 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, for (i = 0; i < (opsize - TCPOLEN_SACK_BASE); i += TCPOLEN_SACK_PERBLOCK) { - memcpy(&tmp, (__u32 *)(ptr + i) + 1, - sizeof(__u32)); - tmp = ntohl(tmp); + tmp = ntohl(*((__be32 *)(ptr+i)+1)); if (after(tmp, *sack)) *sack = tmp; -- cgit v1.2.3-70-g09d2 From 9457d851fc5df54522d733f72cbb1f02ab59272e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:05:25 -0800 Subject: [NETFILTER]: nf_conntrack: automatic helper assignment for expectations Some helpers (namely H.323) manually assign further helpers to expected connections. This is not possible with nf_conntrack anymore since we need to know whether a helper is used at allocation time. Handle the helper assignment centrally, which allows to perform the correct allocation and as a nice side effect eliminates the need for the H.323 helper to fiddle with nf_conntrack_lock. Mid term the allocation scheme really needs to be redesigned since we do both the helper and expectation lookup _twice_ for every new connection. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_expect.h | 3 +++ net/netfilter/nf_conntrack_core.c | 19 ++++++++++++++----- net/netfilter/nf_conntrack_ftp.c | 1 + net/netfilter/nf_conntrack_helper.c | 3 ++- net/netfilter/nf_conntrack_netlink.c | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 2d335f024c85..5d853e826d1d 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -22,6 +22,9 @@ struct nf_conntrack_expect void (*expectfn)(struct nf_conn *new, struct nf_conntrack_expect *this); + /* Helper to assign to new connection */ + struct nf_conntrack_helper *helper; + /* The conntrack of the master connection */ struct nf_conn *master; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a401b1e31028..f952a7fb6ae3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -545,10 +545,10 @@ static int early_drop(struct list_head *chain) 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) + const struct nf_conntrack_l3proto *l3proto, + u_int32_t features) { struct nf_conn *conntrack = NULL; - u_int32_t features = 0; struct nf_conntrack_helper *helper; if (unlikely(!nf_conntrack_hash_rnd_initted)) { @@ -574,7 +574,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, } /* find features needed by this conntrack. */ - features = l3proto->get_features(orig); + features |= l3proto->get_features(orig); /* FIXME: protect helper list per RCU */ read_lock_bh(&nf_conntrack_lock); @@ -624,7 +624,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, struct nf_conntrack_l3proto *l3proto; l3proto = __nf_ct_l3proto_find(orig->src.l3num); - return __nf_conntrack_alloc(orig, repl, l3proto); + return __nf_conntrack_alloc(orig, repl, l3proto, 0); } void nf_conntrack_free(struct nf_conn *conntrack) @@ -649,13 +649,20 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, struct nf_conn *conntrack; 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); + 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"); return (struct nf_conntrack_tuple_hash *)conntrack; @@ -676,6 +683,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, /* Welcome, Mr. Bond. We've been expecting you... */ __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = exp->master; + if (exp->helper) + nfct_help(conntrack)->helper = exp->helper; #ifdef CONFIG_NF_CONNTRACK_MARK conntrack->mark = exp->master->mark; #endif diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index fdac52beeb8c..e96c41d17ee3 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -516,6 +516,7 @@ static int help(struct sk_buff **pskb, } exp->expectfn = NULL; + exp->helper = NULL; exp->flags = 0; /* Now, NAT might want to mangle the packet, and register the diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 2628f4ba35ee..81542dc75069 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -129,7 +129,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Get rid of expectations */ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { struct nf_conn_help *help = nfct_help(exp->master); - if (help->helper == me && del_timer(&exp->timeout)) { + if ((help->helper == me || exp->helper == me) && + del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_conntrack_expect_put(exp); } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index a693d3bd4c11..acaef4025951 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1447,6 +1447,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) exp->expectfn = NULL; exp->flags = 0; exp->master = ct; + exp->helper = NULL; memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple)); -- cgit v1.2.3-70-g09d2 From b321e14425c0234dd9cd07a5327a179507956c7c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:05:46 -0800 Subject: [NETFILTER]: Kconfig: improve conntrack selection Improve the connection tracking selection (well, the user experience, not really the aesthetics) by offering one option to enable connection tracking and a choice between the implementations. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/Kconfig | 14 ------------- net/netfilter/Kconfig | 50 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 06fec80a0089..71485276b819 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -31,20 +31,6 @@ config NF_CONNTRACK_PROC_COMPAT If unsure, say Y. # connection tracking, helpers and protocols -config IP_NF_CONNTRACK - tristate "Connection tracking (required for masq/NAT)" - ---help--- - Connection tracking keeps a record of what packets have passed - through your machine, in order to figure out how they are related - into connections. - - This is required to do Masquerading or other kinds of Network - Address Translation (except for Fast NAT). It can also be used to - enhance packet filtering (see `Connection state match support' - below). - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_CT_ACCT bool "Connection tracking flow accounting" depends on IP_NF_CONNTRACK diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d191dacead5e..efe56f768f34 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -25,19 +25,57 @@ config NETFILTER_NETLINK_LOG and is also scheduled to replace the old syslog-based ipt_LOG and ip6t_LOG modules. -config NF_CONNTRACK - tristate "Layer 3 Independent Connection tracking (EXPERIMENTAL)" - depends on EXPERIMENTAL && IP_NF_CONNTRACK=n - default n - ---help--- +config NF_CONNTRACK_ENABLED + tristate "Netfilter connection tracking support" + help Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related into connections. + This is required to do Masquerading or other kinds of Network + Address Translation (except for Fast NAT). It can also be used to + enhance packet filtering (see `Connection state match support' + below). + + To compile it as a module, choose M here. If unsure, say N. + +choice + prompt "Netfilter connection tracking support" + depends on NF_CONNTRACK_ENABLED + +config NF_CONNTRACK_SUPPORT + bool "Layer 3 Independent Connection tracking (EXPERIMENTAL)" + depends on EXPERIMENTAL + help Layer 3 independent connection tracking is experimental scheme which generalize ip_conntrack to support other layer 3 protocols. - To compile it as a module, choose M here. If unsure, say N. + This is required to do Masquerading or other kinds of Network + Address Translation (except for Fast NAT). It can also be used to + enhance packet filtering (see `Connection state match support' + below). + +config IP_NF_CONNTRACK_SUPPORT + bool "Layer 3 Dependent Connection tracking" + help + The old, Layer 3 dependent ip_conntrack subsystem of netfilter. + + This is required to do Masquerading or other kinds of Network + Address Translation (except for Fast NAT). It can also be used to + enhance packet filtering (see `Connection state match support' + below). + +endchoice + +config NF_CONNTRACK + tristate + default m if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m + default y if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y + +config IP_NF_CONNTRACK + tristate + default m if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m + default y if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y config NF_CT_ACCT bool "Connection tracking flow accounting" -- cgit v1.2.3-70-g09d2 From d2483ddefd38b06053cdce7206382ca61f6282b1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:06:05 -0800 Subject: [NETFILTER]: nf_conntrack: add module aliases to IPv4 conntrack names Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 1 + net/netfilter/nf_conntrack_ftp.c | 1 + net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nf_conntrack_proto_sctp.c | 1 + 4 files changed, 4 insertions(+) (limited to 'net') diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 2b73e3edd94d..653f57b8a107 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -446,6 +446,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { }; MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); +MODULE_ALIAS("ip_conntrack"); MODULE_LICENSE("GPL"); static int __init nf_conntrack_l3proto_ipv4_init(void) diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index e96c41d17ee3..e299d657e4fc 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -34,6 +34,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Rusty Russell "); MODULE_DESCRIPTION("ftp connection tracking helper"); +MODULE_ALIAS("ip_conntrack_ftp"); /* This is slow, but it's simple. --RR */ static char *ftp_buffer; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index acaef4025951..f9c8ddd5973c 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1544,6 +1544,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { .cb = ctnl_exp_cb, }; +MODULE_ALIAS("ip_conntrack_netlink"); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 02b9323e18b7..76e263668222 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -716,3 +716,4 @@ module_exit(nf_conntrack_proto_sctp_fini); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kiran Kumar Immidi"); MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP"); +MODULE_ALIAS("ip_conntrack_proto_sctp"); -- cgit v1.2.3-70-g09d2 From 5b1158e909ecbe1a052203e0d8df15633f829930 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Sat, 2 Dec 2006 22:07:13 -0800 Subject: [NETFILTER]: Add NAT support for nf_conntrack Add NAT support for nf_conntrack. Joint work of Jozsef Kadlecsik, Yasuyuki Kozakai, Martin Josefsson and myself. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter.h | 2 +- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 20 +- include/net/netfilter/nf_conntrack.h | 29 +- include/net/netfilter/nf_conntrack_expect.h | 2 +- include/net/netfilter/nf_nat.h | 77 +++ include/net/netfilter/nf_nat_core.h | 27 ++ include/net/netfilter/nf_nat_helper.h | 32 ++ include/net/netfilter/nf_nat_protocol.h | 70 +++ include/net/netfilter/nf_nat_rule.h | 35 ++ net/ipv4/netfilter/Kconfig | 30 +- net/ipv4/netfilter/Makefile | 7 + net/ipv4/netfilter/ip_nat_standalone.c | 6 - net/ipv4/netfilter/ipt_MASQUERADE.c | 29 +- net/ipv4/netfilter/ipt_NETMAP.c | 4 + net/ipv4/netfilter/ipt_REDIRECT.c | 6 +- net/ipv4/netfilter/ipt_SAME.c | 12 +- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 7 +- net/ipv4/netfilter/nf_nat_core.c | 647 +++++++++++++++++++++++++ net/ipv4/netfilter/nf_nat_helper.c | 433 +++++++++++++++++ net/ipv4/netfilter/nf_nat_proto_icmp.c | 86 ++++ net/ipv4/netfilter/nf_nat_proto_tcp.c | 148 ++++++ net/ipv4/netfilter/nf_nat_proto_udp.c | 138 ++++++ net/ipv4/netfilter/nf_nat_proto_unknown.c | 54 +++ net/ipv4/netfilter/nf_nat_rule.c | 343 +++++++++++++ net/ipv4/netfilter/nf_nat_standalone.c | 406 ++++++++++++++++ net/netfilter/nf_conntrack_core.c | 23 +- net/netfilter/nf_conntrack_netlink.c | 46 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_standalone.c | 5 +- 29 files changed, 2667 insertions(+), 59 deletions(-) create mode 100644 include/net/netfilter/nf_nat.h create mode 100644 include/net/netfilter/nf_nat_core.h create mode 100644 include/net/netfilter/nf_nat_helper.h create mode 100644 include/net/netfilter/nf_nat_protocol.h create mode 100644 include/net/netfilter/nf_nat_rule.h create mode 100644 net/ipv4/netfilter/nf_nat_core.c create mode 100644 net/ipv4/netfilter/nf_nat_helper.c create mode 100644 net/ipv4/netfilter/nf_nat_proto_icmp.c create mode 100644 net/ipv4/netfilter/nf_nat_proto_tcp.c create mode 100644 net/ipv4/netfilter/nf_nat_proto_udp.c create mode 100644 net/ipv4/netfilter/nf_nat_proto_unknown.c create mode 100644 net/ipv4/netfilter/nf_nat_rule.c create mode 100644 net/ipv4/netfilter/nf_nat_standalone.c (limited to 'net') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index f6f3fcbd70ed..d4c4c5120bc0 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -357,7 +357,7 @@ extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); static inline void nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) { -#ifdef CONFIG_IP_NF_NAT_NEEDED +#if defined(CONFIG_IP_NF_NAT_NEEDED) || defined(CONFIG_NF_NAT_NEEDED) void (*decodefn)(struct sk_buff *, struct flowi *); if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL) diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 34b453a81a63..a1c57ee0a4fa 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -9,29 +9,23 @@ #ifndef _NF_CONNTRACK_IPV4_H #define _NF_CONNTRACK_IPV4_H -#ifdef CONFIG_IP_NF_NAT_NEEDED -#include +#ifdef CONFIG_NF_NAT_NEEDED +#include /* per conntrack: nat application helper private data */ -union ip_conntrack_nat_help { +union nf_conntrack_nat_help { /* insert nat helper private data here */ }; -struct nf_conntrack_ipv4_nat { - struct ip_nat_info info; - union ip_conntrack_nat_help help; +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_IP_NF_NAT_NEEDED */ - -struct nf_conntrack_ipv4 { -#ifdef CONFIG_IP_NF_NAT_NEEDED - struct nf_conntrack_ipv4_nat *nat; -#endif -}; +#endif /* CONFIG_NF_NAT_NEEDED */ /* Returns new sk_buff, or NULL */ struct sk_buff * diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index b4beb8c799e5..9948af068688 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -264,18 +264,45 @@ 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 + * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help */ +#ifdef CONFIG_NF_NAT_NEEDED +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); +} + 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_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 5d853e826d1d..b969c430b36a 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -43,7 +43,7 @@ struct nf_conntrack_expect #ifdef CONFIG_NF_NAT_NEEDED /* This is the original per-proto part, used to map the * expected connection the way the recipient expects. */ - union nf_conntrack_manip_proto saved_proto; + union nf_conntrack_man_proto saved_proto; /* Direction relative to the master connection. */ enum ip_conntrack_dir dir; #endif diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h new file mode 100644 index 000000000000..61c62068ca6b --- /dev/null +++ b/include/net/netfilter/nf_nat.h @@ -0,0 +1,77 @@ +#ifndef _NF_NAT_H +#define _NF_NAT_H +#include +#include + +#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16 + +enum nf_nat_manip_type +{ + IP_NAT_MANIP_SRC, + IP_NAT_MANIP_DST +}; + +/* SRC manip occurs POST_ROUTING or LOCAL_IN */ +#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN) + +#define IP_NAT_RANGE_MAP_IPS 1 +#define IP_NAT_RANGE_PROTO_SPECIFIED 2 + +/* NAT sequence number modifications */ +struct nf_nat_seq { + /* position of the last TCP sequence number modification (if any) */ + u_int32_t correction_pos; + + /* sequence number offset before and after last modification */ + int16_t offset_before, offset_after; +}; + +/* Single range specification. */ +struct nf_nat_range +{ + /* Set to OR of flags above. */ + unsigned int flags; + + /* Inclusive: network order. */ + __be32 min_ip, max_ip; + + /* Inclusive: network order */ + union nf_conntrack_man_proto min, max; +}; + +/* For backwards compat: don't use in modern code. */ +struct nf_nat_multi_range_compat +{ + unsigned int rangesize; /* Must be 1. */ + + /* hangs off end. */ + struct nf_nat_range range[1]; +}; + +#ifdef __KERNEL__ +#include + +/* 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; + +/* 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, + unsigned int hooknum); + +/* Is this tuple already taken? (not by us)*/ +extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, + const struct nf_conn *ignored_conntrack); + +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__*/ +#endif diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h new file mode 100644 index 000000000000..9778ffa93440 --- /dev/null +++ b/include/net/netfilter/nf_nat_core.h @@ -0,0 +1,27 @@ +#ifndef _NF_NAT_CORE_H +#define _NF_NAT_CORE_H +#include +#include + +/* This header used to share core functionality between the standalone + NAT module, and the compatibility layer's use of NAT for masquerading. */ + +extern unsigned int nf_nat_packet(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb); + +extern int nf_nat_icmp_reply_translation(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb); + +static inline int nf_nat_initialized(struct nf_conn *ct, + enum nf_nat_manip_type manip) +{ + if (manip == IP_NAT_MANIP_SRC) + return test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status); + else + return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status); +} +#endif /* _NF_NAT_CORE_H */ diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h new file mode 100644 index 000000000000..ec98ecf95fc8 --- /dev/null +++ b/include/net/netfilter/nf_nat_helper.h @@ -0,0 +1,32 @@ +#ifndef _NF_NAT_HELPER_H +#define _NF_NAT_HELPER_H +/* NAT protocol helper routines. */ + +#include + +struct sk_buff; + +/* These return true or false. */ +extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len); +extern int nf_nat_mangle_udp_packet(struct sk_buff **skb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len); +extern int nf_nat_seq_adjust(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo); + +/* Setup NAT on this expected conntrack so it follows master, but goes + * to port ct->master->saved_proto. */ +extern void nf_nat_follow_master(struct nf_conn *ct, + struct nf_conntrack_expect *this); +#endif diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h new file mode 100644 index 000000000000..a9ec5ef61468 --- /dev/null +++ b/include/net/netfilter/nf_nat_protocol.h @@ -0,0 +1,70 @@ +/* Header for use in defining a given protocol. */ +#ifndef _NF_NAT_PROTOCOL_H +#define _NF_NAT_PROTOCOL_H +#include +#include + +struct nf_nat_range; + +struct nf_nat_protocol +{ + /* Protocol name */ + const char *name; + + /* Protocol number. */ + unsigned int protonum; + + struct module *me; + + /* Translate a packet to the target according to manip type. + Return true if succeeded. */ + int (*manip_pkt)(struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype); + + /* Is the manipable part of the tuple between min and max incl? */ + int (*in_range)(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max); + + /* Alter the per-proto part of the tuple (depending on + maniptype), to give a unique tuple in the given range if + possible; return false if not. Per-protocol part of tuple + is initialized to the incoming packet. */ + int (*unique_tuple)(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct); + + int (*range_to_nfattr)(struct sk_buff *skb, + const struct nf_nat_range *range); + + int (*nfattr_to_range)(struct nfattr *tb[], + struct nf_nat_range *range); +}; + +/* Protocol registration. */ +extern int nf_nat_protocol_register(struct nf_nat_protocol *proto); +extern void nf_nat_protocol_unregister(struct nf_nat_protocol *proto); + +extern struct nf_nat_protocol *nf_nat_proto_find_get(u_int8_t protocol); +extern void nf_nat_proto_put(struct nf_nat_protocol *proto); + +/* Built-in protocols. */ +extern struct nf_nat_protocol nf_nat_protocol_tcp; +extern struct nf_nat_protocol nf_nat_protocol_udp; +extern struct nf_nat_protocol nf_nat_protocol_icmp; +extern struct nf_nat_protocol nf_nat_unknown_protocol; + +extern int init_protocols(void) __init; +extern void cleanup_protocols(void); +extern struct nf_nat_protocol *find_nat_proto(u_int16_t protonum); + +extern int nf_nat_port_range_to_nfattr(struct sk_buff *skb, + const struct nf_nat_range *range); +extern int nf_nat_port_nfattr_to_range(struct nfattr *tb[], + struct nf_nat_range *range); + +#endif /*_NF_NAT_PROTO_H*/ diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h new file mode 100644 index 000000000000..f191c672bcc6 --- /dev/null +++ b/include/net/netfilter/nf_nat_rule.h @@ -0,0 +1,35 @@ +#ifndef _NF_NAT_RULE_H +#define _NF_NAT_RULE_H +#include +#include +#include + +/* Compatibility definitions for ipt_FOO modules */ +#define ip_nat_range nf_nat_range +#define ip_conntrack_tuple nf_conntrack_tuple +#define ip_conntrack_get nf_ct_get +#define ip_conntrack nf_conn +#define ip_nat_setup_info nf_nat_setup_info +#define ip_nat_multi_range_compat nf_nat_multi_range_compat +#define ip_ct_iterate_cleanup nf_ct_iterate_cleanup +#define IP_NF_ASSERT NF_CT_ASSERT + +extern int nf_nat_rule_init(void) __init; +extern void nf_nat_rule_cleanup(void); +extern int nf_nat_rule_find(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + struct nf_conn *ct, + struct nf_nat_info *info); + +extern unsigned int +alloc_null_binding(struct nf_conn *ct, + struct nf_nat_info *info, + unsigned int hooknum); + +extern unsigned int +alloc_null_binding_confirmed(struct nf_conn *ct, + struct nf_nat_info *info, + unsigned int hooknum); +#endif /* _NF_NAT_RULE_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 71485276b819..01789aeaeb5f 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -6,7 +6,7 @@ menu "IP: Netfilter Configuration" depends on INET && NETFILTER config NF_CONNTRACK_IPV4 - tristate "IPv4 support for new connection tracking (EXPERIMENTAL)" + tristate "IPv4 support for new connection tracking (required for NAT) (EXPERIMENTAL)" depends on EXPERIMENTAL && NF_CONNTRACK ---help--- Connection tracking keeps a record of what packets have passed @@ -387,7 +387,7 @@ config IP_NF_TARGET_TCPMSS To compile it as a module, choose M here. If unsure, say N. -# NAT + specific targets +# NAT + specific targets: ip_conntrack config IP_NF_NAT tristate "Full NAT" depends on IP_NF_IPTABLES && IP_NF_CONNTRACK @@ -398,14 +398,30 @@ config IP_NF_NAT To compile it as a module, choose M here. If unsure, say N. +# NAT + specific targets: nf_conntrack +config NF_NAT + tristate "Full NAT" + depends on IP_NF_IPTABLES && NF_CONNTRACK + help + The Full NAT option allows masquerading, port forwarding and other + forms of full Network Address Port Translation. It is controlled by + the `nat' table in iptables: see the man page for iptables(8). + + To compile it as a module, choose M here. If unsure, say N. + config IP_NF_NAT_NEEDED bool - depends on IP_NF_NAT != n + depends on IP_NF_NAT + default y + +config NF_NAT_NEEDED + bool + depends on NF_NAT default y config IP_NF_TARGET_MASQUERADE tristate "MASQUERADE target support" - depends on IP_NF_NAT + depends on (NF_NAT || IP_NF_NAT) help Masquerading is a special case of NAT: all outgoing connections are changed to seem to come from a particular interface's address, and @@ -417,7 +433,7 @@ config IP_NF_TARGET_MASQUERADE config IP_NF_TARGET_REDIRECT tristate "REDIRECT target support" - depends on IP_NF_NAT + depends on (NF_NAT || IP_NF_NAT) help REDIRECT is a special case of NAT: all incoming connections are mapped onto the incoming interface's address, causing the packets to @@ -428,7 +444,7 @@ config IP_NF_TARGET_REDIRECT config IP_NF_TARGET_NETMAP tristate "NETMAP target support" - depends on IP_NF_NAT + depends on (NF_NAT || IP_NF_NAT) help NETMAP is an implementation of static 1:1 NAT mapping of network addresses. It maps the network address part, while keeping the host @@ -439,7 +455,7 @@ config IP_NF_TARGET_NETMAP config IP_NF_TARGET_SAME tristate "SAME target support" - depends on IP_NF_NAT + depends on (NF_NAT || IP_NF_NAT) help This option adds a `SAME' target, which works like the standard SNAT target, but attempts to give clients the same IP for all connections. diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 21359d83f0c7..ec31690764ac 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -5,7 +5,12 @@ # objects for the standalone - connection tracking / NAT ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o +nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o +ifneq ($(CONFIG_NF_NAT),) +iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o +else iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o +endif ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o @@ -16,6 +21,7 @@ ip_nat_h323-objs := ip_nat_helper_h323.o # connection tracking obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o obj-$(CONFIG_IP_NF_NAT) += ip_nat.o +obj-$(CONFIG_NF_NAT) += nf_nat.o # conntrack netlink interface obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o @@ -50,6 +56,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o +obj-$(CONFIG_NF_NAT) += iptable_nat.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index d85d2de50449..ad66328baa5d 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -44,12 +44,6 @@ #define DEBUGP(format, args...) #endif -#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \ - : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \ - : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \ - : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ - : "*ERROR*"))) - #ifdef CONFIG_XFRM static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) { diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 3dbfcfac8a84..28b9233956b5 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -2,7 +2,7 @@ (depending on route). */ /* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team + * (C) 2002-2006 Netfilter Core Team * * 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 @@ -20,7 +20,11 @@ #include #include #include +#ifdef CONFIG_NF_NAT_NEEDED +#include +#else #include +#endif #include MODULE_LICENSE("GPL"); @@ -65,23 +69,33 @@ masquerade_target(struct sk_buff **pskb, const struct xt_target *target, const void *targinfo) { +#ifdef CONFIG_NF_NAT_NEEDED + struct nf_conn_nat *nat; +#endif struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; - const struct ip_nat_multi_range_compat *mr; struct ip_nat_range newrange; + const struct ip_nat_multi_range_compat *mr; struct rtable *rt; __be32 newsrc; IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); ct = ip_conntrack_get(*pskb, &ctinfo); +#ifdef CONFIG_NF_NAT_NEEDED + nat = nfct_nat(ct); +#endif IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); /* Source address is 0.0.0.0 - locally generated packet that is * probably not supposed to be masqueraded. */ +#ifdef CONFIG_NF_NAT_NEEDED + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0) +#else if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0) +#endif return NF_ACCEPT; mr = targinfo; @@ -93,7 +107,11 @@ masquerade_target(struct sk_buff **pskb, } write_lock_bh(&masq_lock); +#ifdef CONFIG_NF_NAT_NEEDED + nat->masq_index = out->ifindex; +#else ct->nat.masq_index = out->ifindex; +#endif write_unlock_bh(&masq_lock); /* Transfer from original range. */ @@ -109,10 +127,17 @@ masquerade_target(struct sk_buff **pskb, static inline int device_cmp(struct ip_conntrack *i, void *ifindex) { +#ifdef CONFIG_NF_NAT_NEEDED + struct nf_conn_nat *nat = nfct_nat(i); +#endif int ret; read_lock_bh(&masq_lock); +#ifdef CONFIG_NF_NAT_NEEDED + ret = (nat->masq_index == (int)(long)ifindex); +#else ret = (i->nat.masq_index == (int)(long)ifindex); +#endif read_unlock_bh(&masq_lock); return ret; diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 58a88f227108..9390e90f2b25 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c @@ -15,7 +15,11 @@ #include #include #include +#ifdef CONFIG_NF_NAT_NEEDED +#include +#else #include +#endif #define MODULENAME "NETMAP" MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index c0dcfe9d610c..462eceb3a1b1 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -1,6 +1,6 @@ /* Redirect. Simple mapping which alters dst to a local IP address. */ /* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team + * (C) 2002-2006 Netfilter Core Team * * 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 @@ -18,7 +18,11 @@ #include #include #include +#ifdef CONFIG_NF_NAT_NEEDED +#include +#else #include +#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index b38b13328d73..3dcf29411337 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c @@ -34,7 +34,11 @@ #include #include #include +#ifdef CONFIG_NF_NAT_NEEDED +#include +#else #include +#endif #include MODULE_LICENSE("GPL"); @@ -152,11 +156,17 @@ same_target(struct sk_buff **pskb, Here we calculate the index in same->iparray which holds the ipaddress we should use */ +#ifdef CONFIG_NF_NAT_NEEDED + tmpip = ntohl(t->src.u3.ip); + + if (!(same->info & IPT_SAME_NODST)) + tmpip += ntohl(t->dst.u3.ip); +#else tmpip = ntohl(t->src.ip); if (!(same->info & IPT_SAME_NODST)) tmpip += ntohl(t->dst.ip); - +#endif aindex = tmpip % same->ipnum; new_ip = htonl(same->iparray[aindex]); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 653f57b8a107..5655109dcaff 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -111,10 +111,10 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, return NF_ACCEPT; } -int nat_module_is_loaded = 0; +int nf_nat_module_is_loaded = 0; static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) { - if (nat_module_is_loaded) + if (nf_nat_module_is_loaded) return NF_CT_F_NAT; return NF_CT_F_BASIC; @@ -532,3 +532,6 @@ module_init(nf_conntrack_l3proto_ipv4_init); module_exit(nf_conntrack_l3proto_ipv4_fini); EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); +#ifdef CONFIG_NF_NAT_NEEDED +EXPORT_SYMBOL(nf_nat_module_is_loaded); +#endif diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c new file mode 100644 index 000000000000..86a92272b053 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -0,0 +1,647 @@ +/* NAT for netfilter; shared with compatibility layer. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include /* For tcp_prot in getorigdst */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#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; + +/* Calculated at init based on memory size */ +static unsigned int nf_nat_htable_size; + +static struct list_head *bysource; + +#define MAX_IP_NAT_PROTO 256 +static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]; + +static inline struct nf_nat_protocol * +__nf_nat_proto_find(u_int8_t protonum) +{ + return nf_nat_protos[protonum]; +} + +struct nf_nat_protocol * +nf_nat_proto_find_get(u_int8_t protonum) +{ + struct nf_nat_protocol *p; + + /* we need to disable preemption to make sure 'p' doesn't get + * removed until we've grabbed the reference */ + preempt_disable(); + p = __nf_nat_proto_find(protonum); + if (!try_module_get(p->me)) + p = &nf_nat_unknown_protocol; + preempt_enable(); + + return p; +} +EXPORT_SYMBOL_GPL(nf_nat_proto_find_get); + +void +nf_nat_proto_put(struct nf_nat_protocol *p) +{ + module_put(p->me); +} +EXPORT_SYMBOL_GPL(nf_nat_proto_put); + +/* We keep an extra hash for each conntrack, for fast searching. */ +static inline unsigned int +hash_by_src(const struct nf_conntrack_tuple *tuple) +{ + /* Original src, to ensure we map it consistently if poss. */ + return jhash_3words((__force u32)tuple->src.u3.ip, tuple->src.u.all, + 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); + 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, + const struct nf_conn *ignored_conntrack) +{ + /* Conntrack tracking doesn't keep track of outgoing tuples; only + incoming ones. NAT means they don't have a fixed mapping, + so we invert the tuple and look for the incoming reply. + + We could keep a separate hash if this proves too slow. */ + struct nf_conntrack_tuple reply; + + nf_ct_invert_tuplepr(&reply, tuple); + return nf_conntrack_tuple_taken(&reply, ignored_conntrack); +} +EXPORT_SYMBOL(nf_nat_used_tuple); + +/* If we source map this tuple so reply looks like reply_tuple, will + * that meet the constraints of range. */ +static int +in_range(const struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range) +{ + struct nf_nat_protocol *proto; + + proto = __nf_nat_proto_find(tuple->dst.protonum); + /* If we are supposed to map IPs, then we must be in the + range specified, otherwise let this drag us onto a new src IP. */ + if (range->flags & IP_NAT_RANGE_MAP_IPS) { + if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) || + ntohl(tuple->src.u3.ip) > ntohl(range->max_ip)) + return 0; + } + + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || + proto->in_range(tuple, IP_NAT_MANIP_SRC, + &range->min, &range->max)) + return 1; + + return 0; +} + +static inline int +same_src(const struct nf_conn *ct, + const struct nf_conntrack_tuple *tuple) +{ + const struct nf_conntrack_tuple *t; + + t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + return (t->dst.protonum == tuple->dst.protonum && + t->src.u3.ip == tuple->src.u3.ip && + t->src.u.all == tuple->src.u.all); +} + +/* Only called for SRC manip */ +static int +find_appropriate_src(const struct nf_conntrack_tuple *tuple, + struct nf_conntrack_tuple *result, + const struct nf_nat_range *range) +{ + unsigned int h = hash_by_src(tuple); + struct nf_conn_nat *nat; + struct nf_conn *ct; + + 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)); + if (same_src(ct, tuple)) { + /* Copy source part from reply tuple. */ + nf_ct_invert_tuplepr(result, + &ct->tuplehash[IP_CT_DIR_REPLY].tuple); + result->dst = tuple->dst; + + if (in_range(result, range)) { + read_unlock_bh(&nf_nat_lock); + return 1; + } + } + } + read_unlock_bh(&nf_nat_lock); + return 0; +} + +/* For [FUTURE] fragmentation handling, we want the least-used + src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus + if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports + 1-65535, we don't do pro-rata allocation based on ports; we choose + the ip with the lowest src-ip/dst-ip/proto usage. +*/ +static void +find_best_ips_proto(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + const struct nf_conn *ct, + enum nf_nat_manip_type maniptype) +{ + __be32 *var_ipp; + /* Host order */ + u_int32_t minip, maxip, j; + + /* No IP mapping? Do nothing. */ + if (!(range->flags & IP_NAT_RANGE_MAP_IPS)) + return; + + if (maniptype == IP_NAT_MANIP_SRC) + var_ipp = &tuple->src.u3.ip; + else + var_ipp = &tuple->dst.u3.ip; + + /* Fast path: only one choice. */ + if (range->min_ip == range->max_ip) { + *var_ipp = range->min_ip; + return; + } + + /* Hashing source and destination IPs gives a fairly even + * spread in practice (if there are a small number of IPs + * involved, there usually aren't that many connections + * anyway). The consistency means that servers see the same + * client coming from the same IP (some Internet Banking sites + * like this), even across reboots. */ + minip = ntohl(range->min_ip); + maxip = ntohl(range->max_ip); + j = jhash_2words((__force u32)tuple->src.u3.ip, + (__force u32)tuple->dst.u3.ip, 0); + *var_ipp = htonl(minip + j % (maxip - minip + 1)); +} + +/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING, + * we change the source to map into the range. For NF_IP_PRE_ROUTING + * and NF_IP_LOCAL_OUT, we change the destination to map into the + * range. It might not be possible to get a unique tuple, but we try. + * At worst (or if we race), we will end up with a final duplicate in + * __ip_conntrack_confirm and drop the packet. */ +static void +get_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_tuple *orig_tuple, + const struct nf_nat_range *range, + struct nf_conn *ct, + enum nf_nat_manip_type maniptype) +{ + struct nf_nat_protocol *proto; + + /* 1) If this srcip/proto/src-proto-part is currently mapped, + and that same mapping gives a unique tuple within the given + range, use that. + + This is only required for source (ie. NAT/masq) mappings. + So far, we don't do local source mappings, so multiple + 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"); + if (!nf_nat_used_tuple(tuple, ct)) + return; + } + } + + /* 2) Select the least-used IP/proto combination in the given + range. */ + *tuple = *orig_tuple; + find_best_ips_proto(tuple, range, ct, maniptype); + + /* 3) The per-protocol part of the manip is made to map into + the range to make a unique tuple. */ + + proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); + + /* Only bother mapping if it's not already in range and unique */ + if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || + proto->in_range(tuple, maniptype, &range->min, &range->max)) && + !nf_nat_used_tuple(tuple, ct)) { + nf_nat_proto_put(proto); + return; + } + + /* Last change: get protocol to try to obtain unique tuple. */ + proto->unique_tuple(tuple, range, maniptype, ct); + + nf_nat_proto_put(proto); +} + +unsigned int +nf_nat_setup_info(struct nf_conn *ct, + const struct nf_nat_range *range, + 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; + int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); + enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); + + NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || + hooknum == NF_IP_POST_ROUTING || + hooknum == NF_IP_LOCAL_IN || + hooknum == NF_IP_LOCAL_OUT); + BUG_ON(nf_nat_initialized(ct, maniptype)); + + /* What we've got will look like inverse of reply. Normally + this is what is in the conntrack, except for prior + manipulations (future optimization: if num_manips == 0, + orig_tp = + conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */ + nf_ct_invert_tuplepr(&curr_tuple, + &ct->tuplehash[IP_CT_DIR_REPLY].tuple); + + get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype); + + if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) { + struct nf_conntrack_tuple reply; + + /* Alter conntrack table so will recognize replies. */ + nf_ct_invert_tuplepr(&reply, &new_tuple); + nf_conntrack_alter_reply(ct, &reply); + + /* Non-atomic: we own this at the moment. */ + if (maniptype == IP_NAT_MANIP_SRC) + ct->status |= IPS_SRC_NAT; + else + ct->status |= IPS_DST_NAT; + } + + /* Place in source hash if this is the first time. */ + if (have_to_hash) { + unsigned int srchash; + + srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + write_lock_bh(&nf_nat_lock); + list_add(&info->bysource, &bysource[srchash]); + write_unlock_bh(&nf_nat_lock); + } + + /* It's done. */ + if (maniptype == IP_NAT_MANIP_DST) + set_bit(IPS_DST_NAT_DONE_BIT, &ct->status); + else + set_bit(IPS_SRC_NAT_DONE_BIT, &ct->status); + + return NF_ACCEPT; +} +EXPORT_SYMBOL(nf_nat_setup_info); + +/* Returns true if succeeded. */ +static int +manip_pkt(u_int16_t proto, + struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *target, + enum nf_nat_manip_type maniptype) +{ + struct iphdr *iph; + struct nf_nat_protocol *p; + + if (!skb_make_writable(pskb, iphdroff + sizeof(*iph))) + return 0; + + iph = (void *)(*pskb)->data + iphdroff; + + /* Manipulate protcol part. */ + p = nf_nat_proto_find_get(proto); + if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) { + nf_nat_proto_put(p); + return 0; + } + nf_nat_proto_put(p); + + iph = (void *)(*pskb)->data + iphdroff; + + if (maniptype == IP_NAT_MANIP_SRC) { + nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); + iph->saddr = target->src.u3.ip; + } else { + nf_csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); + iph->daddr = target->dst.u3.ip; + } + return 1; +} + +/* Do packet manipulations according to nf_nat_setup_info. */ +unsigned int nf_nat_packet(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb) +{ + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + unsigned long statusbit; + enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); + + if (mtype == IP_NAT_MANIP_SRC) + statusbit = IPS_SRC_NAT; + else + statusbit = IPS_DST_NAT; + + /* Invert if this is reply dir. */ + if (dir == IP_CT_DIR_REPLY) + statusbit ^= IPS_NAT_MASK; + + /* Non-atomic: these bits don't change. */ + if (ct->status & statusbit) { + struct nf_conntrack_tuple target; + + /* We are aiming to look like inverse of other direction. */ + nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); + + if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype)) + return NF_DROP; + } + return NF_ACCEPT; +} +EXPORT_SYMBOL_GPL(nf_nat_packet); + +/* Dir is direction ICMP is coming from (opposite to packet it contains) */ +int nf_nat_icmp_reply_translation(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb) +{ + struct { + struct icmphdr icmp; + struct iphdr ip; + } *inside; + struct nf_conntrack_tuple inner, target; + int hdrlen = (*pskb)->nh.iph->ihl * 4; + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + unsigned long statusbit; + enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); + + if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) + return 0; + + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + + /* We're actually going to mangle it beyond trivial checksum + adjustment, so make sure the current checksum is correct. */ + if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0)) + return 0; + + /* Must be RELATED */ + NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED || + (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); + + /* Redirects on non-null nats must be dropped, else they'll + start talking to each other without our translation, and be + confused... --RR */ + if (inside->icmp.type == ICMP_REDIRECT) { + /* If NAT isn't finished, assume it and drop. */ + if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) + return 0; + + if (ct->status & IPS_NAT_MASK) + return 0; + } + + DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n", + *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); + + if (!nf_ct_get_tuple(*pskb, + (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr), + (*pskb)->nh.iph->ihl*4 + + sizeof(struct icmphdr) + inside->ip.ihl*4, + (u_int16_t)AF_INET, + inside->ip.protocol, + &inner, + l3proto, + __nf_ct_l4proto_find((u_int16_t)PF_INET, + inside->ip.protocol))) + return 0; + + /* Change inner back to look like incoming packet. We do the + opposite manip on this hook to normal, because it might not + pass all hooks (locally-generated ICMP). Consider incoming + packet: PREROUTING (DST manip), routing produces ICMP, goes + through POSTROUTING (which must correct the DST manip). */ + if (!manip_pkt(inside->ip.protocol, pskb, + (*pskb)->nh.iph->ihl*4 + sizeof(inside->icmp), + &ct->tuplehash[!dir].tuple, + !manip)) + return 0; + + if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { + /* Reloading "inside" here since manip_pkt inner. */ + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + inside->icmp.checksum = 0; + inside->icmp.checksum = + csum_fold(skb_checksum(*pskb, hdrlen, + (*pskb)->len - hdrlen, 0)); + } + + /* Change outer to look the reply to an incoming packet + * (proto 0 means don't invert per-proto part). */ + if (manip == IP_NAT_MANIP_SRC) + statusbit = IPS_SRC_NAT; + else + statusbit = IPS_DST_NAT; + + /* Invert if this is reply dir. */ + if (dir == IP_CT_DIR_REPLY) + statusbit ^= IPS_NAT_MASK; + + if (ct->status & statusbit) { + nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); + if (!manip_pkt(0, pskb, 0, &target, manip)) + return 0; + } + + return 1; +} +EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); + +/* Protocol registration. */ +int nf_nat_protocol_register(struct nf_nat_protocol *proto) +{ + int ret = 0; + + write_lock_bh(&nf_nat_lock); + if (nf_nat_protos[proto->protonum] != &nf_nat_unknown_protocol) { + ret = -EBUSY; + goto out; + } + nf_nat_protos[proto->protonum] = proto; + out: + write_unlock_bh(&nf_nat_lock); + return ret; +} +EXPORT_SYMBOL(nf_nat_protocol_register); + +/* Noone stores the protocol anywhere; simply delete it. */ +void nf_nat_protocol_unregister(struct nf_nat_protocol *proto) +{ + write_lock_bh(&nf_nat_lock); + nf_nat_protos[proto->protonum] = &nf_nat_unknown_protocol; + write_unlock_bh(&nf_nat_lock); + + /* Someone could be still looking at the proto in a bh. */ + synchronize_net(); +} +EXPORT_SYMBOL(nf_nat_protocol_unregister); + +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +int +nf_nat_port_range_to_nfattr(struct sk_buff *skb, + const struct nf_nat_range *range) +{ + NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16), + &range->min.tcp.port); + NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16), + &range->max.tcp.port); + + return 0; + +nfattr_failure: + return -1; +} +EXPORT_SYMBOL_GPL(nf_nat_port_nfattr_to_range); + +int +nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) +{ + int ret = 0; + + /* we have to return whether we actually parsed something or not */ + + if (tb[CTA_PROTONAT_PORT_MIN-1]) { + ret = 1; + range->min.tcp.port = + *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]); + } + + if (!tb[CTA_PROTONAT_PORT_MAX-1]) { + if (ret) + range->max.tcp.port = range->min.tcp.port; + } else { + ret = 1; + range->max.tcp.port = + *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]); + } + + return ret; +} +EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); +#endif + +static int __init nf_nat_init(void) +{ + size_t i; + + /* 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; + + /* Sew in builtin protocols. */ + write_lock_bh(&nf_nat_lock); + for (i = 0; i < MAX_IP_NAT_PROTO; i++) + nf_nat_protos[i] = &nf_nat_unknown_protocol; + nf_nat_protos[IPPROTO_TCP] = &nf_nat_protocol_tcp; + nf_nat_protos[IPPROTO_UDP] = &nf_nat_protocol_udp; + nf_nat_protos[IPPROTO_ICMP] = &nf_nat_protocol_icmp; + write_unlock_bh(&nf_nat_lock); + + for (i = 0; i < nf_nat_htable_size; i++) { + INIT_LIST_HEAD(&bysource[i]); + } + + /* FIXME: Man, this is a hack. */ + NF_CT_ASSERT(nf_conntrack_destroyed == NULL); + nf_conntrack_destroyed = &nf_nat_cleanup_conntrack; + + /* Initialize fake conntrack so that NAT will skip it */ + nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; + + l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); + return 0; +} + +/* Clear NAT section of all conntracks, in case we're loaded again. */ +static int clean_nat(struct nf_conn *i, void *data) +{ + struct nf_conn_nat *nat = nfct_nat(i); + + if (!nat) + return 0; + memset(nat, 0, sizeof(nat)); + i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST); + return 0; +} + +static void __exit nf_nat_cleanup(void) +{ + nf_ct_iterate_cleanup(&clean_nat, NULL); + nf_conntrack_destroyed = NULL; + vfree(bysource); + nf_ct_l3proto_put(l3proto); +} + +MODULE_LICENSE("GPL"); + +module_init(nf_nat_init); +module_exit(nf_nat_cleanup); diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c new file mode 100644 index 000000000000..98fbfc84d183 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -0,0 +1,433 @@ +/* ip_nat_helper.c - generic support functions for NAT helpers + * + * (C) 2000-2002 Harald Welte + * (C) 2003-2006 Netfilter Core Team + * + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#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 + +static DEFINE_SPINLOCK(nf_nat_seqofs_lock); + +/* Setup TCP sequence correction given this change at this sequence */ +static inline void +adjust_tcp_sequence(u32 seq, + int sizediff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + int dir; + 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); + + dir = CTINFO2DIR(ctinfo); + + this_way = &nat->info.seq[dir]; + other_way = &nat->info.seq[!dir]; + + DEBUGP("nf_nat_resize_packet: Seq_offset before: "); + DUMP_OFFSET(this_way); + + spin_lock_bh(&nf_nat_seqofs_lock); + + /* SYN adjust. If it's uninitialized, or this is after last + * correction, record it: we don't handle more than one + * adjustment in the window, but do deal with common case of a + * retransmit */ + if (this_way->offset_before == this_way->offset_after || + before(this_way->correction_pos, seq)) { + this_way->correction_pos = seq; + this_way->offset_before = this_way->offset_after; + this_way->offset_after += sizediff; + } + spin_unlock_bh(&nf_nat_seqofs_lock); + + DEBUGP("nf_nat_resize_packet: Seq_offset after: "); + DUMP_OFFSET(this_way); +} + +/* Frobs data inside this packet, which is linear. */ +static void mangle_contents(struct sk_buff *skb, + unsigned int dataoff, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len) +{ + unsigned char *data; + + BUG_ON(skb_is_nonlinear(skb)); + data = (unsigned char *)skb->nh.iph + dataoff; + + /* move post-replacement */ + memmove(data + match_offset + rep_len, + data + match_offset + match_len, + skb->tail - (data + match_offset + match_len)); + + /* insert data from buffer */ + memcpy(data + match_offset, rep_buffer, rep_len); + + /* 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); + 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); + __skb_trim(skb, skb->len + rep_len - match_len); + } + + /* fix IP hdr checksum information */ + skb->nh.iph->tot_len = htons(skb->len); + ip_send_check(skb->nh.iph); +} + +/* Unusual, but possible case. */ +static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) +{ + struct sk_buff *nskb; + + if ((*pskb)->len + extra > 65535) + return 0; + + nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC); + if (!nskb) + return 0; + + /* Transfer socket to new skb. */ + if ((*pskb)->sk) + skb_set_owner_w(nskb, (*pskb)->sk); + kfree_skb(*pskb); + *pskb = nskb; + return 1; +} + +/* Generic function for mangling variable-length address changes inside + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX + * command in FTP). + * + * Takes care about all the nasty sequence number changes, checksumming, + * skb enlargement, ... + * + * */ +int +nf_nat_mangle_tcp_packet(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len) +{ + struct iphdr *iph; + struct tcphdr *tcph; + int oldlen, datalen; + + if (!skb_make_writable(pskb, (*pskb)->len)) + return 0; + + if (rep_len > match_len && + rep_len - match_len > skb_tailroom(*pskb) && + !enlarge_skb(pskb, rep_len - match_len)) + return 0; + + SKB_LINEAR_ASSERT(*pskb); + + iph = (*pskb)->nh.iph; + tcph = (void *)iph + iph->ihl*4; + + oldlen = (*pskb)->len - iph->ihl*4; + mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4, + match_offset, match_len, rep_buffer, rep_len); + + datalen = (*pskb)->len - iph->ihl*4; + if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { + tcph->check = 0; + tcph->check = tcp_v4_check(tcph, datalen, + iph->saddr, iph->daddr, + csum_partial((char *)tcph, + datalen, 0)); + } else + nf_proto_csum_replace2(&tcph->check, *pskb, + htons(oldlen), htons(datalen), 1); + + if (rep_len != match_len) { + set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); + adjust_tcp_sequence(ntohl(tcph->seq), + (int)rep_len - (int)match_len, + ct, ctinfo); + /* Tell TCP window tracking about seq change */ + nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, + ct, CTINFO2DIR(ctinfo)); + } + return 1; +} +EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); + +/* Generic function for mangling variable-length address changes inside + * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX + * command in the Amanda protocol) + * + * Takes care about all the nasty sequence number changes, checksumming, + * skb enlargement, ... + * + * XXX - This function could be merged with nf_nat_mangle_tcp_packet which + * should be fairly easy to do. + */ +int +nf_nat_mangle_udp_packet(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len) +{ + struct iphdr *iph; + struct udphdr *udph; + int datalen, oldlen; + + /* UDP helpers might accidentally mangle the wrong packet */ + iph = (*pskb)->nh.iph; + if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) + + match_offset + match_len) + return 0; + + if (!skb_make_writable(pskb, (*pskb)->len)) + return 0; + + if (rep_len > match_len && + rep_len - match_len > skb_tailroom(*pskb) && + !enlarge_skb(pskb, rep_len - match_len)) + return 0; + + iph = (*pskb)->nh.iph; + udph = (void *)iph + iph->ihl*4; + + oldlen = (*pskb)->len - iph->ihl*4; + mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph), + match_offset, match_len, rep_buffer, rep_len); + + /* update the length of the UDP packet */ + datalen = (*pskb)->len - iph->ihl*4; + udph->len = htons(datalen); + + /* fix udp checksum if udp checksum was previously calculated */ + if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL) + return 1; + + if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { + udph->check = 0; + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + datalen, IPPROTO_UDP, + csum_partial((char *)udph, + datalen, 0)); + if (!udph->check) + udph->check = CSUM_MANGLED_0; + } else + nf_proto_csum_replace2(&udph->check, *pskb, + htons(oldlen), htons(datalen), 1); + + return 1; +} +EXPORT_SYMBOL(nf_nat_mangle_udp_packet); + +/* Adjust one found SACK option including checksum correction */ +static void +sack_adjust(struct sk_buff *skb, + struct tcphdr *tcph, + unsigned int sackoff, + unsigned int sackend, + struct nf_nat_seq *natseq) +{ + while (sackoff < sackend) { + struct tcp_sack_block_wire *sack; + __be32 new_start_seq, new_end_seq; + + sack = (void *)skb->data + sackoff; + if (after(ntohl(sack->start_seq) - natseq->offset_before, + natseq->correction_pos)) + new_start_seq = htonl(ntohl(sack->start_seq) + - natseq->offset_after); + else + new_start_seq = htonl(ntohl(sack->start_seq) + - natseq->offset_before); + + if (after(ntohl(sack->end_seq) - natseq->offset_before, + natseq->correction_pos)) + new_end_seq = htonl(ntohl(sack->end_seq) + - natseq->offset_after); + else + 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); + + nf_proto_csum_replace4(&tcph->check, skb, + sack->start_seq, new_start_seq, 0); + nf_proto_csum_replace4(&tcph->check, skb, + sack->end_seq, new_end_seq, 0); + sack->start_seq = new_start_seq; + sack->end_seq = new_end_seq; + sackoff += sizeof(*sack); + } +} + +/* TCP SACK sequence number adjustment */ +static inline unsigned int +nf_nat_sack_adjust(struct sk_buff **pskb, + struct tcphdr *tcph, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + unsigned int dir, optoff, optend; + struct nf_conn_nat *nat = nfct_nat(ct); + + optoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct tcphdr); + optend = (*pskb)->nh.iph->ihl*4 + tcph->doff*4; + + if (!skb_make_writable(pskb, optend)) + return 0; + + dir = CTINFO2DIR(ctinfo); + + while (optoff < optend) { + /* Usually: option, length. */ + unsigned char *op = (*pskb)->data + optoff; + + switch (op[0]) { + case TCPOPT_EOL: + return 1; + case TCPOPT_NOP: + optoff++; + continue; + default: + /* no partial options */ + if (optoff + 1 == optend || + optoff + op[1] > optend || + op[1] < 2) + return 0; + if (op[0] == TCPOPT_SACK && + 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]; + } + } + return 1; +} + +/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ +int +nf_nat_seq_adjust(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + struct tcphdr *tcph; + int dir; + __be32 newseq, newack; + struct nf_conn_nat *nat = nfct_nat(ct); + struct nf_nat_seq *this_way, *other_way; + + dir = CTINFO2DIR(ctinfo); + + this_way = &nat->info.seq[dir]; + other_way = &nat->info.seq[!dir]; + + if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph))) + return 0; + + tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + if (after(ntohl(tcph->seq), this_way->correction_pos)) + newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); + else + newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); + + if (after(ntohl(tcph->ack_seq) - other_way->offset_before, + other_way->correction_pos)) + newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); + else + newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); + + 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)); + + tcph->seq = newseq; + tcph->ack_seq = newack; + + if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo)) + return 0; + + nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, ct, dir); + + return 1; +} +EXPORT_SYMBOL(nf_nat_seq_adjust); + +/* Setup NAT on this expected conntrack so it follows master. */ +/* If we fail to get a free NAT slot, we'll get dropped on confirm */ +void nf_nat_follow_master(struct nf_conn *ct, + struct nf_conntrack_expect *exp) +{ + struct nf_nat_range range; + + /* This must be a fresh one. */ + BUG_ON(ct->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; + /* hook doesn't matter, but it has to do source manip */ + nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); + range.min = range.max = exp->saved_proto; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; + /* hook doesn't matter, but it has to do destination manip */ + nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); +} +EXPORT_SYMBOL(nf_nat_follow_master); diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c new file mode 100644 index 000000000000..dcfd772972d7 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c @@ -0,0 +1,86 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include + +static int +icmp_in_range(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max) +{ + return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) && + ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id); +} + +static int +icmp_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct) +{ + static u_int16_t id; + unsigned int range_size; + unsigned int i; + + range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; + /* If no range specified... */ + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) + range_size = 0xFFFF; + + for (i = 0; i < range_size; i++, id++) { + tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) + + (id % range_size)); + if (!nf_nat_used_tuple(tuple, ct)) + return 1; + } + return 0; +} + +static int +icmp_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype) +{ + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + struct icmphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; + + if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) + return 0; + + hdr = (struct icmphdr *)((*pskb)->data + hdroff); + nf_proto_csum_replace2(&hdr->checksum, *pskb, + hdr->un.echo.id, tuple->src.u.icmp.id, 0); + hdr->un.echo.id = tuple->src.u.icmp.id; + return 1; +} + +struct nf_nat_protocol nf_nat_protocol_icmp = { + .name = "ICMP", + .protonum = IPPROTO_ICMP, + .me = THIS_MODULE, + .manip_pkt = icmp_manip_pkt, + .in_range = icmp_in_range, + .unique_tuple = icmp_unique_tuple, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .range_to_nfattr = nf_nat_port_range_to_nfattr, + .nfattr_to_range = nf_nat_port_nfattr_to_range, +#endif +}; diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c new file mode 100644 index 000000000000..7e26a7e9bee1 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -0,0 +1,148 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include +#include + +static int +tcp_in_range(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max) +{ + __be16 port; + + if (maniptype == IP_NAT_MANIP_SRC) + port = tuple->src.u.tcp.port; + else + port = tuple->dst.u.tcp.port; + + return ntohs(port) >= ntohs(min->tcp.port) && + ntohs(port) <= ntohs(max->tcp.port); +} + +static int +tcp_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct) +{ + static u_int16_t port; + __be16 *portptr; + unsigned int range_size, min, i; + + if (maniptype == IP_NAT_MANIP_SRC) + portptr = &tuple->src.u.tcp.port; + else + portptr = &tuple->dst.u.tcp.port; + + /* If no range specified... */ + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { + /* If it's dst rewrite, can't change port */ + if (maniptype == IP_NAT_MANIP_DST) + return 0; + + /* Map privileged onto privileged. */ + if (ntohs(*portptr) < 1024) { + /* Loose convention: >> 512 is credential passing */ + if (ntohs(*portptr)<512) { + min = 1; + range_size = 511 - min + 1; + } else { + min = 600; + range_size = 1023 - min + 1; + } + } else { + min = 1024; + range_size = 65535 - 1024 + 1; + } + } else { + min = ntohs(range->min.tcp.port); + range_size = ntohs(range->max.tcp.port) - min + 1; + } + + for (i = 0; i < range_size; i++, port++) { + *portptr = htons(min + port % range_size); + if (!nf_nat_used_tuple(tuple, ct)) + return 1; + } + return 0; +} + +static int +tcp_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype) +{ + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + struct tcphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; + __be32 oldip, newip; + __be16 *portptr, newport, oldport; + int hdrsize = 8; /* TCP connection tracking guarantees this much */ + + /* this could be a inner header returned in icmp packet; in such + cases we cannot update the checksum field since it is outside of + the 8 bytes of transport layer headers we are guaranteed */ + if ((*pskb)->len >= hdroff + sizeof(struct tcphdr)) + hdrsize = sizeof(struct tcphdr); + + if (!skb_make_writable(pskb, hdroff + hdrsize)) + return 0; + + iph = (struct iphdr *)((*pskb)->data + iphdroff); + hdr = (struct tcphdr *)((*pskb)->data + hdroff); + + if (maniptype == IP_NAT_MANIP_SRC) { + /* Get rid of src ip and src pt */ + oldip = iph->saddr; + newip = tuple->src.u3.ip; + newport = tuple->src.u.tcp.port; + portptr = &hdr->source; + } else { + /* Get rid of dst ip and dst pt */ + oldip = iph->daddr; + newip = tuple->dst.u3.ip; + newport = tuple->dst.u.tcp.port; + portptr = &hdr->dest; + } + + oldport = *portptr; + *portptr = newport; + + if (hdrsize < sizeof(*hdr)) + return 1; + + nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); + nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0); + return 1; +} + +struct nf_nat_protocol nf_nat_protocol_tcp = { + .name = "TCP", + .protonum = IPPROTO_TCP, + .me = THIS_MODULE, + .manip_pkt = tcp_manip_pkt, + .in_range = tcp_in_range, + .unique_tuple = tcp_unique_tuple, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .range_to_nfattr = nf_nat_port_range_to_nfattr, + .nfattr_to_range = nf_nat_port_nfattr_to_range, +#endif +}; diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c new file mode 100644 index 000000000000..ab0ce4c8699f --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -0,0 +1,138 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include + +static int +udp_in_range(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max) +{ + __be16 port; + + if (maniptype == IP_NAT_MANIP_SRC) + port = tuple->src.u.udp.port; + else + port = tuple->dst.u.udp.port; + + return ntohs(port) >= ntohs(min->udp.port) && + ntohs(port) <= ntohs(max->udp.port); +} + +static int +udp_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct) +{ + static u_int16_t port; + __be16 *portptr; + unsigned int range_size, min, i; + + if (maniptype == IP_NAT_MANIP_SRC) + portptr = &tuple->src.u.udp.port; + else + portptr = &tuple->dst.u.udp.port; + + /* If no range specified... */ + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { + /* If it's dst rewrite, can't change port */ + if (maniptype == IP_NAT_MANIP_DST) + return 0; + + if (ntohs(*portptr) < 1024) { + /* Loose convention: >> 512 is credential passing */ + if (ntohs(*portptr)<512) { + min = 1; + range_size = 511 - min + 1; + } else { + min = 600; + range_size = 1023 - min + 1; + } + } else { + min = 1024; + range_size = 65535 - 1024 + 1; + } + } else { + min = ntohs(range->min.udp.port); + range_size = ntohs(range->max.udp.port) - min + 1; + } + + for (i = 0; i < range_size; i++, port++) { + *portptr = htons(min + port % range_size); + if (!nf_nat_used_tuple(tuple, ct)) + return 1; + } + return 0; +} + +static int +udp_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype) +{ + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + struct udphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; + __be32 oldip, newip; + __be16 *portptr, newport; + + if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) + return 0; + + iph = (struct iphdr *)((*pskb)->data + iphdroff); + hdr = (struct udphdr *)((*pskb)->data + hdroff); + + if (maniptype == IP_NAT_MANIP_SRC) { + /* Get rid of src ip and src pt */ + oldip = iph->saddr; + newip = tuple->src.u3.ip; + newport = tuple->src.u.udp.port; + portptr = &hdr->source; + } else { + /* Get rid of dst ip and dst pt */ + oldip = iph->daddr; + newip = tuple->dst.u3.ip; + newport = tuple->dst.u.udp.port; + portptr = &hdr->dest; + } + if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { + nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); + nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, + 0); + if (!hdr->check) + hdr->check = CSUM_MANGLED_0; + } + *portptr = newport; + return 1; +} + +struct nf_nat_protocol nf_nat_protocol_udp = { + .name = "UDP", + .protonum = IPPROTO_UDP, + .me = THIS_MODULE, + .manip_pkt = udp_manip_pkt, + .in_range = udp_in_range, + .unique_tuple = udp_unique_tuple, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .range_to_nfattr = nf_nat_port_range_to_nfattr, + .nfattr_to_range = nf_nat_port_nfattr_to_range, +#endif +}; diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c new file mode 100644 index 000000000000..f50d0203f9c0 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c @@ -0,0 +1,54 @@ +/* The "unknown" protocol. This is what is used for protocols we + * don't understand. It's returned by ip_ct_find_proto(). + */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 int unknown_in_range(const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type manip_type, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max) +{ + return 1; +} + +static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *ct) +{ + /* Sorry: we can't help you; if it's not unique, we can't frob + anything. */ + return 0; +} + +static int +unknown_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype) +{ + return 1; +} + +struct nf_nat_protocol nf_nat_unknown_protocol = { + .name = "unknown", + /* .me isn't set: getting a ref to this cannot fail. */ + .manip_pkt = unknown_manip_pkt, + .in_range = unknown_in_range, + .unique_tuple = unknown_unique_tuple, +}; diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c new file mode 100644 index 000000000000..b868ee0195d4 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -0,0 +1,343 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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. + */ + +/* Everything about the rules for NAT. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +#define NAT_VALID_HOOKS ((1<range[0], hooknum); +} + +/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */ +static void warn_if_extra_mangle(__be32 dstip, __be32 srcip) +{ + static int warned = 0; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } }; + struct rtable *rt; + + if (ip_route_output_key(&rt, &fl) != 0) + return; + + if (rt->rt_src != srcip && !warned) { + printk("NAT: no longer support implicit source local NAT\n"); + printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n", + NIPQUAD(srcip), NIPQUAD(dstip)); + warned = 1; + } + ip_rt_put(rt); +} + +static unsigned int ipt_dnat_target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const struct xt_target *target, + const void *targinfo) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + const struct nf_nat_multi_range_compat *mr = targinfo; + + NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || + hooknum == NF_IP_LOCAL_OUT); + + ct = nf_ct_get(*pskb, &ctinfo); + + /* Connection must be valid and new. */ + NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); + + if (hooknum == NF_IP_LOCAL_OUT && + mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) + warn_if_extra_mangle((*pskb)->nh.iph->daddr, + mr->range[0].min_ip); + + return nf_nat_setup_info(ct, &mr->range[0], hooknum); +} + +static int ipt_snat_checkentry(const char *tablename, + const void *entry, + const struct xt_target *target, + void *targinfo, + unsigned int hook_mask) +{ + struct nf_nat_multi_range_compat *mr = targinfo; + + /* Must be a valid range */ + if (mr->rangesize != 1) { + printk("SNAT: multiple ranges no longer supported\n"); + return 0; + } + return 1; +} + +static int ipt_dnat_checkentry(const char *tablename, + const void *entry, + const struct xt_target *target, + void *targinfo, + unsigned int hook_mask) +{ + struct nf_nat_multi_range_compat *mr = targinfo; + + /* Must be a valid range */ + if (mr->rangesize != 1) { + printk("DNAT: multiple ranges no longer supported\n"); + return 0; + } + return 1; +} + +inline unsigned int +alloc_null_binding(struct nf_conn *ct, + struct nf_nat_info *info, + unsigned int hooknum) +{ + /* Force range to this IP; let proto decide mapping for + per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). + Use reply in case it's already been mangled (eg local packet). + */ + __be32 ip + = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip + : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); + struct nf_nat_range range + = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } }; + + DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", + ct, NIPQUAD(ip)); + return nf_nat_setup_info(ct, &range, hooknum); +} + +unsigned int +alloc_null_binding_confirmed(struct nf_conn *ct, + struct nf_nat_info *info, + unsigned int hooknum) +{ + __be32 ip + = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip + : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); + u_int16_t all + = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all + : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all); + struct nf_nat_range range + = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } }; + + DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n", + ct, NIPQUAD(ip)); + return nf_nat_setup_info(ct, &range, hooknum); +} + +int nf_nat_rule_find(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + struct nf_conn *ct, + struct nf_nat_info *info) +{ + int ret; + + ret = ipt_do_table(pskb, hooknum, in, out, &nat_table); + + if (ret == NF_ACCEPT) { + if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) + /* NUL mapping */ + ret = alloc_null_binding(ct, info, hooknum); + } + return ret; +} + +static struct ipt_target ipt_snat_reg = { + .name = "SNAT", + .target = ipt_snat_target, + .targetsize = sizeof(struct nf_nat_multi_range_compat), + .table = "nat", + .hooks = 1 << NF_IP_POST_ROUTING, + .checkentry = ipt_snat_checkentry, + .family = AF_INET, +}; + +static struct xt_target ipt_dnat_reg = { + .name = "DNAT", + .target = ipt_dnat_target, + .targetsize = sizeof(struct nf_nat_multi_range_compat), + .table = "nat", + .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), + .checkentry = ipt_dnat_checkentry, + .family = AF_INET, +}; + +int __init nf_nat_rule_init(void) +{ + int ret; + + ret = ipt_register_table(&nat_table, &nat_initial_table.repl); + if (ret != 0) + return ret; + ret = xt_register_target(&ipt_snat_reg); + if (ret != 0) + goto unregister_table; + + ret = xt_register_target(&ipt_dnat_reg); + if (ret != 0) + goto unregister_snat; + + return ret; + + unregister_snat: + xt_unregister_target(&ipt_snat_reg); + unregister_table: + ipt_unregister_table(&nat_table); + + return ret; +} + +void nf_nat_rule_cleanup(void) +{ + xt_unregister_target(&ipt_dnat_reg); + xt_unregister_target(&ipt_snat_reg); + ipt_unregister_table(&nat_table); +} diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c new file mode 100644 index 000000000000..730a7a44c883 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -0,0 +1,406 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \ + : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \ + : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \ + : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ + : "*ERROR*"))) + +#ifdef CONFIG_XFRM +static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) +{ + struct nf_conn *ct; + struct nf_conntrack_tuple *t; + enum ip_conntrack_info ctinfo; + enum ip_conntrack_dir dir; + unsigned long statusbit; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) + return; + dir = CTINFO2DIR(ctinfo); + t = &ct->tuplehash[dir].tuple; + + if (dir == IP_CT_DIR_ORIGINAL) + statusbit = IPS_DST_NAT; + else + statusbit = IPS_SRC_NAT; + + if (ct->status & statusbit) { + fl->fl4_dst = t->dst.u3.ip; + if (t->dst.protonum == IPPROTO_TCP || + t->dst.protonum == IPPROTO_UDP) + fl->fl_ip_dport = t->dst.u.tcp.port; + } + + statusbit ^= IPS_NAT_MASK; + + if (ct->status & statusbit) { + fl->fl4_src = t->src.u3.ip; + if (t->dst.protonum == IPPROTO_TCP || + t->dst.protonum == IPPROTO_UDP) + fl->fl_ip_sport = t->src.u.tcp.port; + } +} +#endif + +static unsigned int +nf_nat_fn(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + struct nf_conn_nat *nat; + struct nf_nat_info *info; + /* maniptype == SRC for postrouting. */ + enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); + + /* We never see fragments: conntrack defrags on pre-routing + and local-out, and nf_nat_out protects post-routing. */ + NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off + & htons(IP_MF|IP_OFFSET))); + + ct = nf_ct_get(*pskb, &ctinfo); + /* Can't track? It's not due to stress, or conntrack would + have dropped it. Hence it's the user's responsibilty to + packet filter it out, or implement conntrack/NAT for that + protocol. 8) --RR */ + if (!ct) { + /* Exception: ICMP redirect to new connection (not in + hash table yet). We must not let this through, in + case we're doing NAT to the same network. */ + if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { + struct icmphdr _hdr, *hp; + + hp = skb_header_pointer(*pskb, + (*pskb)->nh.iph->ihl*4, + sizeof(_hdr), &_hdr); + if (hp != NULL && + hp->type == ICMP_REDIRECT) + return NF_DROP; + } + return NF_ACCEPT; + } + + /* Don't try to NAT if this packet is not conntracked */ + if (ct == &nf_conntrack_untracked) + return NF_ACCEPT; + + nat = nfct_nat(ct); + if (!nat) + return NF_DROP; + + switch (ctinfo) { + case IP_CT_RELATED: + case IP_CT_RELATED+IP_CT_IS_REPLY: + if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { + if (!nf_nat_icmp_reply_translation(ct, ctinfo, + hooknum, pskb)) + return NF_DROP; + else + return NF_ACCEPT; + } + /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ + case IP_CT_NEW: + info = &nat->info; + + /* Seen it before? This can happen for loopback, retrans, + or local packets.. */ + if (!nf_nat_initialized(ct, maniptype)) { + unsigned int ret; + + if (unlikely(nf_ct_is_confirmed(ct))) + /* NAT module was loaded late */ + ret = alloc_null_binding_confirmed(ct, info, + hooknum); + else if (hooknum == NF_IP_LOCAL_IN) + /* LOCAL_IN hook doesn't have a chain! */ + ret = alloc_null_binding(ct, info, hooknum); + else + ret = nf_nat_rule_find(pskb, hooknum, in, out, + ct, info); + + if (ret != NF_ACCEPT) { + return ret; + } + } else + DEBUGP("Already setup manip %s for ct %p\n", + maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", + ct); + break; + + default: + /* ESTABLISHED */ + NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || + ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); + info = &nat->info; + } + + NF_CT_ASSERT(info); + return nf_nat_packet(ct, ctinfo, hooknum, pskb); +} + +static unsigned int +nf_nat_in(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + unsigned int ret; + __be32 daddr = (*pskb)->nh.iph->daddr; + + ret = nf_nat_fn(hooknum, pskb, in, out, okfn); + if (ret != NF_DROP && ret != NF_STOLEN && + daddr != (*pskb)->nh.iph->daddr) { + dst_release((*pskb)->dst); + (*pskb)->dst = NULL; + } + return ret; +} + +static unsigned int +nf_nat_out(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ +#ifdef CONFIG_XFRM + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; +#endif + unsigned int ret; + + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) || + (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + + ret = nf_nat_fn(hooknum, pskb, in, out, okfn); +#ifdef CONFIG_XFRM + if (ret != NF_DROP && ret != NF_STOLEN && + (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + + if (ct->tuplehash[dir].tuple.src.u3.ip != + ct->tuplehash[!dir].tuple.dst.u3.ip + || ct->tuplehash[dir].tuple.src.u.all != + ct->tuplehash[!dir].tuple.dst.u.all + ) + return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; + } +#endif + return ret; +} + +static unsigned int +nf_nat_local_fn(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + unsigned int ret; + + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) || + (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + + ret = nf_nat_fn(hooknum, pskb, in, out, okfn); + if (ret != NF_DROP && ret != NF_STOLEN && + (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + + if (ct->tuplehash[dir].tuple.dst.u3.ip != + ct->tuplehash[!dir].tuple.src.u3.ip +#ifdef CONFIG_XFRM + || ct->tuplehash[dir].tuple.dst.u.all != + ct->tuplehash[!dir].tuple.src.u.all +#endif + ) + if (ip_route_me_harder(pskb, RTN_UNSPEC)) + ret = NF_DROP; + } + return ret; +} + +static unsigned int +nf_nat_adjust(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + + ct = nf_ct_get(*pskb, &ctinfo); + if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { + DEBUGP("nf_nat_standalone: adjusting sequence number\n"); + if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) + return NF_DROP; + } + return NF_ACCEPT; +} + +/* We must be after connection tracking and before packet filtering. */ + +static struct nf_hook_ops nf_nat_ops[] = { + /* Before packet filtering, change destination */ + { + .hook = nf_nat_in, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_NAT_DST, + }, + /* After packet filtering, change source */ + { + .hook = nf_nat_out, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SRC, + }, + /* After conntrack, adjust sequence number */ + { + .hook = nf_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, + }, + /* Before packet filtering, change destination */ + { + .hook = nf_nat_local_fn, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_NAT_DST, + }, + /* After packet filtering, change source */ + { + .hook = nf_nat_fn, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SRC, + }, + /* After conntrack, adjust sequence number */ + { + .hook = nf_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, + }, +}; + +static int __init nf_nat_standalone_init(void) +{ + int size, 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; + } + + 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; +#endif + ret = nf_nat_rule_init(); + if (ret < 0) { + printk("nf_nat_init: can't setup rules.\n"); + goto cleanup_decode_session; + } + ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); + if (ret < 0) { + printk("nf_nat_init: can't register hooks.\n"); + goto cleanup_rule_init; + } + nf_nat_module_is_loaded = 1; + return ret; + + cleanup_rule_init: + nf_nat_rule_cleanup(); + cleanup_decode_session: +#ifdef CONFIG_XFRM + 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; +} + +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(); +#endif + /* Conntrack caches are unregistered in nf_conntrack_cleanup */ +} + +module_init(nf_nat_standalone_init); +module_exit(nf_nat_standalone_fini); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_nat"); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f952a7fb6ae3..aa8beabfeebb 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -579,7 +579,8 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, /* FIXME: protect helper list per RCU */ read_lock_bh(&nf_conntrack_lock); helper = __nf_ct_helper_find(repl); - if (helper) + /* 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); @@ -850,6 +851,26 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, orig->dst.protonum)); } +/* Alter reply tuple (maybe alter helper). This is for NAT, and is + implicitly racy: see __nf_conntrack_confirm */ +void nf_conntrack_alter_reply(struct nf_conn *ct, + const struct nf_conntrack_tuple *newreply) +{ + struct nf_conn_help *help = nfct_help(ct); + + write_lock_bh(&nf_conntrack_lock); + /* 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); + NF_CT_DUMP_TUPLE(newreply); + + ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; + if (!ct->master && help && help->expecting == 0) + help->helper = __nf_ct_helper_find(newreply); + write_unlock_bh(&nf_conntrack_lock); +} + /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index f9c8ddd5973c..bd1d2de75e45 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -39,7 +39,11 @@ #include #include #include -#include +#include +#ifdef CONFIG_NF_NAT_NEEDED +#include +#include +#endif #include #include @@ -430,7 +434,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) restart: list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { h = (struct nf_conntrack_tuple_hash *) i; - if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) + if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); /* Dump entries of a given L3 protocol number. @@ -556,28 +560,28 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple, return 0; } -#ifdef CONFIG_IP_NF_NAT_NEEDED +#ifdef CONFIG_NF_NAT_NEEDED static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = { [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t), [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t), }; -static int ctnetlink_parse_nat_proto(struct nfattr *attr, +static int nfnetlink_parse_nat_proto(struct nfattr *attr, const struct nf_conn *ct, - struct ip_nat_range *range) + struct nf_nat_range *range) { struct nfattr *tb[CTA_PROTONAT_MAX]; - struct ip_nat_protocol *npt; + struct nf_nat_protocol *npt; nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) return -EINVAL; - npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); + npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); if (!npt->nfattr_to_range) { - ip_nat_proto_put(npt); + nf_nat_proto_put(npt); return 0; } @@ -585,7 +589,7 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, if (npt->nfattr_to_range(tb, range) > 0) range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; - ip_nat_proto_put(npt); + nf_nat_proto_put(npt); return 0; } @@ -596,8 +600,8 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { }; static inline int -ctnetlink_parse_nat(struct nfattr *nat, - const struct nf_conn *ct, struct ip_nat_range *range) +nfnetlink_parse_nat(struct nfattr *nat, + const struct nf_conn *ct, struct nf_nat_range *range) { struct nfattr *tb[CTA_NAT_MAX]; int err; @@ -623,7 +627,7 @@ ctnetlink_parse_nat(struct nfattr *nat, if (!tb[CTA_NAT_PROTO-1]) return 0; - err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range); + err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range); if (err < 0) return err; @@ -798,35 +802,35 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[]) return -EINVAL; if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { -#ifndef CONFIG_IP_NF_NAT_NEEDED +#ifndef CONFIG_NF_NAT_NEEDED return -EINVAL; #else - struct ip_nat_range range; + struct nf_nat_range range; if (cda[CTA_NAT_DST-1]) { - if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, + if (nfnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, &range) < 0) return -EINVAL; - if (ip_nat_initialized(ct, + if (nf_nat_initialized(ct, HOOK2MANIP(NF_IP_PRE_ROUTING))) return -EEXIST; - ip_nat_setup_info(ct, &range, hooknum); + nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); } if (cda[CTA_NAT_SRC-1]) { - if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, + if (nfnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, &range) < 0) return -EINVAL; - if (ip_nat_initialized(ct, + if (nf_nat_initialized(ct, HOOK2MANIP(NF_IP_POST_ROUTING))) return -EEXIST; - ip_nat_setup_info(ct, &range, hooknum); + nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); } #endif } /* Be careful here, modifying NAT bits can screw up things, * so don't let users modify them directly if they don't pass - * ip_nat_range. */ + * nf_nat_range. */ ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK); return 0; } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 71f492fc6413..8156e429b885 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -730,7 +730,7 @@ static int tcp_in_window(struct ip_ct_tcp *state, return res; } -#ifdef CONFIG_IP_NF_NAT_NEEDED +#ifdef CONFIG_NF_NAT_NEEDED /* Update sender->td_end after NAT successfully mangled the packet */ /* Caller must linearize skb at tcp header. */ void nf_conntrack_tcp_update(struct sk_buff *skb, diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index be94b6359725..3f56a3a6c399 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -530,8 +530,11 @@ EXPORT_SYMBOL(nf_conntrack_lock); EXPORT_SYMBOL(nf_conntrack_hash); EXPORT_SYMBOL(nf_conntrack_untracked); EXPORT_SYMBOL_GPL(nf_conntrack_find_get); -#ifdef CONFIG_IP_NF_NAT_NEEDED +#ifdef CONFIG_NF_NAT_NEEDED EXPORT_SYMBOL(nf_conntrack_tcp_update); +EXPORT_SYMBOL(nf_conntrack_register_cache); +EXPORT_SYMBOL(nf_conntrack_unregister_cache); +EXPORT_SYMBOL(nf_conntrack_alter_reply); #endif EXPORT_SYMBOL(__nf_conntrack_confirm); EXPORT_SYMBOL(nf_ct_get_tuple); -- cgit v1.2.3-70-g09d2 From 55a733247d6d2883d9bb77825fafac3dfca13fc2 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Sat, 2 Dec 2006 22:07:44 -0800 Subject: [NETFILTER]: nf_nat: add FTP NAT helper port Add FTP NAT helper. Split out from Jozsef's big nf_nat patch with a few small fixes by myself. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_ftp.h | 20 +-- include/linux/netfilter_ipv4/ip_conntrack_ftp.h | 40 +++++- include/net/netfilter/nf_conntrack.h | 2 +- net/ipv4/netfilter/Kconfig | 25 ++-- net/ipv4/netfilter/Makefile | 5 +- net/ipv4/netfilter/nf_nat_ftp.c | 179 ++++++++++++++++++++++++ net/netfilter/nf_conntrack_ftp.c | 20 +-- 7 files changed, 260 insertions(+), 31 deletions(-) create mode 100644 net/ipv4/netfilter/nf_nat_ftp.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h index ad4a41c9ce93..81453ea7e4c2 100644 --- a/include/linux/netfilter/nf_conntrack_ftp.h +++ b/include/linux/netfilter/nf_conntrack_ftp.h @@ -3,16 +3,16 @@ /* FTP tracking. */ /* This enum is exposed to userspace */ -enum ip_ct_ftp_type +enum nf_ct_ftp_type { /* PORT command from client */ - IP_CT_FTP_PORT, + NF_CT_FTP_PORT, /* PASV response from server */ - IP_CT_FTP_PASV, + NF_CT_FTP_PASV, /* EPRT command from client */ - IP_CT_FTP_EPRT, + NF_CT_FTP_EPRT, /* EPSV response from server */ - IP_CT_FTP_EPSV, + NF_CT_FTP_EPSV, }; #ifdef __KERNEL__ @@ -21,23 +21,23 @@ enum ip_ct_ftp_type #define NUM_SEQ_TO_REMEMBER 2 /* This structure exists only once per master */ -struct ip_ct_ftp_master { +struct nf_ct_ftp_master { /* Valid seq positions for cmd matching after newline */ u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER]; /* 0 means seq_match_aft_nl not set */ int seq_aft_nl_num[IP_CT_DIR_MAX]; }; -struct ip_conntrack_expect; +struct nf_conntrack_expect; /* For NAT to hook in when we find a packet which describes what other * connection we should expect. */ -extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb, +extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, - enum ip_ct_ftp_type type, + enum nf_ct_ftp_type type, unsigned int matchoff, unsigned int matchlen, - struct ip_conntrack_expect *exp, + struct nf_conntrack_expect *exp, u32 *seq); #endif /* __KERNEL__ */ diff --git a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h index 63811934de4d..2129fc3972ac 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h @@ -1,6 +1,44 @@ #ifndef _IP_CONNTRACK_FTP_H #define _IP_CONNTRACK_FTP_H +/* FTP tracking. */ -#include +/* This enum is exposed to userspace */ +enum ip_ct_ftp_type +{ + /* PORT command from client */ + IP_CT_FTP_PORT, + /* PASV response from server */ + IP_CT_FTP_PASV, + /* EPRT command from client */ + IP_CT_FTP_EPRT, + /* EPSV response from server */ + IP_CT_FTP_EPSV, +}; + +#ifdef __KERNEL__ + +#define FTP_PORT 21 + +#define NUM_SEQ_TO_REMEMBER 2 +/* This structure exists only once per master */ +struct ip_ct_ftp_master { + /* Valid seq positions for cmd matching after newline */ + u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER]; + /* 0 means seq_match_aft_nl not set */ + int seq_aft_nl_num[IP_CT_DIR_MAX]; +}; + +struct ip_conntrack_expect; + +/* For NAT to hook in when we find a packet which describes what other + * connection we should expect. */ +extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + enum ip_ct_ftp_type type, + unsigned int matchoff, + unsigned int matchlen, + struct ip_conntrack_expect *exp, + u32 *seq); +#endif /* __KERNEL__ */ #endif /* _IP_CONNTRACK_FTP_H */ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 9948af068688..83694cfdfa8f 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -45,7 +45,7 @@ union nf_conntrack_expect_proto { /* per conntrack: application helper private data */ union nf_conntrack_help { /* insert conntrack helper private data (master) here */ - struct ip_ct_ftp_master ct_ftp_info; + struct nf_ct_ftp_master ct_ftp_info; }; #include diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 01789aeaeb5f..52f876db68f4 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -477,20 +477,29 @@ config IP_NF_NAT_SNMP_BASIC To compile it as a module, choose M here. If unsure, say N. +# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), +# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. +# From kconfig-language.txt: +# +# '&&' (6) +# +# (6) Returns the result of min(/expr/, /expr/). +config IP_NF_NAT_FTP + tristate + depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT + default IP_NF_NAT && IP_NF_FTP + +config NF_NAT_FTP + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_FTP + config IP_NF_NAT_IRC tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n default IP_NF_NAT if IP_NF_IRC=y default m if IP_NF_IRC=m -# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), -# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh. -config IP_NF_NAT_FTP - tristate - depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n - default IP_NF_NAT if IP_NF_FTP=y - default m if IP_NF_FTP=m - config IP_NF_NAT_TFTP tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index ec31690764ac..c0c6194bb275 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o -# NAT helpers +# NAT helpers (ip_conntrack) obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o @@ -49,6 +49,9 @@ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o +# NAT helpers (nf_conntrack) +obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o + # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c new file mode 100644 index 000000000000..751b59801755 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_ftp.c @@ -0,0 +1,179 @@ +/* FTP extension for TCP NAT alteration. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * 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 +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +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 +mangle_rfc959_packet(struct sk_buff **pskb, + __be32 newip, + u_int16_t port, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + u32 *seq) +{ + char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")]; + + sprintf(buffer, "%u,%u,%u,%u,%u,%u", + NIPQUAD(newip), port>>8, port&0xFF); + + DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + + *seq += strlen(buffer) - matchlen; + return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, + matchlen, buffer, strlen(buffer)); +} + +/* |1|132.235.1.2|6275| */ +static int +mangle_eprt_packet(struct sk_buff **pskb, + __be32 newip, + u_int16_t port, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + u32 *seq) +{ + char buffer[sizeof("|1|255.255.255.255|65535|")]; + + sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); + + DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + + *seq += strlen(buffer) - matchlen; + return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, + matchlen, buffer, strlen(buffer)); +} + +/* |1|132.235.1.2|6275| */ +static int +mangle_epsv_packet(struct sk_buff **pskb, + __be32 newip, + u_int16_t port, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + u32 *seq) +{ + char buffer[sizeof("|||65535|")]; + + sprintf(buffer, "|||%u|", port); + + DEBUGP("calling nf_nat_mangle_tcp_packet\n"); + + *seq += strlen(buffer) - matchlen; + return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, + matchlen, buffer, strlen(buffer)); +} + +static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, + unsigned int, unsigned int, struct nf_conn *, + enum ip_conntrack_info, u32 *seq) += { + [NF_CT_FTP_PORT] = mangle_rfc959_packet, + [NF_CT_FTP_PASV] = mangle_rfc959_packet, + [NF_CT_FTP_EPRT] = mangle_eprt_packet, + [NF_CT_FTP_EPSV] = mangle_epsv_packet +}; + +/* So, this packet has hit the connection tracking matching code. + Mangle it, and change the expectation to match the new version. */ +static unsigned int nf_nat_ftp(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + enum nf_ct_ftp_type type, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp, + u32 *seq) +{ + __be32 newip; + u_int16_t port; + int dir = CTINFO2DIR(ctinfo); + struct nf_conn *ct = exp->master; + + DEBUGP("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; + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->dir = !dir; + + /* When you see the packet, we need to NAT it the same as the + * this one. */ + exp->expectfn = nf_nat_follow_master; + + /* 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) + break; + } + + if (port == 0) + return NF_DROP; + + if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo, + seq)) { + nf_conntrack_unexpect_related(exp); + return NF_DROP; + } + return NF_ACCEPT; +} + +static void __exit nf_nat_ftp_fini(void) +{ + rcu_assign_pointer(nf_nat_ftp_hook, NULL); + synchronize_rcu(); +} + +static int __init nf_nat_ftp_init(void) +{ + BUG_ON(rcu_dereference(nf_nat_ftp_hook)); + rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp); + return 0; +} + +/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */ +static int warn_set(const char *val, struct kernel_param *kp) +{ + printk(KERN_INFO KBUILD_MODNAME + ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n"); + return 0; +} +module_param_call(ports, warn_set, NULL, NULL, 0); + +module_init(nf_nat_ftp_init); +module_exit(nf_nat_ftp_fini); diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index e299d657e4fc..92a947168761 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -51,7 +51,7 @@ module_param(loose, bool, 0600); unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, - enum ip_ct_ftp_type type, + enum nf_ct_ftp_type type, unsigned int matchoff, unsigned int matchlen, struct nf_conntrack_expect *exp, @@ -74,7 +74,7 @@ static struct ftp_search { size_t plen; char skip; char term; - enum ip_ct_ftp_type ftptype; + enum nf_ct_ftp_type ftptype; int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char); } search[IP_CT_DIR_MAX][2] = { [IP_CT_DIR_ORIGINAL] = { @@ -83,7 +83,7 @@ static struct ftp_search { .plen = sizeof("PORT") - 1, .skip = ' ', .term = '\r', - .ftptype = IP_CT_FTP_PORT, + .ftptype = NF_CT_FTP_PORT, .getnum = try_rfc959, }, { @@ -91,7 +91,7 @@ static struct ftp_search { .plen = sizeof("EPRT") - 1, .skip = ' ', .term = '\r', - .ftptype = IP_CT_FTP_EPRT, + .ftptype = NF_CT_FTP_EPRT, .getnum = try_eprt, }, }, @@ -101,7 +101,7 @@ static struct ftp_search { .plen = sizeof("227 ") - 1, .skip = '(', .term = ')', - .ftptype = IP_CT_FTP_PASV, + .ftptype = NF_CT_FTP_PASV, .getnum = try_rfc959, }, { @@ -109,7 +109,7 @@ static struct ftp_search { .plen = sizeof("229 ") - 1, .skip = '(', .term = ')', - .ftptype = IP_CT_FTP_EPSV, + .ftptype = NF_CT_FTP_EPSV, .getnum = try_epsv_response, }, }, @@ -320,7 +320,7 @@ static int find_pattern(const char *data, size_t dlen, } /* Look up to see if we're just after a \n. */ -static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir) +static int find_nl_seq(u32 seq, const struct nf_ct_ftp_master *info, int dir) { unsigned int i; @@ -331,7 +331,7 @@ static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir) } /* We don't update if it's older than what we have. */ -static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir, +static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir, struct sk_buff *skb) { unsigned int i, oldest = NUM_SEQ_TO_REMEMBER; @@ -367,7 +367,7 @@ static int help(struct sk_buff **pskb, u32 seq; int dir = CTINFO2DIR(ctinfo); unsigned int matchlen, matchoff; - struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; + struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; struct nf_conntrack_expect *exp; struct nf_conntrack_man cmd = {}; unsigned int i; @@ -523,7 +523,7 @@ static int help(struct sk_buff **pskb, /* Now, NAT might want to mangle the packet, and register the * (possibly changed) expectation itself. */ nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); - if (nf_nat_ftp) + if (nf_nat_ftp && ct->status & IPS_NAT_MASK) ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, matchoff, matchlen, exp, &seq); else { -- cgit v1.2.3-70-g09d2 From d6a9b6500a8941599bcef98e7de49e1260d104ed Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:08:01 -0800 Subject: [NETFILTER]: nf_conntrack: add helper function for expectation initialization Expectation address masks need to be differently initialized depending on the address family, create helper function to avoid cluttering up the code too much. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_expect.h | 4 ++ include/net/netfilter/nf_conntrack_tuple.h | 10 ++--- net/netfilter/nf_conntrack_expect.c | 68 +++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index b969c430b36a..54a3d038beaa 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -68,6 +68,10 @@ void nf_conntrack_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); diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index be9dc9a0eb77..c96a9c576736 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -24,7 +24,7 @@ /* The l3 protocol-specific manipulable parts of the tuple: always in network order! */ -union nf_conntrack_man_l3proto { +union nf_conntrack_address { u_int32_t all[NF_CT_TUPLE_L3SIZE]; __be32 ip; __be32 ip6[4]; @@ -54,7 +54,7 @@ union nf_conntrack_man_proto /* The manipulable part of the tuple. */ struct nf_conntrack_man { - union nf_conntrack_man_l3proto u3; + union nf_conntrack_address u3; union nf_conntrack_man_proto u; /* Layer 3 protocol */ u_int16_t l3num; @@ -67,11 +67,7 @@ struct nf_conntrack_tuple /* These are the parts of the tuple which are fixed. */ struct { - union { - u_int32_t all[NF_CT_TUPLE_L3SIZE]; - u_int32_t ip; - u_int32_t ip6[4]; - } u3; + union nf_conntrack_address u3; union { /* Add other protocols here. */ u_int16_t all; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index aa5903e4da11..68623ae778c8 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -196,6 +196,74 @@ struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me) return new; } +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) +{ + int len; + + if (family == AF_INET) + len = 4; + else + len = 16; + + exp->flags = 0; + exp->expectfn = NULL; + 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); + if (sizeof(exp->tuple.src.u3) > len) + /* address needs to be cleared for nf_ct_tuple_equal */ + memset((void *)&exp->tuple.src.u3 + len, 0x00, + sizeof(exp->tuple.src.u3) - len); + memset(&exp->mask.src.u3, 0xFF, len); + if (sizeof(exp->mask.src.u3) > len) + memset((void *)&exp->mask.src.u3 + len, 0x00, + sizeof(exp->mask.src.u3) - len); + } else { + memset(&exp->tuple.src.u3, 0x00, sizeof(exp->tuple.src.u3)); + 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; + } else { + exp->tuple.src.u.all = 0; + 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; + } +} +EXPORT_SYMBOL_GPL(nf_conntrack_expect_init); + void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) { if (atomic_dec_and_test(&exp->use)) -- cgit v1.2.3-70-g09d2 From 16958900578b94585c2ab9a2d20d837b4d5e3ba6 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:08:26 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add amanda helper port Add IPv4 and IPv6 capable nf_conntrack port of the Amanda conntrack/NAT helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_amanda.h | 10 ++ net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 1 + net/ipv4/netfilter/nf_nat_amanda.c | 78 +++++++++ net/netfilter/Kconfig | 15 ++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_amanda.c | 237 ++++++++++++++++++++++++++ 7 files changed, 347 insertions(+) create mode 100644 include/linux/netfilter/nf_conntrack_amanda.h create mode 100644 net/ipv4/netfilter/nf_nat_amanda.c create mode 100644 net/netfilter/nf_conntrack_amanda.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h new file mode 100644 index 000000000000..26c223544ae8 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_amanda.h @@ -0,0 +1,10 @@ +#ifndef _NF_CONNTRACK_AMANDA_H +#define _NF_CONNTRACK_AMANDA_H +/* AMANDA tracking. */ + +extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp); +#endif /* _NF_CONNTRACK_AMANDA_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 52f876db68f4..6993ec53dc06 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -512,6 +512,11 @@ config IP_NF_NAT_AMANDA default IP_NF_NAT if IP_NF_AMANDA=y default m if IP_NF_AMANDA=m +config NF_NAT_AMANDA + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_AMANDA + config IP_NF_NAT_PPTP tristate depends on IP_NF_NAT!=n && IP_NF_PPTP!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c0c6194bb275..8893249bbe98 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o # NAT helpers (nf_conntrack) +obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o # generic IP tables diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c new file mode 100644 index 000000000000..0f17098917bc --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_amanda.c @@ -0,0 +1,78 @@ +/* Amanda extension for TCP NAT alteration. + * (C) 2002 by Brian J. Murrell + * based on a copy of HW's ip_nat_irc.c as well as other modules + * + * 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 + +MODULE_AUTHOR("Brian J. Murrell "); +MODULE_DESCRIPTION("Amanda NAT helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_nat_amanda"); + +static unsigned int help(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp) +{ + char buffer[sizeof("65535")]; + u_int16_t port; + unsigned int ret; + + /* Connection comes from client. */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->dir = IP_CT_DIR_ORIGINAL; + + /* When you see the packet, we need to NAT it the same as the + * this one (ie. same IP: it will be TCP and master is UDP). */ + exp->expectfn = nf_nat_follow_master; + + /* 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) + break; + } + + if (port == 0) + return NF_DROP; + + sprintf(buffer, "%u", port); + ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo, + matchoff, matchlen, + buffer, strlen(buffer)); + if (ret != NF_ACCEPT) + nf_conntrack_unexpect_related(exp); + return ret; +} + +static void __exit nf_nat_amanda_fini(void) +{ + rcu_assign_pointer(nf_nat_amanda_hook, NULL); + synchronize_rcu(); +} + +static int __init nf_nat_amanda_init(void) +{ + BUG_ON(rcu_dereference(nf_nat_amanda_hook)); + rcu_assign_pointer(nf_nat_amanda_hook, help); + return 0; +} + +module_init(nf_nat_amanda_init); +module_exit(nf_nat_amanda_fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index efe56f768f34..f85fd43b344b 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -131,6 +131,21 @@ config NF_CT_PROTO_SCTP If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +config NF_CONNTRACK_AMANDA + tristate "Amanda backup protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + select TEXTSEARCH + select TEXTSEARCH_KMP + help + If you are running the Amanda backup package + on this machine or machines that will be MASQUERADED through this + machine, then you may want to enable this feature. This allows the + connection tracking and natting code to allow the sub-channels that + Amanda requires for communication of the backup data, messages and + index. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CONNTRACK_FTP tristate "FTP support on new connection tracking (EXPERIMENTAL)" depends on EXPERIMENTAL && NF_CONNTRACK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 7f0089c584bf..a5ee93817427 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o # connection tracking helpers +obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o # generic X tables diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c new file mode 100644 index 000000000000..5c495dc9d942 --- /dev/null +++ b/net/netfilter/nf_conntrack_amanda.c @@ -0,0 +1,237 @@ +/* Amanda extension for IP connection tracking + * + * (C) 2002 by Brian J. Murrell + * based on HW's ip_conntrack_irc.c as well as other modules + * + * 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 + +static unsigned int master_timeout __read_mostly = 300; +static char *ts_algo = "kmp"; + +MODULE_AUTHOR("Brian J. Murrell "); +MODULE_DESCRIPTION("Amanda connection tracking module"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_amanda"); + +module_param(master_timeout, uint, 0600); +MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); +module_param(ts_algo, charp, 0400); +MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); + +unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp) + __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_amanda_hook); + +enum amanda_strings { + SEARCH_CONNECT, + SEARCH_NEWLINE, + SEARCH_DATA, + SEARCH_MESG, + SEARCH_INDEX, +}; + +static struct { + char *string; + size_t len; + struct ts_config *ts; +} search[] __read_mostly = { + [SEARCH_CONNECT] = { + .string = "CONNECT ", + .len = 8, + }, + [SEARCH_NEWLINE] = { + .string = "\n", + .len = 1, + }, + [SEARCH_DATA] = { + .string = "DATA ", + .len = 5, + }, + [SEARCH_MESG] = { + .string = "MESG ", + .len = 5, + }, + [SEARCH_INDEX] = { + .string = "INDEX ", + .len = 6, + }, +}; + +static int amanda_help(struct sk_buff **pskb, + unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + struct ts_state ts; + struct nf_conntrack_expect *exp; + struct nf_conntrack_tuple *tuple; + unsigned int dataoff, start, stop, off, i; + char pbuf[sizeof("65535")], *tmp; + u_int16_t len; + __be16 port; + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + int ret = NF_ACCEPT; + typeof(nf_nat_amanda_hook) nf_nat_amanda; + + /* Only look at packets from the Amanda server */ + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) + return NF_ACCEPT; + + /* increase the UDP timeout of the master connection as replies from + * Amanda clients to the server can be quite delayed */ + nf_ct_refresh(ct, *pskb, master_timeout * HZ); + + /* No data? */ + dataoff = protoff + sizeof(struct udphdr); + if (dataoff >= (*pskb)->len) { + if (net_ratelimit()) + printk("amanda_help: skblen = %u\n", (*pskb)->len); + return NF_ACCEPT; + } + + memset(&ts, 0, sizeof(ts)); + start = skb_find_text(*pskb, dataoff, (*pskb)->len, + search[SEARCH_CONNECT].ts, &ts); + if (start == UINT_MAX) + goto out; + start += dataoff + search[SEARCH_CONNECT].len; + + memset(&ts, 0, sizeof(ts)); + stop = skb_find_text(*pskb, start, (*pskb)->len, + search[SEARCH_NEWLINE].ts, &ts); + if (stop == UINT_MAX) + goto out; + stop += start; + + for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { + memset(&ts, 0, sizeof(ts)); + off = skb_find_text(*pskb, start, stop, search[i].ts, &ts); + if (off == UINT_MAX) + continue; + off += start + search[i].len; + + len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); + if (skb_copy_bits(*pskb, off, pbuf, len)) + break; + pbuf[len] = '\0'; + + port = htons(simple_strtoul(pbuf, &tmp, 10)); + len = tmp - pbuf; + if (port == 0 || len > 5) + break; + + exp = nf_conntrack_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_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) + ret = NF_DROP; + nf_conntrack_expect_put(exp); + } + +out: + return ret; +} + +static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { + { + .name = "amanda", + .max_expected = 3, + .timeout = 180, + .me = THIS_MODULE, + .help = amanda_help, + .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", + .max_expected = 3, + .timeout = 180, + .me = THIS_MODULE, + .help = amanda_help, + .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, + }, +}; + +static void __exit nf_conntrack_amanda_fini(void) +{ + int i; + + nf_conntrack_helper_unregister(&amanda_helper[0]); + nf_conntrack_helper_unregister(&amanda_helper[1]); + for (i = 0; i < ARRAY_SIZE(search); i++) + textsearch_destroy(search[i].ts); +} + +static int __init nf_conntrack_amanda_init(void) +{ + int ret, i; + + ret = -ENOMEM; + for (i = 0; i < ARRAY_SIZE(search); i++) { + search[i].ts = textsearch_prepare(ts_algo, search[i].string, + search[i].len, + GFP_KERNEL, TS_AUTOLOAD); + if (search[i].ts == NULL) + goto err1; + } + ret = nf_conntrack_helper_register(&amanda_helper[0]); + if (ret < 0) + goto err1; + ret = nf_conntrack_helper_register(&amanda_helper[1]); + if (ret < 0) + goto err2; + return 0; + +err2: + nf_conntrack_helper_unregister(&amanda_helper[0]); +err1: + for (; i >= 0; i--) { + if (search[i].ts) + textsearch_destroy(search[i].ts); + } + return ret; +} + +module_init(nf_conntrack_amanda_init); +module_exit(nf_conntrack_amanda_fini); -- cgit v1.2.3-70-g09d2 From f587de0e2feb9eb9b94f98d0a7b7437e4d6617b4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:08:46 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port Add IPv4 and IPv6 capable nf_conntrack port of the H.323 conntrack/NAT helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_h323.h | 92 + include/linux/netfilter/nf_conntrack_h323_asn1.h | 98 + include/linux/netfilter/nf_conntrack_h323_types.h | 951 ++++++++++ include/linux/netfilter_ipv4/Kbuild | 2 - include/linux/netfilter_ipv4/ip_conntrack_h323.h | 2 +- .../netfilter_ipv4/ip_conntrack_helper_h323_asn1.h | 98 - .../ip_conntrack_helper_h323_types.h | 939 ---------- include/net/netfilter/nf_conntrack.h | 2 + include/net/netfilter/nf_conntrack_expect.h | 1 + net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 3 +- net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 874 --------- .../netfilter/ip_conntrack_helper_h323_types.c | 1926 ------------------- net/ipv4/netfilter/nf_nat_h323.c | 596 ++++++ net/netfilter/Kconfig | 19 + net/netfilter/Makefile | 3 + net/netfilter/nf_conntrack_h323_asn1.c | 874 +++++++++ net/netfilter/nf_conntrack_h323_main.c | 1856 +++++++++++++++++++ net/netfilter/nf_conntrack_h323_types.c | 1927 ++++++++++++++++++++ 19 files changed, 6427 insertions(+), 3841 deletions(-) create mode 100644 include/linux/netfilter/nf_conntrack_h323.h create mode 100644 include/linux/netfilter/nf_conntrack_h323_asn1.h create mode 100644 include/linux/netfilter/nf_conntrack_h323_types.h delete mode 100644 include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h delete mode 100644 include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h delete mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c delete mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_types.c create mode 100644 net/ipv4/netfilter/nf_nat_h323.c create mode 100644 net/netfilter/nf_conntrack_h323_asn1.c create mode 100644 net/netfilter/nf_conntrack_h323_main.c create mode 100644 net/netfilter/nf_conntrack_h323_types.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h new file mode 100644 index 000000000000..08e2f4977c2e --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -0,0 +1,92 @@ +#ifndef _NF_CONNTRACK_H323_H +#define _NF_CONNTRACK_H323_H + +#ifdef __KERNEL__ + +#include + +#define RAS_PORT 1719 +#define Q931_PORT 1720 +#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ + +/* This structure exists only once per master */ +struct nf_ct_h323_master { + + /* Original and NATed Q.931 or H.245 signal ports */ + __be16 sig_port[IP_CT_DIR_MAX]; + + /* Original and NATed RTP ports */ + __be16 rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX]; + + union { + /* RAS connection timeout */ + u_int32_t timeout; + + /* Next TPKT length (for separate TPKT header and data) */ + u_int16_t tpkt_len[IP_CT_DIR_MAX]; + }; +}; + +struct nf_conn; + +extern int get_h225_addr(struct nf_conn *ct, unsigned char *data, + TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 *port); +extern void nf_conntrack_h245_expect(struct nf_conn *new, + struct nf_conntrack_expect *this); +extern void nf_conntrack_q931_expect(struct nf_conn *new, + struct nf_conntrack_expect *this); +extern int (*set_h245_addr_hook) (struct sk_buff **pskb, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + union nf_conntrack_address *addr, + __be16 port); +extern int (*set_h225_addr_hook) (struct sk_buff **pskb, + unsigned char **data, int dataoff, + TransportAddress *taddr, + union nf_conntrack_address *addr, + __be16 port); +extern int (*set_sig_addr_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count); +extern int (*set_ras_addr_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count); +extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + __be16 port, __be16 rtp_port, + struct nf_conntrack_expect *rtp_exp, + struct nf_conntrack_expect *rtcp_exp); +extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp); +extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp); +extern int (*nat_callforwarding_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, + __be16 port, + struct nf_conntrack_expect *exp); +extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress *taddr, + int idx, __be16 port, + struct nf_conntrack_expect *exp); + +#endif + +#endif diff --git a/include/linux/netfilter/nf_conntrack_h323_asn1.h b/include/linux/netfilter/nf_conntrack_h323_asn1.h new file mode 100644 index 000000000000..8dab5968fc7e --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_h323_asn1.h @@ -0,0 +1,98 @@ +/**************************************************************************** + * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323 + * conntrack/NAT module. + * + * Copyright (c) 2006 by Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * + * This library is based on H.225 version 4, H.235 version 2 and H.245 + * version 7. It is extremely optimized to decode only the absolutely + * necessary objects in a signal for Linux kernel NAT module use, so don't + * expect it to be a full ASN.1 library. + * + * Features: + * + * 1. Small. The total size of code plus data is less than 20 KB (IA32). + * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 + * takes only 3.9 seconds. + * 3. No memory allocation. It uses a static object. No need to initialize or + * cleanup. + * 4. Thread safe. + * 5. Support embedded architectures that has no misaligned memory access + * support. + * + * Limitations: + * + * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. + * If a Setup signal contains more than 30 faststart, the packet size will + * very likely exceed the MTU size, then the TPKT will be fragmented. I + * don't know how to handle this in a Netfilter module. Anybody can help? + * Although I think 30 is enough for most of the cases. + * 2. IPv4 addresses only. + * + ****************************************************************************/ + +#ifndef _NF_CONNTRACK_HELPER_H323_ASN1_H_ +#define _NF_CONNTRACK_HELPER_H323_ASN1_H_ + +/***************************************************************************** + * H.323 Types + ****************************************************************************/ +#include "nf_conntrack_h323_types.h" + +typedef struct { + enum { + Q931_NationalEscape = 0x00, + Q931_Alerting = 0x01, + Q931_CallProceeding = 0x02, + Q931_Connect = 0x07, + Q931_ConnectAck = 0x0F, + Q931_Progress = 0x03, + Q931_Setup = 0x05, + Q931_SetupAck = 0x0D, + Q931_Resume = 0x26, + Q931_ResumeAck = 0x2E, + Q931_ResumeReject = 0x22, + Q931_Suspend = 0x25, + Q931_SuspendAck = 0x2D, + Q931_SuspendReject = 0x21, + Q931_UserInformation = 0x20, + Q931_Disconnect = 0x45, + Q931_Release = 0x4D, + Q931_ReleaseComplete = 0x5A, + Q931_Restart = 0x46, + Q931_RestartAck = 0x4E, + Q931_Segment = 0x60, + Q931_CongestionCtrl = 0x79, + Q931_Information = 0x7B, + Q931_Notify = 0x6E, + Q931_Status = 0x7D, + Q931_StatusEnquiry = 0x75, + Q931_Facility = 0x62 + } MessageType; + H323_UserInformation UUIE; +} Q931; + +/***************************************************************************** + * Decode Functions Return Codes + ****************************************************************************/ + +#define H323_ERROR_NONE 0 /* Decoded successfully */ +#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ +#define H323_ERROR_BOUND -1 +#define H323_ERROR_RANGE -2 + + +/***************************************************************************** + * Decode Functions + ****************************************************************************/ + +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); +int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); +int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, + MultimediaSystemControlMessage * + mscm); + +#endif diff --git a/include/linux/netfilter/nf_conntrack_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h new file mode 100644 index 000000000000..38d74d5c9700 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_h323_types.h @@ -0,0 +1,951 @@ +/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006 + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + */ + +typedef struct TransportAddress_ipAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned ip; +} TransportAddress_ipAddress; + +typedef struct TransportAddress_ip6Address { /* SEQUENCE */ + int options; /* No use */ + unsigned ip6; +} TransportAddress_ip6Address; + +typedef struct TransportAddress { /* CHOICE */ + enum { + eTransportAddress_ipAddress, + eTransportAddress_ipSourceRoute, + eTransportAddress_ipxAddress, + eTransportAddress_ip6Address, + eTransportAddress_netBios, + eTransportAddress_nsap, + eTransportAddress_nonStandardAddress, + } choice; + union { + TransportAddress_ipAddress ipAddress; + TransportAddress_ip6Address ip6Address; + }; +} TransportAddress; + +typedef struct DataProtocolCapability { /* CHOICE */ + enum { + eDataProtocolCapability_nonStandard, + eDataProtocolCapability_v14buffered, + eDataProtocolCapability_v42lapm, + eDataProtocolCapability_hdlcFrameTunnelling, + eDataProtocolCapability_h310SeparateVCStack, + eDataProtocolCapability_h310SingleVCStack, + eDataProtocolCapability_transparent, + eDataProtocolCapability_segmentationAndReassembly, + eDataProtocolCapability_hdlcFrameTunnelingwSAR, + eDataProtocolCapability_v120, + eDataProtocolCapability_separateLANStack, + eDataProtocolCapability_v76wCompression, + eDataProtocolCapability_tcp, + eDataProtocolCapability_udp, + } choice; +} DataProtocolCapability; + +typedef struct DataApplicationCapability_application { /* CHOICE */ + enum { + eDataApplicationCapability_application_nonStandard, + eDataApplicationCapability_application_t120, + eDataApplicationCapability_application_dsm_cc, + eDataApplicationCapability_application_userData, + eDataApplicationCapability_application_t84, + eDataApplicationCapability_application_t434, + eDataApplicationCapability_application_h224, + eDataApplicationCapability_application_nlpid, + eDataApplicationCapability_application_dsvdControl, + eDataApplicationCapability_application_h222DataPartitioning, + eDataApplicationCapability_application_t30fax, + eDataApplicationCapability_application_t140, + eDataApplicationCapability_application_t38fax, + eDataApplicationCapability_application_genericDataCapability, + } choice; + union { + DataProtocolCapability t120; + }; +} DataApplicationCapability_application; + +typedef struct DataApplicationCapability { /* SEQUENCE */ + int options; /* No use */ + DataApplicationCapability_application application; +} DataApplicationCapability; + +typedef struct DataType { /* CHOICE */ + enum { + eDataType_nonStandard, + eDataType_nullData, + eDataType_videoData, + eDataType_audioData, + eDataType_data, + eDataType_encryptionData, + eDataType_h235Control, + eDataType_h235Media, + eDataType_multiplexedStream, + } choice; + union { + DataApplicationCapability data; + }; +} DataType; + +typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned network; +} UnicastAddress_iPAddress; + +typedef struct UnicastAddress_iP6Address { /* SEQUENCE */ + int options; /* No use */ + unsigned network; +} UnicastAddress_iP6Address; + +typedef struct UnicastAddress { /* CHOICE */ + enum { + eUnicastAddress_iPAddress, + eUnicastAddress_iPXAddress, + eUnicastAddress_iP6Address, + eUnicastAddress_netBios, + eUnicastAddress_iPSourceRouteAddress, + eUnicastAddress_nsap, + eUnicastAddress_nonStandardAddress, + } choice; + union { + UnicastAddress_iPAddress iPAddress; + UnicastAddress_iP6Address iP6Address; + }; +} UnicastAddress; + +typedef struct H245_TransportAddress { /* CHOICE */ + enum { + eH245_TransportAddress_unicastAddress, + eH245_TransportAddress_multicastAddress, + } choice; + union { + UnicastAddress unicastAddress; + }; +} H245_TransportAddress; + +typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelParameters_nonStandard = (1 << 31), + eH2250LogicalChannelParameters_associatedSessionID = + (1 << 30), + eH2250LogicalChannelParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelParameters_mediaGuaranteedDelivery = + (1 << 28), + eH2250LogicalChannelParameters_mediaControlChannel = + (1 << 27), + eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery + = (1 << 26), + eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), + eH2250LogicalChannelParameters_destination = (1 << 24), + eH2250LogicalChannelParameters_dynamicRTPPayloadType = + (1 << 23), + eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), + eH2250LogicalChannelParameters_transportCapability = + (1 << 21), + eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), + eH2250LogicalChannelParameters_source = (1 << 19), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + DataType dataType; + OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_forwardLogicalChannelParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + = (1 << 31), + eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_reverseLogicalChannelParameters; + +typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ + enum { + eNetworkAccessParameters_networkAddress_q2931Address, + eNetworkAccessParameters_networkAddress_e164Address, + eNetworkAccessParameters_networkAddress_localAreaAddress, + } choice; + union { + H245_TransportAddress localAreaAddress; + }; +} NetworkAccessParameters_networkAddress; + +typedef struct NetworkAccessParameters { /* SEQUENCE */ + enum { + eNetworkAccessParameters_distribution = (1 << 31), + eNetworkAccessParameters_externalReference = (1 << 30), + eNetworkAccessParameters_t120SetupProcedure = (1 << 29), + } options; + NetworkAccessParameters_networkAddress networkAddress; +} NetworkAccessParameters; + +typedef struct OpenLogicalChannel { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannel_separateStack = (1 << 30), + eOpenLogicalChannel_encryptionSync = (1 << 29), + } options; + OpenLogicalChannel_forwardLogicalChannelParameters + forwardLogicalChannelParameters; + OpenLogicalChannel_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + NetworkAccessParameters separateStack; +} OpenLogicalChannel; + +typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Setup_UUIE_fastStart; + +typedef struct Setup_UUIE { /* SEQUENCE */ + enum { + eSetup_UUIE_h245Address = (1 << 31), + eSetup_UUIE_sourceAddress = (1 << 30), + eSetup_UUIE_destinationAddress = (1 << 29), + eSetup_UUIE_destCallSignalAddress = (1 << 28), + eSetup_UUIE_destExtraCallInfo = (1 << 27), + eSetup_UUIE_destExtraCRV = (1 << 26), + eSetup_UUIE_callServices = (1 << 25), + eSetup_UUIE_sourceCallSignalAddress = (1 << 24), + eSetup_UUIE_remoteExtensionAddress = (1 << 23), + eSetup_UUIE_callIdentifier = (1 << 22), + eSetup_UUIE_h245SecurityCapability = (1 << 21), + eSetup_UUIE_tokens = (1 << 20), + eSetup_UUIE_cryptoTokens = (1 << 19), + eSetup_UUIE_fastStart = (1 << 18), + eSetup_UUIE_mediaWaitForConnect = (1 << 17), + eSetup_UUIE_canOverlapSend = (1 << 16), + eSetup_UUIE_endpointIdentifier = (1 << 15), + eSetup_UUIE_multipleCalls = (1 << 14), + eSetup_UUIE_maintainConnection = (1 << 13), + eSetup_UUIE_connectionParameters = (1 << 12), + eSetup_UUIE_language = (1 << 11), + eSetup_UUIE_presentationIndicator = (1 << 10), + eSetup_UUIE_screeningIndicator = (1 << 9), + eSetup_UUIE_serviceControl = (1 << 8), + eSetup_UUIE_symmetricOperationRequired = (1 << 7), + eSetup_UUIE_capacity = (1 << 6), + eSetup_UUIE_circuitInfo = (1 << 5), + eSetup_UUIE_desiredProtocols = (1 << 4), + eSetup_UUIE_neededFeatures = (1 << 3), + eSetup_UUIE_desiredFeatures = (1 << 2), + eSetup_UUIE_supportedFeatures = (1 << 1), + eSetup_UUIE_parallelH245Control = (1 << 0), + } options; + TransportAddress h245Address; + TransportAddress destCallSignalAddress; + TransportAddress sourceCallSignalAddress; + Setup_UUIE_fastStart fastStart; +} Setup_UUIE; + +typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} CallProceeding_UUIE_fastStart; + +typedef struct CallProceeding_UUIE { /* SEQUENCE */ + enum { + eCallProceeding_UUIE_h245Address = (1 << 31), + eCallProceeding_UUIE_callIdentifier = (1 << 30), + eCallProceeding_UUIE_h245SecurityMode = (1 << 29), + eCallProceeding_UUIE_tokens = (1 << 28), + eCallProceeding_UUIE_cryptoTokens = (1 << 27), + eCallProceeding_UUIE_fastStart = (1 << 26), + eCallProceeding_UUIE_multipleCalls = (1 << 25), + eCallProceeding_UUIE_maintainConnection = (1 << 24), + eCallProceeding_UUIE_fastConnectRefused = (1 << 23), + eCallProceeding_UUIE_featureSet = (1 << 22), + } options; + TransportAddress h245Address; + CallProceeding_UUIE_fastStart fastStart; +} CallProceeding_UUIE; + +typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Connect_UUIE_fastStart; + +typedef struct Connect_UUIE { /* SEQUENCE */ + enum { + eConnect_UUIE_h245Address = (1 << 31), + eConnect_UUIE_callIdentifier = (1 << 30), + eConnect_UUIE_h245SecurityMode = (1 << 29), + eConnect_UUIE_tokens = (1 << 28), + eConnect_UUIE_cryptoTokens = (1 << 27), + eConnect_UUIE_fastStart = (1 << 26), + eConnect_UUIE_multipleCalls = (1 << 25), + eConnect_UUIE_maintainConnection = (1 << 24), + eConnect_UUIE_language = (1 << 23), + eConnect_UUIE_connectedAddress = (1 << 22), + eConnect_UUIE_presentationIndicator = (1 << 21), + eConnect_UUIE_screeningIndicator = (1 << 20), + eConnect_UUIE_fastConnectRefused = (1 << 19), + eConnect_UUIE_serviceControl = (1 << 18), + eConnect_UUIE_capacity = (1 << 17), + eConnect_UUIE_featureSet = (1 << 16), + } options; + TransportAddress h245Address; + Connect_UUIE_fastStart fastStart; +} Connect_UUIE; + +typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Alerting_UUIE_fastStart; + +typedef struct Alerting_UUIE { /* SEQUENCE */ + enum { + eAlerting_UUIE_h245Address = (1 << 31), + eAlerting_UUIE_callIdentifier = (1 << 30), + eAlerting_UUIE_h245SecurityMode = (1 << 29), + eAlerting_UUIE_tokens = (1 << 28), + eAlerting_UUIE_cryptoTokens = (1 << 27), + eAlerting_UUIE_fastStart = (1 << 26), + eAlerting_UUIE_multipleCalls = (1 << 25), + eAlerting_UUIE_maintainConnection = (1 << 24), + eAlerting_UUIE_alertingAddress = (1 << 23), + eAlerting_UUIE_presentationIndicator = (1 << 22), + eAlerting_UUIE_screeningIndicator = (1 << 21), + eAlerting_UUIE_fastConnectRefused = (1 << 20), + eAlerting_UUIE_serviceControl = (1 << 19), + eAlerting_UUIE_capacity = (1 << 18), + eAlerting_UUIE_featureSet = (1 << 17), + } options; + TransportAddress h245Address; + Alerting_UUIE_fastStart fastStart; +} Alerting_UUIE; + +typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Information_UUIE_fastStart; + +typedef struct Information_UUIE { /* SEQUENCE */ + enum { + eInformation_UUIE_callIdentifier = (1 << 31), + eInformation_UUIE_tokens = (1 << 30), + eInformation_UUIE_cryptoTokens = (1 << 29), + eInformation_UUIE_fastStart = (1 << 28), + eInformation_UUIE_fastConnectRefused = (1 << 27), + eInformation_UUIE_circuitInfo = (1 << 26), + } options; + Information_UUIE_fastStart fastStart; +} Information_UUIE; + +typedef struct FacilityReason { /* CHOICE */ + enum { + eFacilityReason_routeCallToGatekeeper, + eFacilityReason_callForwarded, + eFacilityReason_routeCallToMC, + eFacilityReason_undefinedReason, + eFacilityReason_conferenceListChoice, + eFacilityReason_startH245, + eFacilityReason_noH245, + eFacilityReason_newTokens, + eFacilityReason_featureSetUpdate, + eFacilityReason_forwardedElements, + eFacilityReason_transportedInformation, + } choice; +} FacilityReason; + +typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Facility_UUIE_fastStart; + +typedef struct Facility_UUIE { /* SEQUENCE */ + enum { + eFacility_UUIE_alternativeAddress = (1 << 31), + eFacility_UUIE_alternativeAliasAddress = (1 << 30), + eFacility_UUIE_conferenceID = (1 << 29), + eFacility_UUIE_callIdentifier = (1 << 28), + eFacility_UUIE_destExtraCallInfo = (1 << 27), + eFacility_UUIE_remoteExtensionAddress = (1 << 26), + eFacility_UUIE_tokens = (1 << 25), + eFacility_UUIE_cryptoTokens = (1 << 24), + eFacility_UUIE_conferences = (1 << 23), + eFacility_UUIE_h245Address = (1 << 22), + eFacility_UUIE_fastStart = (1 << 21), + eFacility_UUIE_multipleCalls = (1 << 20), + eFacility_UUIE_maintainConnection = (1 << 19), + eFacility_UUIE_fastConnectRefused = (1 << 18), + eFacility_UUIE_serviceControl = (1 << 17), + eFacility_UUIE_circuitInfo = (1 << 16), + eFacility_UUIE_featureSet = (1 << 15), + eFacility_UUIE_destinationInfo = (1 << 14), + eFacility_UUIE_h245SecurityMode = (1 << 13), + } options; + TransportAddress alternativeAddress; + FacilityReason reason; + TransportAddress h245Address; + Facility_UUIE_fastStart fastStart; +} Facility_UUIE; + +typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Progress_UUIE_fastStart; + +typedef struct Progress_UUIE { /* SEQUENCE */ + enum { + eProgress_UUIE_h245Address = (1 << 31), + eProgress_UUIE_h245SecurityMode = (1 << 30), + eProgress_UUIE_tokens = (1 << 29), + eProgress_UUIE_cryptoTokens = (1 << 28), + eProgress_UUIE_fastStart = (1 << 27), + eProgress_UUIE_multipleCalls = (1 << 26), + eProgress_UUIE_maintainConnection = (1 << 25), + eProgress_UUIE_fastConnectRefused = (1 << 24), + } options; + TransportAddress h245Address; + Progress_UUIE_fastStart fastStart; +} Progress_UUIE; + +typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ + enum { + eH323_UU_PDU_h323_message_body_setup, + eH323_UU_PDU_h323_message_body_callProceeding, + eH323_UU_PDU_h323_message_body_connect, + eH323_UU_PDU_h323_message_body_alerting, + eH323_UU_PDU_h323_message_body_information, + eH323_UU_PDU_h323_message_body_releaseComplete, + eH323_UU_PDU_h323_message_body_facility, + eH323_UU_PDU_h323_message_body_progress, + eH323_UU_PDU_h323_message_body_empty, + eH323_UU_PDU_h323_message_body_status, + eH323_UU_PDU_h323_message_body_statusInquiry, + eH323_UU_PDU_h323_message_body_setupAcknowledge, + eH323_UU_PDU_h323_message_body_notify, + } choice; + union { + Setup_UUIE setup; + CallProceeding_UUIE callProceeding; + Connect_UUIE connect; + Alerting_UUIE alerting; + Information_UUIE information; + Facility_UUIE facility; + Progress_UUIE progress; + }; +} H323_UU_PDU_h323_message_body; + +typedef struct RequestMessage { /* CHOICE */ + enum { + eRequestMessage_nonStandard, + eRequestMessage_masterSlaveDetermination, + eRequestMessage_terminalCapabilitySet, + eRequestMessage_openLogicalChannel, + eRequestMessage_closeLogicalChannel, + eRequestMessage_requestChannelClose, + eRequestMessage_multiplexEntrySend, + eRequestMessage_requestMultiplexEntry, + eRequestMessage_requestMode, + eRequestMessage_roundTripDelayRequest, + eRequestMessage_maintenanceLoopRequest, + eRequestMessage_communicationModeRequest, + eRequestMessage_conferenceRequest, + eRequestMessage_multilinkRequest, + eRequestMessage_logicalChannelRateRequest, + } choice; + union { + OpenLogicalChannel openLogicalChannel; + }; +} RequestMessage; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + = (1 << 30), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannelAck_reverseLogicalChannelParameters; + +typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), + eH2250LogicalChannelAckParameters_sessionID = (1 << 30), + eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelAckParameters_mediaControlChannel = + (1 << 28), + eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = + (1 << 27), + eH2250LogicalChannelAckParameters_flowControlToZero = + (1 << 26), + eH2250LogicalChannelAckParameters_portNumber = (1 << 25), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelAckParameters; + +typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, + } choice; + union { + H2250LogicalChannelAckParameters + h2250LogicalChannelAckParameters; + }; +} OpenLogicalChannelAck_forwardMultiplexAckParameters; + +typedef struct OpenLogicalChannelAck { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannelAck_separateStack = (1 << 30), + eOpenLogicalChannelAck_forwardMultiplexAckParameters = + (1 << 29), + eOpenLogicalChannelAck_encryptionSync = (1 << 28), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + OpenLogicalChannelAck_forwardMultiplexAckParameters + forwardMultiplexAckParameters; +} OpenLogicalChannelAck; + +typedef struct ResponseMessage { /* CHOICE */ + enum { + eResponseMessage_nonStandard, + eResponseMessage_masterSlaveDeterminationAck, + eResponseMessage_masterSlaveDeterminationReject, + eResponseMessage_terminalCapabilitySetAck, + eResponseMessage_terminalCapabilitySetReject, + eResponseMessage_openLogicalChannelAck, + eResponseMessage_openLogicalChannelReject, + eResponseMessage_closeLogicalChannelAck, + eResponseMessage_requestChannelCloseAck, + eResponseMessage_requestChannelCloseReject, + eResponseMessage_multiplexEntrySendAck, + eResponseMessage_multiplexEntrySendReject, + eResponseMessage_requestMultiplexEntryAck, + eResponseMessage_requestMultiplexEntryReject, + eResponseMessage_requestModeAck, + eResponseMessage_requestModeReject, + eResponseMessage_roundTripDelayResponse, + eResponseMessage_maintenanceLoopAck, + eResponseMessage_maintenanceLoopReject, + eResponseMessage_communicationModeResponse, + eResponseMessage_conferenceResponse, + eResponseMessage_multilinkResponse, + eResponseMessage_logicalChannelRateAcknowledge, + eResponseMessage_logicalChannelRateReject, + } choice; + union { + OpenLogicalChannelAck openLogicalChannelAck; + }; +} ResponseMessage; + +typedef struct MultimediaSystemControlMessage { /* CHOICE */ + enum { + eMultimediaSystemControlMessage_request, + eMultimediaSystemControlMessage_response, + eMultimediaSystemControlMessage_command, + eMultimediaSystemControlMessage_indication, + } choice; + union { + RequestMessage request; + ResponseMessage response; + }; +} MultimediaSystemControlMessage; + +typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ + int count; + MultimediaSystemControlMessage item[4]; +} H323_UU_PDU_h245Control; + +typedef struct H323_UU_PDU { /* SEQUENCE */ + enum { + eH323_UU_PDU_nonStandardData = (1 << 31), + eH323_UU_PDU_h4501SupplementaryService = (1 << 30), + eH323_UU_PDU_h245Tunneling = (1 << 29), + eH323_UU_PDU_h245Control = (1 << 28), + eH323_UU_PDU_nonStandardControl = (1 << 27), + eH323_UU_PDU_callLinkage = (1 << 26), + eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), + eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), + eH323_UU_PDU_stimulusControl = (1 << 23), + eH323_UU_PDU_genericData = (1 << 22), + } options; + H323_UU_PDU_h323_message_body h323_message_body; + H323_UU_PDU_h245Control h245Control; +} H323_UU_PDU; + +typedef struct H323_UserInformation { /* SEQUENCE */ + enum { + eH323_UserInformation_user_data = (1 << 31), + } options; + H323_UU_PDU h323_uu_pdu; +} H323_UserInformation; + +typedef struct GatekeeperRequest { /* SEQUENCE */ + enum { + eGatekeeperRequest_nonStandardData = (1 << 31), + eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), + eGatekeeperRequest_callServices = (1 << 29), + eGatekeeperRequest_endpointAlias = (1 << 28), + eGatekeeperRequest_alternateEndpoints = (1 << 27), + eGatekeeperRequest_tokens = (1 << 26), + eGatekeeperRequest_cryptoTokens = (1 << 25), + eGatekeeperRequest_authenticationCapability = (1 << 24), + eGatekeeperRequest_algorithmOIDs = (1 << 23), + eGatekeeperRequest_integrity = (1 << 22), + eGatekeeperRequest_integrityCheckValue = (1 << 21), + eGatekeeperRequest_supportsAltGK = (1 << 20), + eGatekeeperRequest_featureSet = (1 << 19), + eGatekeeperRequest_genericData = (1 << 18), + } options; + TransportAddress rasAddress; +} GatekeeperRequest; + +typedef struct GatekeeperConfirm { /* SEQUENCE */ + enum { + eGatekeeperConfirm_nonStandardData = (1 << 31), + eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), + eGatekeeperConfirm_alternateGatekeeper = (1 << 29), + eGatekeeperConfirm_authenticationMode = (1 << 28), + eGatekeeperConfirm_tokens = (1 << 27), + eGatekeeperConfirm_cryptoTokens = (1 << 26), + eGatekeeperConfirm_algorithmOID = (1 << 25), + eGatekeeperConfirm_integrity = (1 << 24), + eGatekeeperConfirm_integrityCheckValue = (1 << 23), + eGatekeeperConfirm_featureSet = (1 << 22), + eGatekeeperConfirm_genericData = (1 << 21), + } options; + TransportAddress rasAddress; +} GatekeeperConfirm; + +typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_callSignalAddress; + +typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_rasAddress; + +typedef struct RegistrationRequest { /* SEQUENCE */ + enum { + eRegistrationRequest_nonStandardData = (1 << 31), + eRegistrationRequest_terminalAlias = (1 << 30), + eRegistrationRequest_gatekeeperIdentifier = (1 << 29), + eRegistrationRequest_alternateEndpoints = (1 << 28), + eRegistrationRequest_timeToLive = (1 << 27), + eRegistrationRequest_tokens = (1 << 26), + eRegistrationRequest_cryptoTokens = (1 << 25), + eRegistrationRequest_integrityCheckValue = (1 << 24), + eRegistrationRequest_keepAlive = (1 << 23), + eRegistrationRequest_endpointIdentifier = (1 << 22), + eRegistrationRequest_willSupplyUUIEs = (1 << 21), + eRegistrationRequest_maintainConnection = (1 << 20), + eRegistrationRequest_alternateTransportAddresses = (1 << 19), + eRegistrationRequest_additiveRegistration = (1 << 18), + eRegistrationRequest_terminalAliasPattern = (1 << 17), + eRegistrationRequest_supportsAltGK = (1 << 16), + eRegistrationRequest_usageReportingCapability = (1 << 15), + eRegistrationRequest_multipleCalls = (1 << 14), + eRegistrationRequest_supportedH248Packages = (1 << 13), + eRegistrationRequest_callCreditCapability = (1 << 12), + eRegistrationRequest_capacityReportingCapability = (1 << 11), + eRegistrationRequest_capacity = (1 << 10), + eRegistrationRequest_featureSet = (1 << 9), + eRegistrationRequest_genericData = (1 << 8), + } options; + RegistrationRequest_callSignalAddress callSignalAddress; + RegistrationRequest_rasAddress rasAddress; + unsigned timeToLive; +} RegistrationRequest; + +typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationConfirm_callSignalAddress; + +typedef struct RegistrationConfirm { /* SEQUENCE */ + enum { + eRegistrationConfirm_nonStandardData = (1 << 31), + eRegistrationConfirm_terminalAlias = (1 << 30), + eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), + eRegistrationConfirm_alternateGatekeeper = (1 << 28), + eRegistrationConfirm_timeToLive = (1 << 27), + eRegistrationConfirm_tokens = (1 << 26), + eRegistrationConfirm_cryptoTokens = (1 << 25), + eRegistrationConfirm_integrityCheckValue = (1 << 24), + eRegistrationConfirm_willRespondToIRR = (1 << 23), + eRegistrationConfirm_preGrantedARQ = (1 << 22), + eRegistrationConfirm_maintainConnection = (1 << 21), + eRegistrationConfirm_serviceControl = (1 << 20), + eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), + eRegistrationConfirm_terminalAliasPattern = (1 << 18), + eRegistrationConfirm_supportedPrefixes = (1 << 17), + eRegistrationConfirm_usageSpec = (1 << 16), + eRegistrationConfirm_featureServerAlias = (1 << 15), + eRegistrationConfirm_capacityReportingSpec = (1 << 14), + eRegistrationConfirm_featureSet = (1 << 13), + eRegistrationConfirm_genericData = (1 << 12), + } options; + RegistrationConfirm_callSignalAddress callSignalAddress; + unsigned timeToLive; +} RegistrationConfirm; + +typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} UnregistrationRequest_callSignalAddress; + +typedef struct UnregistrationRequest { /* SEQUENCE */ + enum { + eUnregistrationRequest_endpointAlias = (1 << 31), + eUnregistrationRequest_nonStandardData = (1 << 30), + eUnregistrationRequest_endpointIdentifier = (1 << 29), + eUnregistrationRequest_alternateEndpoints = (1 << 28), + eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), + eUnregistrationRequest_tokens = (1 << 26), + eUnregistrationRequest_cryptoTokens = (1 << 25), + eUnregistrationRequest_integrityCheckValue = (1 << 24), + eUnregistrationRequest_reason = (1 << 23), + eUnregistrationRequest_endpointAliasPattern = (1 << 22), + eUnregistrationRequest_supportedPrefixes = (1 << 21), + eUnregistrationRequest_alternateGatekeeper = (1 << 20), + eUnregistrationRequest_genericData = (1 << 19), + } options; + UnregistrationRequest_callSignalAddress callSignalAddress; +} UnregistrationRequest; + +typedef struct AdmissionRequest { /* SEQUENCE */ + enum { + eAdmissionRequest_callModel = (1 << 31), + eAdmissionRequest_destinationInfo = (1 << 30), + eAdmissionRequest_destCallSignalAddress = (1 << 29), + eAdmissionRequest_destExtraCallInfo = (1 << 28), + eAdmissionRequest_srcCallSignalAddress = (1 << 27), + eAdmissionRequest_nonStandardData = (1 << 26), + eAdmissionRequest_callServices = (1 << 25), + eAdmissionRequest_canMapAlias = (1 << 24), + eAdmissionRequest_callIdentifier = (1 << 23), + eAdmissionRequest_srcAlternatives = (1 << 22), + eAdmissionRequest_destAlternatives = (1 << 21), + eAdmissionRequest_gatekeeperIdentifier = (1 << 20), + eAdmissionRequest_tokens = (1 << 19), + eAdmissionRequest_cryptoTokens = (1 << 18), + eAdmissionRequest_integrityCheckValue = (1 << 17), + eAdmissionRequest_transportQOS = (1 << 16), + eAdmissionRequest_willSupplyUUIEs = (1 << 15), + eAdmissionRequest_callLinkage = (1 << 14), + eAdmissionRequest_gatewayDataRate = (1 << 13), + eAdmissionRequest_capacity = (1 << 12), + eAdmissionRequest_circuitInfo = (1 << 11), + eAdmissionRequest_desiredProtocols = (1 << 10), + eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), + eAdmissionRequest_featureSet = (1 << 8), + eAdmissionRequest_genericData = (1 << 7), + } options; + TransportAddress destCallSignalAddress; + TransportAddress srcCallSignalAddress; +} AdmissionRequest; + +typedef struct AdmissionConfirm { /* SEQUENCE */ + enum { + eAdmissionConfirm_irrFrequency = (1 << 31), + eAdmissionConfirm_nonStandardData = (1 << 30), + eAdmissionConfirm_destinationInfo = (1 << 29), + eAdmissionConfirm_destExtraCallInfo = (1 << 28), + eAdmissionConfirm_destinationType = (1 << 27), + eAdmissionConfirm_remoteExtensionAddress = (1 << 26), + eAdmissionConfirm_alternateEndpoints = (1 << 25), + eAdmissionConfirm_tokens = (1 << 24), + eAdmissionConfirm_cryptoTokens = (1 << 23), + eAdmissionConfirm_integrityCheckValue = (1 << 22), + eAdmissionConfirm_transportQOS = (1 << 21), + eAdmissionConfirm_willRespondToIRR = (1 << 20), + eAdmissionConfirm_uuiesRequested = (1 << 19), + eAdmissionConfirm_language = (1 << 18), + eAdmissionConfirm_alternateTransportAddresses = (1 << 17), + eAdmissionConfirm_useSpecifiedTransport = (1 << 16), + eAdmissionConfirm_circuitInfo = (1 << 15), + eAdmissionConfirm_usageSpec = (1 << 14), + eAdmissionConfirm_supportedProtocols = (1 << 13), + eAdmissionConfirm_serviceControl = (1 << 12), + eAdmissionConfirm_multipleCalls = (1 << 11), + eAdmissionConfirm_featureSet = (1 << 10), + eAdmissionConfirm_genericData = (1 << 9), + } options; + TransportAddress destCallSignalAddress; +} AdmissionConfirm; + +typedef struct LocationRequest { /* SEQUENCE */ + enum { + eLocationRequest_endpointIdentifier = (1 << 31), + eLocationRequest_nonStandardData = (1 << 30), + eLocationRequest_sourceInfo = (1 << 29), + eLocationRequest_canMapAlias = (1 << 28), + eLocationRequest_gatekeeperIdentifier = (1 << 27), + eLocationRequest_tokens = (1 << 26), + eLocationRequest_cryptoTokens = (1 << 25), + eLocationRequest_integrityCheckValue = (1 << 24), + eLocationRequest_desiredProtocols = (1 << 23), + eLocationRequest_desiredTunnelledProtocol = (1 << 22), + eLocationRequest_featureSet = (1 << 21), + eLocationRequest_genericData = (1 << 20), + eLocationRequest_hopCount = (1 << 19), + eLocationRequest_circuitInfo = (1 << 18), + } options; + TransportAddress replyAddress; +} LocationRequest; + +typedef struct LocationConfirm { /* SEQUENCE */ + enum { + eLocationConfirm_nonStandardData = (1 << 31), + eLocationConfirm_destinationInfo = (1 << 30), + eLocationConfirm_destExtraCallInfo = (1 << 29), + eLocationConfirm_destinationType = (1 << 28), + eLocationConfirm_remoteExtensionAddress = (1 << 27), + eLocationConfirm_alternateEndpoints = (1 << 26), + eLocationConfirm_tokens = (1 << 25), + eLocationConfirm_cryptoTokens = (1 << 24), + eLocationConfirm_integrityCheckValue = (1 << 23), + eLocationConfirm_alternateTransportAddresses = (1 << 22), + eLocationConfirm_supportedProtocols = (1 << 21), + eLocationConfirm_multipleCalls = (1 << 20), + eLocationConfirm_featureSet = (1 << 19), + eLocationConfirm_genericData = (1 << 18), + eLocationConfirm_circuitInfo = (1 << 17), + eLocationConfirm_serviceControl = (1 << 16), + } options; + TransportAddress callSignalAddress; + TransportAddress rasAddress; +} LocationConfirm; + +typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} InfoRequestResponse_callSignalAddress; + +typedef struct InfoRequestResponse { /* SEQUENCE */ + enum { + eInfoRequestResponse_nonStandardData = (1 << 31), + eInfoRequestResponse_endpointAlias = (1 << 30), + eInfoRequestResponse_perCallInfo = (1 << 29), + eInfoRequestResponse_tokens = (1 << 28), + eInfoRequestResponse_cryptoTokens = (1 << 27), + eInfoRequestResponse_integrityCheckValue = (1 << 26), + eInfoRequestResponse_needResponse = (1 << 25), + eInfoRequestResponse_capacity = (1 << 24), + eInfoRequestResponse_irrStatus = (1 << 23), + eInfoRequestResponse_unsolicited = (1 << 22), + eInfoRequestResponse_genericData = (1 << 21), + } options; + TransportAddress rasAddress; + InfoRequestResponse_callSignalAddress callSignalAddress; +} InfoRequestResponse; + +typedef struct RasMessage { /* CHOICE */ + enum { + eRasMessage_gatekeeperRequest, + eRasMessage_gatekeeperConfirm, + eRasMessage_gatekeeperReject, + eRasMessage_registrationRequest, + eRasMessage_registrationConfirm, + eRasMessage_registrationReject, + eRasMessage_unregistrationRequest, + eRasMessage_unregistrationConfirm, + eRasMessage_unregistrationReject, + eRasMessage_admissionRequest, + eRasMessage_admissionConfirm, + eRasMessage_admissionReject, + eRasMessage_bandwidthRequest, + eRasMessage_bandwidthConfirm, + eRasMessage_bandwidthReject, + eRasMessage_disengageRequest, + eRasMessage_disengageConfirm, + eRasMessage_disengageReject, + eRasMessage_locationRequest, + eRasMessage_locationConfirm, + eRasMessage_locationReject, + eRasMessage_infoRequest, + eRasMessage_infoRequestResponse, + eRasMessage_nonStandardMessage, + eRasMessage_unknownMessageResponse, + eRasMessage_requestInProgress, + eRasMessage_resourcesAvailableIndicate, + eRasMessage_resourcesAvailableConfirm, + eRasMessage_infoRequestAck, + eRasMessage_infoRequestNak, + eRasMessage_serviceControlIndication, + eRasMessage_serviceControlResponse, + } choice; + union { + GatekeeperRequest gatekeeperRequest; + GatekeeperConfirm gatekeeperConfirm; + RegistrationRequest registrationRequest; + RegistrationConfirm registrationConfirm; + UnregistrationRequest unregistrationRequest; + AdmissionRequest admissionRequest; + AdmissionConfirm admissionConfirm; + LocationRequest locationRequest; + LocationConfirm locationConfirm; + InfoRequestResponse infoRequestResponse; + }; +} RasMessage; diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild index 591c1a809c00..180337801a86 100644 --- a/include/linux/netfilter_ipv4/Kbuild +++ b/include/linux/netfilter_ipv4/Kbuild @@ -1,6 +1,4 @@ header-y += ip_conntrack_helper.h -header-y += ip_conntrack_helper_h323_asn1.h -header-y += ip_conntrack_helper_h323_types.h header-y += ip_conntrack_protocol.h header-y += ip_conntrack_sctp.h header-y += ip_conntrack_tcp.h diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h index 943cc6a4871d..18f769818f4e 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h @@ -3,7 +3,7 @@ #ifdef __KERNEL__ -#include +#include #define RAS_PORT 1719 #define Q931_PORT 1720 diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h deleted file mode 100644 index c6e9a0b6d30b..000000000000 --- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** - * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 - * conntrack/NAT module. - * - * Copyright (c) 2006 by Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - * - * - * This library is based on H.225 version 4, H.235 version 2 and H.245 - * version 7. It is extremely optimized to decode only the absolutely - * necessary objects in a signal for Linux kernel NAT module use, so don't - * expect it to be a full ASN.1 library. - * - * Features: - * - * 1. Small. The total size of code plus data is less than 20 KB (IA32). - * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 - * takes only 3.9 seconds. - * 3. No memory allocation. It uses a static object. No need to initialize or - * cleanup. - * 4. Thread safe. - * 5. Support embedded architectures that has no misaligned memory access - * support. - * - * Limitations: - * - * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. - * If a Setup signal contains more than 30 faststart, the packet size will - * very likely exceed the MTU size, then the TPKT will be fragmented. I - * don't know how to handle this in a Netfilter module. Anybody can help? - * Although I think 30 is enough for most of the cases. - * 2. IPv4 addresses only. - * - ****************************************************************************/ - -#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ -#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ - -/***************************************************************************** - * H.323 Types - ****************************************************************************/ -#include "ip_conntrack_helper_h323_types.h" - -typedef struct { - enum { - Q931_NationalEscape = 0x00, - Q931_Alerting = 0x01, - Q931_CallProceeding = 0x02, - Q931_Connect = 0x07, - Q931_ConnectAck = 0x0F, - Q931_Progress = 0x03, - Q931_Setup = 0x05, - Q931_SetupAck = 0x0D, - Q931_Resume = 0x26, - Q931_ResumeAck = 0x2E, - Q931_ResumeReject = 0x22, - Q931_Suspend = 0x25, - Q931_SuspendAck = 0x2D, - Q931_SuspendReject = 0x21, - Q931_UserInformation = 0x20, - Q931_Disconnect = 0x45, - Q931_Release = 0x4D, - Q931_ReleaseComplete = 0x5A, - Q931_Restart = 0x46, - Q931_RestartAck = 0x4E, - Q931_Segment = 0x60, - Q931_CongestionCtrl = 0x79, - Q931_Information = 0x7B, - Q931_Notify = 0x6E, - Q931_Status = 0x7D, - Q931_StatusEnquiry = 0x75, - Q931_Facility = 0x62 - } MessageType; - H323_UserInformation UUIE; -} Q931; - -/***************************************************************************** - * Decode Functions Return Codes - ****************************************************************************/ - -#define H323_ERROR_NONE 0 /* Decoded successfully */ -#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ -#define H323_ERROR_BOUND -1 -#define H323_ERROR_RANGE -2 - - -/***************************************************************************** - * Decode Functions - ****************************************************************************/ - -int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); -int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); -int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, - MultimediaSystemControlMessage * - mscm); - -#endif diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h deleted file mode 100644 index 3d4a773799fc..000000000000 --- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h +++ /dev/null @@ -1,939 +0,0 @@ -/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006 - * - * Copyright (c) 2006 Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - */ - -typedef struct TransportAddress_ipAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned ip; -} TransportAddress_ipAddress; - -typedef struct TransportAddress { /* CHOICE */ - enum { - eTransportAddress_ipAddress, - eTransportAddress_ipSourceRoute, - eTransportAddress_ipxAddress, - eTransportAddress_ip6Address, - eTransportAddress_netBios, - eTransportAddress_nsap, - eTransportAddress_nonStandardAddress, - } choice; - union { - TransportAddress_ipAddress ipAddress; - }; -} TransportAddress; - -typedef struct DataProtocolCapability { /* CHOICE */ - enum { - eDataProtocolCapability_nonStandard, - eDataProtocolCapability_v14buffered, - eDataProtocolCapability_v42lapm, - eDataProtocolCapability_hdlcFrameTunnelling, - eDataProtocolCapability_h310SeparateVCStack, - eDataProtocolCapability_h310SingleVCStack, - eDataProtocolCapability_transparent, - eDataProtocolCapability_segmentationAndReassembly, - eDataProtocolCapability_hdlcFrameTunnelingwSAR, - eDataProtocolCapability_v120, - eDataProtocolCapability_separateLANStack, - eDataProtocolCapability_v76wCompression, - eDataProtocolCapability_tcp, - eDataProtocolCapability_udp, - } choice; -} DataProtocolCapability; - -typedef struct DataApplicationCapability_application { /* CHOICE */ - enum { - eDataApplicationCapability_application_nonStandard, - eDataApplicationCapability_application_t120, - eDataApplicationCapability_application_dsm_cc, - eDataApplicationCapability_application_userData, - eDataApplicationCapability_application_t84, - eDataApplicationCapability_application_t434, - eDataApplicationCapability_application_h224, - eDataApplicationCapability_application_nlpid, - eDataApplicationCapability_application_dsvdControl, - eDataApplicationCapability_application_h222DataPartitioning, - eDataApplicationCapability_application_t30fax, - eDataApplicationCapability_application_t140, - eDataApplicationCapability_application_t38fax, - eDataApplicationCapability_application_genericDataCapability, - } choice; - union { - DataProtocolCapability t120; - }; -} DataApplicationCapability_application; - -typedef struct DataApplicationCapability { /* SEQUENCE */ - int options; /* No use */ - DataApplicationCapability_application application; -} DataApplicationCapability; - -typedef struct DataType { /* CHOICE */ - enum { - eDataType_nonStandard, - eDataType_nullData, - eDataType_videoData, - eDataType_audioData, - eDataType_data, - eDataType_encryptionData, - eDataType_h235Control, - eDataType_h235Media, - eDataType_multiplexedStream, - } choice; - union { - DataApplicationCapability data; - }; -} DataType; - -typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned network; -} UnicastAddress_iPAddress; - -typedef struct UnicastAddress { /* CHOICE */ - enum { - eUnicastAddress_iPAddress, - eUnicastAddress_iPXAddress, - eUnicastAddress_iP6Address, - eUnicastAddress_netBios, - eUnicastAddress_iPSourceRouteAddress, - eUnicastAddress_nsap, - eUnicastAddress_nonStandardAddress, - } choice; - union { - UnicastAddress_iPAddress iPAddress; - }; -} UnicastAddress; - -typedef struct H245_TransportAddress { /* CHOICE */ - enum { - eH245_TransportAddress_unicastAddress, - eH245_TransportAddress_multicastAddress, - } choice; - union { - UnicastAddress unicastAddress; - }; -} H245_TransportAddress; - -typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelParameters_nonStandard = (1 << 31), - eH2250LogicalChannelParameters_associatedSessionID = - (1 << 30), - eH2250LogicalChannelParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelParameters_mediaGuaranteedDelivery = - (1 << 28), - eH2250LogicalChannelParameters_mediaControlChannel = - (1 << 27), - eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery - = (1 << 26), - eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), - eH2250LogicalChannelParameters_destination = (1 << 24), - eH2250LogicalChannelParameters_dynamicRTPPayloadType = - (1 << 23), - eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), - eH2250LogicalChannelParameters_transportCapability = - (1 << 21), - eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), - eH2250LogicalChannelParameters_source = (1 << 19), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - DataType dataType; - OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_forwardLogicalChannelParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - = (1 << 31), - eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_reverseLogicalChannelParameters; - -typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ - enum { - eNetworkAccessParameters_networkAddress_q2931Address, - eNetworkAccessParameters_networkAddress_e164Address, - eNetworkAccessParameters_networkAddress_localAreaAddress, - } choice; - union { - H245_TransportAddress localAreaAddress; - }; -} NetworkAccessParameters_networkAddress; - -typedef struct NetworkAccessParameters { /* SEQUENCE */ - enum { - eNetworkAccessParameters_distribution = (1 << 31), - eNetworkAccessParameters_externalReference = (1 << 30), - eNetworkAccessParameters_t120SetupProcedure = (1 << 29), - } options; - NetworkAccessParameters_networkAddress networkAddress; -} NetworkAccessParameters; - -typedef struct OpenLogicalChannel { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannel_separateStack = (1 << 30), - eOpenLogicalChannel_encryptionSync = (1 << 29), - } options; - OpenLogicalChannel_forwardLogicalChannelParameters - forwardLogicalChannelParameters; - OpenLogicalChannel_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - NetworkAccessParameters separateStack; -} OpenLogicalChannel; - -typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Setup_UUIE_fastStart; - -typedef struct Setup_UUIE { /* SEQUENCE */ - enum { - eSetup_UUIE_h245Address = (1 << 31), - eSetup_UUIE_sourceAddress = (1 << 30), - eSetup_UUIE_destinationAddress = (1 << 29), - eSetup_UUIE_destCallSignalAddress = (1 << 28), - eSetup_UUIE_destExtraCallInfo = (1 << 27), - eSetup_UUIE_destExtraCRV = (1 << 26), - eSetup_UUIE_callServices = (1 << 25), - eSetup_UUIE_sourceCallSignalAddress = (1 << 24), - eSetup_UUIE_remoteExtensionAddress = (1 << 23), - eSetup_UUIE_callIdentifier = (1 << 22), - eSetup_UUIE_h245SecurityCapability = (1 << 21), - eSetup_UUIE_tokens = (1 << 20), - eSetup_UUIE_cryptoTokens = (1 << 19), - eSetup_UUIE_fastStart = (1 << 18), - eSetup_UUIE_mediaWaitForConnect = (1 << 17), - eSetup_UUIE_canOverlapSend = (1 << 16), - eSetup_UUIE_endpointIdentifier = (1 << 15), - eSetup_UUIE_multipleCalls = (1 << 14), - eSetup_UUIE_maintainConnection = (1 << 13), - eSetup_UUIE_connectionParameters = (1 << 12), - eSetup_UUIE_language = (1 << 11), - eSetup_UUIE_presentationIndicator = (1 << 10), - eSetup_UUIE_screeningIndicator = (1 << 9), - eSetup_UUIE_serviceControl = (1 << 8), - eSetup_UUIE_symmetricOperationRequired = (1 << 7), - eSetup_UUIE_capacity = (1 << 6), - eSetup_UUIE_circuitInfo = (1 << 5), - eSetup_UUIE_desiredProtocols = (1 << 4), - eSetup_UUIE_neededFeatures = (1 << 3), - eSetup_UUIE_desiredFeatures = (1 << 2), - eSetup_UUIE_supportedFeatures = (1 << 1), - eSetup_UUIE_parallelH245Control = (1 << 0), - } options; - TransportAddress h245Address; - TransportAddress destCallSignalAddress; - TransportAddress sourceCallSignalAddress; - Setup_UUIE_fastStart fastStart; -} Setup_UUIE; - -typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} CallProceeding_UUIE_fastStart; - -typedef struct CallProceeding_UUIE { /* SEQUENCE */ - enum { - eCallProceeding_UUIE_h245Address = (1 << 31), - eCallProceeding_UUIE_callIdentifier = (1 << 30), - eCallProceeding_UUIE_h245SecurityMode = (1 << 29), - eCallProceeding_UUIE_tokens = (1 << 28), - eCallProceeding_UUIE_cryptoTokens = (1 << 27), - eCallProceeding_UUIE_fastStart = (1 << 26), - eCallProceeding_UUIE_multipleCalls = (1 << 25), - eCallProceeding_UUIE_maintainConnection = (1 << 24), - eCallProceeding_UUIE_fastConnectRefused = (1 << 23), - eCallProceeding_UUIE_featureSet = (1 << 22), - } options; - TransportAddress h245Address; - CallProceeding_UUIE_fastStart fastStart; -} CallProceeding_UUIE; - -typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Connect_UUIE_fastStart; - -typedef struct Connect_UUIE { /* SEQUENCE */ - enum { - eConnect_UUIE_h245Address = (1 << 31), - eConnect_UUIE_callIdentifier = (1 << 30), - eConnect_UUIE_h245SecurityMode = (1 << 29), - eConnect_UUIE_tokens = (1 << 28), - eConnect_UUIE_cryptoTokens = (1 << 27), - eConnect_UUIE_fastStart = (1 << 26), - eConnect_UUIE_multipleCalls = (1 << 25), - eConnect_UUIE_maintainConnection = (1 << 24), - eConnect_UUIE_language = (1 << 23), - eConnect_UUIE_connectedAddress = (1 << 22), - eConnect_UUIE_presentationIndicator = (1 << 21), - eConnect_UUIE_screeningIndicator = (1 << 20), - eConnect_UUIE_fastConnectRefused = (1 << 19), - eConnect_UUIE_serviceControl = (1 << 18), - eConnect_UUIE_capacity = (1 << 17), - eConnect_UUIE_featureSet = (1 << 16), - } options; - TransportAddress h245Address; - Connect_UUIE_fastStart fastStart; -} Connect_UUIE; - -typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Alerting_UUIE_fastStart; - -typedef struct Alerting_UUIE { /* SEQUENCE */ - enum { - eAlerting_UUIE_h245Address = (1 << 31), - eAlerting_UUIE_callIdentifier = (1 << 30), - eAlerting_UUIE_h245SecurityMode = (1 << 29), - eAlerting_UUIE_tokens = (1 << 28), - eAlerting_UUIE_cryptoTokens = (1 << 27), - eAlerting_UUIE_fastStart = (1 << 26), - eAlerting_UUIE_multipleCalls = (1 << 25), - eAlerting_UUIE_maintainConnection = (1 << 24), - eAlerting_UUIE_alertingAddress = (1 << 23), - eAlerting_UUIE_presentationIndicator = (1 << 22), - eAlerting_UUIE_screeningIndicator = (1 << 21), - eAlerting_UUIE_fastConnectRefused = (1 << 20), - eAlerting_UUIE_serviceControl = (1 << 19), - eAlerting_UUIE_capacity = (1 << 18), - eAlerting_UUIE_featureSet = (1 << 17), - } options; - TransportAddress h245Address; - Alerting_UUIE_fastStart fastStart; -} Alerting_UUIE; - -typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Information_UUIE_fastStart; - -typedef struct Information_UUIE { /* SEQUENCE */ - enum { - eInformation_UUIE_callIdentifier = (1 << 31), - eInformation_UUIE_tokens = (1 << 30), - eInformation_UUIE_cryptoTokens = (1 << 29), - eInformation_UUIE_fastStart = (1 << 28), - eInformation_UUIE_fastConnectRefused = (1 << 27), - eInformation_UUIE_circuitInfo = (1 << 26), - } options; - Information_UUIE_fastStart fastStart; -} Information_UUIE; - -typedef struct FacilityReason { /* CHOICE */ - enum { - eFacilityReason_routeCallToGatekeeper, - eFacilityReason_callForwarded, - eFacilityReason_routeCallToMC, - eFacilityReason_undefinedReason, - eFacilityReason_conferenceListChoice, - eFacilityReason_startH245, - eFacilityReason_noH245, - eFacilityReason_newTokens, - eFacilityReason_featureSetUpdate, - eFacilityReason_forwardedElements, - eFacilityReason_transportedInformation, - } choice; -} FacilityReason; - -typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Facility_UUIE_fastStart; - -typedef struct Facility_UUIE { /* SEQUENCE */ - enum { - eFacility_UUIE_alternativeAddress = (1 << 31), - eFacility_UUIE_alternativeAliasAddress = (1 << 30), - eFacility_UUIE_conferenceID = (1 << 29), - eFacility_UUIE_callIdentifier = (1 << 28), - eFacility_UUIE_destExtraCallInfo = (1 << 27), - eFacility_UUIE_remoteExtensionAddress = (1 << 26), - eFacility_UUIE_tokens = (1 << 25), - eFacility_UUIE_cryptoTokens = (1 << 24), - eFacility_UUIE_conferences = (1 << 23), - eFacility_UUIE_h245Address = (1 << 22), - eFacility_UUIE_fastStart = (1 << 21), - eFacility_UUIE_multipleCalls = (1 << 20), - eFacility_UUIE_maintainConnection = (1 << 19), - eFacility_UUIE_fastConnectRefused = (1 << 18), - eFacility_UUIE_serviceControl = (1 << 17), - eFacility_UUIE_circuitInfo = (1 << 16), - eFacility_UUIE_featureSet = (1 << 15), - eFacility_UUIE_destinationInfo = (1 << 14), - eFacility_UUIE_h245SecurityMode = (1 << 13), - } options; - TransportAddress alternativeAddress; - FacilityReason reason; - TransportAddress h245Address; - Facility_UUIE_fastStart fastStart; -} Facility_UUIE; - -typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Progress_UUIE_fastStart; - -typedef struct Progress_UUIE { /* SEQUENCE */ - enum { - eProgress_UUIE_h245Address = (1 << 31), - eProgress_UUIE_h245SecurityMode = (1 << 30), - eProgress_UUIE_tokens = (1 << 29), - eProgress_UUIE_cryptoTokens = (1 << 28), - eProgress_UUIE_fastStart = (1 << 27), - eProgress_UUIE_multipleCalls = (1 << 26), - eProgress_UUIE_maintainConnection = (1 << 25), - eProgress_UUIE_fastConnectRefused = (1 << 24), - } options; - TransportAddress h245Address; - Progress_UUIE_fastStart fastStart; -} Progress_UUIE; - -typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ - enum { - eH323_UU_PDU_h323_message_body_setup, - eH323_UU_PDU_h323_message_body_callProceeding, - eH323_UU_PDU_h323_message_body_connect, - eH323_UU_PDU_h323_message_body_alerting, - eH323_UU_PDU_h323_message_body_information, - eH323_UU_PDU_h323_message_body_releaseComplete, - eH323_UU_PDU_h323_message_body_facility, - eH323_UU_PDU_h323_message_body_progress, - eH323_UU_PDU_h323_message_body_empty, - eH323_UU_PDU_h323_message_body_status, - eH323_UU_PDU_h323_message_body_statusInquiry, - eH323_UU_PDU_h323_message_body_setupAcknowledge, - eH323_UU_PDU_h323_message_body_notify, - } choice; - union { - Setup_UUIE setup; - CallProceeding_UUIE callProceeding; - Connect_UUIE connect; - Alerting_UUIE alerting; - Information_UUIE information; - Facility_UUIE facility; - Progress_UUIE progress; - }; -} H323_UU_PDU_h323_message_body; - -typedef struct RequestMessage { /* CHOICE */ - enum { - eRequestMessage_nonStandard, - eRequestMessage_masterSlaveDetermination, - eRequestMessage_terminalCapabilitySet, - eRequestMessage_openLogicalChannel, - eRequestMessage_closeLogicalChannel, - eRequestMessage_requestChannelClose, - eRequestMessage_multiplexEntrySend, - eRequestMessage_requestMultiplexEntry, - eRequestMessage_requestMode, - eRequestMessage_roundTripDelayRequest, - eRequestMessage_maintenanceLoopRequest, - eRequestMessage_communicationModeRequest, - eRequestMessage_conferenceRequest, - eRequestMessage_multilinkRequest, - eRequestMessage_logicalChannelRateRequest, - } choice; - union { - OpenLogicalChannel openLogicalChannel; - }; -} RequestMessage; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - = (1 << 30), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannelAck_reverseLogicalChannelParameters; - -typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), - eH2250LogicalChannelAckParameters_sessionID = (1 << 30), - eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelAckParameters_mediaControlChannel = - (1 << 28), - eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = - (1 << 27), - eH2250LogicalChannelAckParameters_flowControlToZero = - (1 << 26), - eH2250LogicalChannelAckParameters_portNumber = (1 << 25), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelAckParameters; - -typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, - } choice; - union { - H2250LogicalChannelAckParameters - h2250LogicalChannelAckParameters; - }; -} OpenLogicalChannelAck_forwardMultiplexAckParameters; - -typedef struct OpenLogicalChannelAck { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannelAck_separateStack = (1 << 30), - eOpenLogicalChannelAck_forwardMultiplexAckParameters = - (1 << 29), - eOpenLogicalChannelAck_encryptionSync = (1 << 28), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - OpenLogicalChannelAck_forwardMultiplexAckParameters - forwardMultiplexAckParameters; -} OpenLogicalChannelAck; - -typedef struct ResponseMessage { /* CHOICE */ - enum { - eResponseMessage_nonStandard, - eResponseMessage_masterSlaveDeterminationAck, - eResponseMessage_masterSlaveDeterminationReject, - eResponseMessage_terminalCapabilitySetAck, - eResponseMessage_terminalCapabilitySetReject, - eResponseMessage_openLogicalChannelAck, - eResponseMessage_openLogicalChannelReject, - eResponseMessage_closeLogicalChannelAck, - eResponseMessage_requestChannelCloseAck, - eResponseMessage_requestChannelCloseReject, - eResponseMessage_multiplexEntrySendAck, - eResponseMessage_multiplexEntrySendReject, - eResponseMessage_requestMultiplexEntryAck, - eResponseMessage_requestMultiplexEntryReject, - eResponseMessage_requestModeAck, - eResponseMessage_requestModeReject, - eResponseMessage_roundTripDelayResponse, - eResponseMessage_maintenanceLoopAck, - eResponseMessage_maintenanceLoopReject, - eResponseMessage_communicationModeResponse, - eResponseMessage_conferenceResponse, - eResponseMessage_multilinkResponse, - eResponseMessage_logicalChannelRateAcknowledge, - eResponseMessage_logicalChannelRateReject, - } choice; - union { - OpenLogicalChannelAck openLogicalChannelAck; - }; -} ResponseMessage; - -typedef struct MultimediaSystemControlMessage { /* CHOICE */ - enum { - eMultimediaSystemControlMessage_request, - eMultimediaSystemControlMessage_response, - eMultimediaSystemControlMessage_command, - eMultimediaSystemControlMessage_indication, - } choice; - union { - RequestMessage request; - ResponseMessage response; - }; -} MultimediaSystemControlMessage; - -typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ - int count; - MultimediaSystemControlMessage item[4]; -} H323_UU_PDU_h245Control; - -typedef struct H323_UU_PDU { /* SEQUENCE */ - enum { - eH323_UU_PDU_nonStandardData = (1 << 31), - eH323_UU_PDU_h4501SupplementaryService = (1 << 30), - eH323_UU_PDU_h245Tunneling = (1 << 29), - eH323_UU_PDU_h245Control = (1 << 28), - eH323_UU_PDU_nonStandardControl = (1 << 27), - eH323_UU_PDU_callLinkage = (1 << 26), - eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), - eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), - eH323_UU_PDU_stimulusControl = (1 << 23), - eH323_UU_PDU_genericData = (1 << 22), - } options; - H323_UU_PDU_h323_message_body h323_message_body; - H323_UU_PDU_h245Control h245Control; -} H323_UU_PDU; - -typedef struct H323_UserInformation { /* SEQUENCE */ - enum { - eH323_UserInformation_user_data = (1 << 31), - } options; - H323_UU_PDU h323_uu_pdu; -} H323_UserInformation; - -typedef struct GatekeeperRequest { /* SEQUENCE */ - enum { - eGatekeeperRequest_nonStandardData = (1 << 31), - eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), - eGatekeeperRequest_callServices = (1 << 29), - eGatekeeperRequest_endpointAlias = (1 << 28), - eGatekeeperRequest_alternateEndpoints = (1 << 27), - eGatekeeperRequest_tokens = (1 << 26), - eGatekeeperRequest_cryptoTokens = (1 << 25), - eGatekeeperRequest_authenticationCapability = (1 << 24), - eGatekeeperRequest_algorithmOIDs = (1 << 23), - eGatekeeperRequest_integrity = (1 << 22), - eGatekeeperRequest_integrityCheckValue = (1 << 21), - eGatekeeperRequest_supportsAltGK = (1 << 20), - eGatekeeperRequest_featureSet = (1 << 19), - eGatekeeperRequest_genericData = (1 << 18), - } options; - TransportAddress rasAddress; -} GatekeeperRequest; - -typedef struct GatekeeperConfirm { /* SEQUENCE */ - enum { - eGatekeeperConfirm_nonStandardData = (1 << 31), - eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), - eGatekeeperConfirm_alternateGatekeeper = (1 << 29), - eGatekeeperConfirm_authenticationMode = (1 << 28), - eGatekeeperConfirm_tokens = (1 << 27), - eGatekeeperConfirm_cryptoTokens = (1 << 26), - eGatekeeperConfirm_algorithmOID = (1 << 25), - eGatekeeperConfirm_integrity = (1 << 24), - eGatekeeperConfirm_integrityCheckValue = (1 << 23), - eGatekeeperConfirm_featureSet = (1 << 22), - eGatekeeperConfirm_genericData = (1 << 21), - } options; - TransportAddress rasAddress; -} GatekeeperConfirm; - -typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_callSignalAddress; - -typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_rasAddress; - -typedef struct RegistrationRequest { /* SEQUENCE */ - enum { - eRegistrationRequest_nonStandardData = (1 << 31), - eRegistrationRequest_terminalAlias = (1 << 30), - eRegistrationRequest_gatekeeperIdentifier = (1 << 29), - eRegistrationRequest_alternateEndpoints = (1 << 28), - eRegistrationRequest_timeToLive = (1 << 27), - eRegistrationRequest_tokens = (1 << 26), - eRegistrationRequest_cryptoTokens = (1 << 25), - eRegistrationRequest_integrityCheckValue = (1 << 24), - eRegistrationRequest_keepAlive = (1 << 23), - eRegistrationRequest_endpointIdentifier = (1 << 22), - eRegistrationRequest_willSupplyUUIEs = (1 << 21), - eRegistrationRequest_maintainConnection = (1 << 20), - eRegistrationRequest_alternateTransportAddresses = (1 << 19), - eRegistrationRequest_additiveRegistration = (1 << 18), - eRegistrationRequest_terminalAliasPattern = (1 << 17), - eRegistrationRequest_supportsAltGK = (1 << 16), - eRegistrationRequest_usageReportingCapability = (1 << 15), - eRegistrationRequest_multipleCalls = (1 << 14), - eRegistrationRequest_supportedH248Packages = (1 << 13), - eRegistrationRequest_callCreditCapability = (1 << 12), - eRegistrationRequest_capacityReportingCapability = (1 << 11), - eRegistrationRequest_capacity = (1 << 10), - eRegistrationRequest_featureSet = (1 << 9), - eRegistrationRequest_genericData = (1 << 8), - } options; - RegistrationRequest_callSignalAddress callSignalAddress; - RegistrationRequest_rasAddress rasAddress; - unsigned timeToLive; -} RegistrationRequest; - -typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationConfirm_callSignalAddress; - -typedef struct RegistrationConfirm { /* SEQUENCE */ - enum { - eRegistrationConfirm_nonStandardData = (1 << 31), - eRegistrationConfirm_terminalAlias = (1 << 30), - eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), - eRegistrationConfirm_alternateGatekeeper = (1 << 28), - eRegistrationConfirm_timeToLive = (1 << 27), - eRegistrationConfirm_tokens = (1 << 26), - eRegistrationConfirm_cryptoTokens = (1 << 25), - eRegistrationConfirm_integrityCheckValue = (1 << 24), - eRegistrationConfirm_willRespondToIRR = (1 << 23), - eRegistrationConfirm_preGrantedARQ = (1 << 22), - eRegistrationConfirm_maintainConnection = (1 << 21), - eRegistrationConfirm_serviceControl = (1 << 20), - eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), - eRegistrationConfirm_terminalAliasPattern = (1 << 18), - eRegistrationConfirm_supportedPrefixes = (1 << 17), - eRegistrationConfirm_usageSpec = (1 << 16), - eRegistrationConfirm_featureServerAlias = (1 << 15), - eRegistrationConfirm_capacityReportingSpec = (1 << 14), - eRegistrationConfirm_featureSet = (1 << 13), - eRegistrationConfirm_genericData = (1 << 12), - } options; - RegistrationConfirm_callSignalAddress callSignalAddress; - unsigned timeToLive; -} RegistrationConfirm; - -typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} UnregistrationRequest_callSignalAddress; - -typedef struct UnregistrationRequest { /* SEQUENCE */ - enum { - eUnregistrationRequest_endpointAlias = (1 << 31), - eUnregistrationRequest_nonStandardData = (1 << 30), - eUnregistrationRequest_endpointIdentifier = (1 << 29), - eUnregistrationRequest_alternateEndpoints = (1 << 28), - eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), - eUnregistrationRequest_tokens = (1 << 26), - eUnregistrationRequest_cryptoTokens = (1 << 25), - eUnregistrationRequest_integrityCheckValue = (1 << 24), - eUnregistrationRequest_reason = (1 << 23), - eUnregistrationRequest_endpointAliasPattern = (1 << 22), - eUnregistrationRequest_supportedPrefixes = (1 << 21), - eUnregistrationRequest_alternateGatekeeper = (1 << 20), - eUnregistrationRequest_genericData = (1 << 19), - } options; - UnregistrationRequest_callSignalAddress callSignalAddress; -} UnregistrationRequest; - -typedef struct AdmissionRequest { /* SEQUENCE */ - enum { - eAdmissionRequest_callModel = (1 << 31), - eAdmissionRequest_destinationInfo = (1 << 30), - eAdmissionRequest_destCallSignalAddress = (1 << 29), - eAdmissionRequest_destExtraCallInfo = (1 << 28), - eAdmissionRequest_srcCallSignalAddress = (1 << 27), - eAdmissionRequest_nonStandardData = (1 << 26), - eAdmissionRequest_callServices = (1 << 25), - eAdmissionRequest_canMapAlias = (1 << 24), - eAdmissionRequest_callIdentifier = (1 << 23), - eAdmissionRequest_srcAlternatives = (1 << 22), - eAdmissionRequest_destAlternatives = (1 << 21), - eAdmissionRequest_gatekeeperIdentifier = (1 << 20), - eAdmissionRequest_tokens = (1 << 19), - eAdmissionRequest_cryptoTokens = (1 << 18), - eAdmissionRequest_integrityCheckValue = (1 << 17), - eAdmissionRequest_transportQOS = (1 << 16), - eAdmissionRequest_willSupplyUUIEs = (1 << 15), - eAdmissionRequest_callLinkage = (1 << 14), - eAdmissionRequest_gatewayDataRate = (1 << 13), - eAdmissionRequest_capacity = (1 << 12), - eAdmissionRequest_circuitInfo = (1 << 11), - eAdmissionRequest_desiredProtocols = (1 << 10), - eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), - eAdmissionRequest_featureSet = (1 << 8), - eAdmissionRequest_genericData = (1 << 7), - } options; - TransportAddress destCallSignalAddress; - TransportAddress srcCallSignalAddress; -} AdmissionRequest; - -typedef struct AdmissionConfirm { /* SEQUENCE */ - enum { - eAdmissionConfirm_irrFrequency = (1 << 31), - eAdmissionConfirm_nonStandardData = (1 << 30), - eAdmissionConfirm_destinationInfo = (1 << 29), - eAdmissionConfirm_destExtraCallInfo = (1 << 28), - eAdmissionConfirm_destinationType = (1 << 27), - eAdmissionConfirm_remoteExtensionAddress = (1 << 26), - eAdmissionConfirm_alternateEndpoints = (1 << 25), - eAdmissionConfirm_tokens = (1 << 24), - eAdmissionConfirm_cryptoTokens = (1 << 23), - eAdmissionConfirm_integrityCheckValue = (1 << 22), - eAdmissionConfirm_transportQOS = (1 << 21), - eAdmissionConfirm_willRespondToIRR = (1 << 20), - eAdmissionConfirm_uuiesRequested = (1 << 19), - eAdmissionConfirm_language = (1 << 18), - eAdmissionConfirm_alternateTransportAddresses = (1 << 17), - eAdmissionConfirm_useSpecifiedTransport = (1 << 16), - eAdmissionConfirm_circuitInfo = (1 << 15), - eAdmissionConfirm_usageSpec = (1 << 14), - eAdmissionConfirm_supportedProtocols = (1 << 13), - eAdmissionConfirm_serviceControl = (1 << 12), - eAdmissionConfirm_multipleCalls = (1 << 11), - eAdmissionConfirm_featureSet = (1 << 10), - eAdmissionConfirm_genericData = (1 << 9), - } options; - TransportAddress destCallSignalAddress; -} AdmissionConfirm; - -typedef struct LocationRequest { /* SEQUENCE */ - enum { - eLocationRequest_endpointIdentifier = (1 << 31), - eLocationRequest_nonStandardData = (1 << 30), - eLocationRequest_sourceInfo = (1 << 29), - eLocationRequest_canMapAlias = (1 << 28), - eLocationRequest_gatekeeperIdentifier = (1 << 27), - eLocationRequest_tokens = (1 << 26), - eLocationRequest_cryptoTokens = (1 << 25), - eLocationRequest_integrityCheckValue = (1 << 24), - eLocationRequest_desiredProtocols = (1 << 23), - eLocationRequest_desiredTunnelledProtocol = (1 << 22), - eLocationRequest_featureSet = (1 << 21), - eLocationRequest_genericData = (1 << 20), - eLocationRequest_hopCount = (1 << 19), - eLocationRequest_circuitInfo = (1 << 18), - } options; - TransportAddress replyAddress; -} LocationRequest; - -typedef struct LocationConfirm { /* SEQUENCE */ - enum { - eLocationConfirm_nonStandardData = (1 << 31), - eLocationConfirm_destinationInfo = (1 << 30), - eLocationConfirm_destExtraCallInfo = (1 << 29), - eLocationConfirm_destinationType = (1 << 28), - eLocationConfirm_remoteExtensionAddress = (1 << 27), - eLocationConfirm_alternateEndpoints = (1 << 26), - eLocationConfirm_tokens = (1 << 25), - eLocationConfirm_cryptoTokens = (1 << 24), - eLocationConfirm_integrityCheckValue = (1 << 23), - eLocationConfirm_alternateTransportAddresses = (1 << 22), - eLocationConfirm_supportedProtocols = (1 << 21), - eLocationConfirm_multipleCalls = (1 << 20), - eLocationConfirm_featureSet = (1 << 19), - eLocationConfirm_genericData = (1 << 18), - eLocationConfirm_circuitInfo = (1 << 17), - eLocationConfirm_serviceControl = (1 << 16), - } options; - TransportAddress callSignalAddress; - TransportAddress rasAddress; -} LocationConfirm; - -typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} InfoRequestResponse_callSignalAddress; - -typedef struct InfoRequestResponse { /* SEQUENCE */ - enum { - eInfoRequestResponse_nonStandardData = (1 << 31), - eInfoRequestResponse_endpointAlias = (1 << 30), - eInfoRequestResponse_perCallInfo = (1 << 29), - eInfoRequestResponse_tokens = (1 << 28), - eInfoRequestResponse_cryptoTokens = (1 << 27), - eInfoRequestResponse_integrityCheckValue = (1 << 26), - eInfoRequestResponse_needResponse = (1 << 25), - eInfoRequestResponse_capacity = (1 << 24), - eInfoRequestResponse_irrStatus = (1 << 23), - eInfoRequestResponse_unsolicited = (1 << 22), - eInfoRequestResponse_genericData = (1 << 21), - } options; - TransportAddress rasAddress; - InfoRequestResponse_callSignalAddress callSignalAddress; -} InfoRequestResponse; - -typedef struct RasMessage { /* CHOICE */ - enum { - eRasMessage_gatekeeperRequest, - eRasMessage_gatekeeperConfirm, - eRasMessage_gatekeeperReject, - eRasMessage_registrationRequest, - eRasMessage_registrationConfirm, - eRasMessage_registrationReject, - eRasMessage_unregistrationRequest, - eRasMessage_unregistrationConfirm, - eRasMessage_unregistrationReject, - eRasMessage_admissionRequest, - eRasMessage_admissionConfirm, - eRasMessage_admissionReject, - eRasMessage_bandwidthRequest, - eRasMessage_bandwidthConfirm, - eRasMessage_bandwidthReject, - eRasMessage_disengageRequest, - eRasMessage_disengageConfirm, - eRasMessage_disengageReject, - eRasMessage_locationRequest, - eRasMessage_locationConfirm, - eRasMessage_locationReject, - eRasMessage_infoRequest, - eRasMessage_infoRequestResponse, - eRasMessage_nonStandardMessage, - eRasMessage_unknownMessageResponse, - eRasMessage_requestInProgress, - eRasMessage_resourcesAvailableIndicate, - eRasMessage_resourcesAvailableConfirm, - eRasMessage_infoRequestAck, - eRasMessage_infoRequestNak, - eRasMessage_serviceControlIndication, - eRasMessage_serviceControlResponse, - } choice; - union { - GatekeeperRequest gatekeeperRequest; - GatekeeperConfirm gatekeeperConfirm; - RegistrationRequest registrationRequest; - RegistrationConfirm registrationConfirm; - UnregistrationRequest unregistrationRequest; - AdmissionRequest admissionRequest; - AdmissionConfirm admissionConfirm; - LocationRequest locationRequest; - LocationConfirm locationConfirm; - InfoRequestResponse infoRequestResponse; - }; -} RasMessage; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 83694cfdfa8f..1646076933b1 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -41,11 +41,13 @@ union nf_conntrack_expect_proto { /* Add protocol helper include file here */ #include +#include /* per conntrack: application helper private data */ union nf_conntrack_help { /* insert conntrack helper private data (master) here */ struct nf_ct_ftp_master ct_ftp_info; + struct nf_ct_h323_master ct_h323_info; }; #include diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 54a3d038beaa..cef3136e22a3 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -41,6 +41,7 @@ struct nf_conntrack_expect unsigned int flags; #ifdef CONFIG_NF_NAT_NEEDED + __be32 saved_ip; /* This is the original per-proto part, used to map the * expected connection the way the recipient expects. */ union nf_conntrack_man_proto saved_proto; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 6993ec53dc06..e14156d1122e 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -529,6 +529,11 @@ config IP_NF_NAT_H323 default IP_NF_NAT if IP_NF_H323=y default m if IP_NF_H323=m +config NF_NAT_H323 + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_H323 + config IP_NF_NAT_SIP tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 8893249bbe98..bdaba4700e3b 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -15,7 +15,7 @@ endif ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o -ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o +ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o ip_nat_h323-objs := ip_nat_helper_h323.o # connection tracking @@ -52,6 +52,7 @@ obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o # NAT helpers (nf_conntrack) obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o +obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c deleted file mode 100644 index 26dfecadb335..000000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ /dev/null @@ -1,874 +0,0 @@ -/**************************************************************************** - * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 - * conntrack/NAT module. - * - * Copyright (c) 2006 by Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - * - * See ip_conntrack_helper_h323_asn1.h for details. - * - ****************************************************************************/ - -#ifdef __KERNEL__ -#include -#else -#include -#endif -#include - -/* Trace Flag */ -#ifndef H323_TRACE -#define H323_TRACE 0 -#endif - -#if H323_TRACE -#define TAB_SIZE 4 -#define IFTHEN(cond, act) if(cond){act;} -#ifdef __KERNEL__ -#define PRINT printk -#else -#define PRINT printf -#endif -#define FNAME(name) name, -#else -#define IFTHEN(cond, act) -#define PRINT(fmt, args...) -#define FNAME(name) -#endif - -/* ASN.1 Types */ -#define NUL 0 -#define BOOL 1 -#define OID 2 -#define INT 3 -#define ENUM 4 -#define BITSTR 5 -#define NUMSTR 6 -#define NUMDGT 6 -#define TBCDSTR 6 -#define OCTSTR 7 -#define PRTSTR 7 -#define IA5STR 7 -#define GENSTR 7 -#define BMPSTR 8 -#define SEQ 9 -#define SET 9 -#define SEQOF 10 -#define SETOF 10 -#define CHOICE 11 - -/* Constraint Types */ -#define FIXD 0 -/* #define BITS 1-8 */ -#define BYTE 9 -#define WORD 10 -#define CONS 11 -#define SEMI 12 -#define UNCO 13 - -/* ASN.1 Type Attributes */ -#define SKIP 0 -#define STOP 1 -#define DECODE 2 -#define EXT 4 -#define OPEN 8 -#define OPT 16 - - -/* ASN.1 Field Structure */ -typedef struct field_t { -#if H323_TRACE - char *name; -#endif - unsigned char type; - unsigned char sz; - unsigned char lb; - unsigned char ub; - unsigned short attr; - unsigned short offset; - struct field_t *fields; -} field_t; - -/* Bit Stream */ -typedef struct { - unsigned char *buf; - unsigned char *beg; - unsigned char *end; - unsigned char *cur; - unsigned bit; -} bitstr_t; - -/* Tool Functions */ -#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;} -#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;} -#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;} -#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND) -static unsigned get_len(bitstr_t * bs); -static unsigned get_bit(bitstr_t * bs); -static unsigned get_bits(bitstr_t * bs, unsigned b); -static unsigned get_bitmap(bitstr_t * bs, unsigned b); -static unsigned get_uint(bitstr_t * bs, int b); - -/* Decoder Functions */ -static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_int(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level); -static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level); - -/* Decoder Functions Vector */ -typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int); -static decoder_t Decoders[] = { - decode_nul, - decode_bool, - decode_oid, - decode_int, - decode_enum, - decode_bitstr, - decode_numstr, - decode_octstr, - decode_bmpstr, - decode_seq, - decode_seqof, - decode_choice, -}; - -/**************************************************************************** - * H.323 Types - ****************************************************************************/ -#include "ip_conntrack_helper_h323_types.c" - -/**************************************************************************** - * Functions - ****************************************************************************/ -/* Assume bs is aligned && v < 16384 */ -unsigned get_len(bitstr_t * bs) -{ - unsigned v; - - v = *bs->cur++; - - if (v & 0x80) { - v &= 0x3f; - v <<= 8; - v += *bs->cur++; - } - - return v; -} - -/****************************************************************************/ -unsigned get_bit(bitstr_t * bs) -{ - unsigned b = (*bs->cur) & (0x80 >> bs->bit); - - INC_BIT(bs); - - return b; -} - -/****************************************************************************/ -/* Assume b <= 8 */ -unsigned get_bits(bitstr_t * bs, unsigned b) -{ - unsigned v, l; - - v = (*bs->cur) & (0xffU >> bs->bit); - l = b + bs->bit; - - if (l < 8) { - v >>= 8 - l; - bs->bit = l; - } else if (l == 8) { - bs->cur++; - bs->bit = 0; - } else { /* l > 8 */ - - v <<= 8; - v += *(++bs->cur); - v >>= 16 - l; - bs->bit = l - 8; - } - - return v; -} - -/****************************************************************************/ -/* Assume b <= 32 */ -unsigned get_bitmap(bitstr_t * bs, unsigned b) -{ - unsigned v, l, shift, bytes; - - if (!b) - return 0; - - l = bs->bit + b; - - if (l < 8) { - v = (unsigned) (*bs->cur) << (bs->bit + 24); - bs->bit = l; - } else if (l == 8) { - v = (unsigned) (*bs->cur++) << (bs->bit + 24); - bs->bit = 0; - } else { - for (bytes = l >> 3, shift = 24, v = 0; bytes; - bytes--, shift -= 8) - v |= (unsigned) (*bs->cur++) << shift; - - if (l < 32) { - v |= (unsigned) (*bs->cur) << shift; - v <<= bs->bit; - } else if (l > 32) { - v <<= bs->bit; - v |= (*bs->cur) >> (8 - bs->bit); - } - - bs->bit = l & 0x7; - } - - v &= 0xffffffff << (32 - b); - - return v; -} - -/**************************************************************************** - * Assume bs is aligned and sizeof(unsigned int) == 4 - ****************************************************************************/ -unsigned get_uint(bitstr_t * bs, int b) -{ - unsigned v = 0; - - switch (b) { - case 4: - v |= *bs->cur++; - v <<= 8; - case 3: - v |= *bs->cur++; - v <<= 8; - case 2: - v |= *bs->cur++; - v <<= 8; - case 1: - v |= *bs->cur++; - break; - } - return v; -} - -/****************************************************************************/ -int decode_nul(bitstr_t * bs, field_t * f, char *base, int level) -{ - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_bool(bitstr_t * bs, field_t * f, char *base, int level) -{ - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - INC_BIT(bs); - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_oid(bitstr_t * bs, field_t * f, char *base, int level) -{ - int len; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 1); - len = *bs->cur++; - bs->cur += len; - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_int(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned len; - - PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); - - switch (f->sz) { - case BYTE: /* Range == 256 */ - BYTE_ALIGN(bs); - bs->cur++; - break; - case WORD: /* 257 <= Range <= 64K */ - BYTE_ALIGN(bs); - bs->cur += 2; - break; - case CONS: /* 64K < Range < 4G */ - len = get_bits(bs, 2) + 1; - BYTE_ALIGN(bs); - if (base && (f->attr & DECODE)) { /* timeToLive */ - unsigned v = get_uint(bs, len) + f->lb; - PRINT(" = %u", v); - *((unsigned *) (base + f->offset)) = v; - } - bs->cur += len; - break; - case UNCO: - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 2); - len = get_len(bs); - bs->cur += len; - break; - default: /* 2 <= Range <= 255 */ - INC_BITS(bs, f->sz); - break; - } - - PRINT("\n"); - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_enum(bitstr_t * bs, field_t * f, char *base, int level) -{ - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - if ((f->attr & EXT) && get_bit(bs)) { - INC_BITS(bs, 7); - } else { - INC_BITS(bs, f->sz); - } - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned len; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - BYTE_ALIGN(bs); - switch (f->sz) { - case FIXD: /* fixed length > 16 */ - len = f->lb; - break; - case WORD: /* 2-byte length */ - CHECK_BOUND(bs, 2); - len = (*bs->cur++) << 8; - len += (*bs->cur++) + f->lb; - break; - case SEMI: - CHECK_BOUND(bs, 2); - len = get_len(bs); - break; - default: - len = 0; - break; - } - - bs->cur += len >> 3; - bs->bit = len & 7; - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned len; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - /* 2 <= Range <= 255 */ - len = get_bits(bs, f->sz) + f->lb; - - BYTE_ALIGN(bs); - INC_BITS(bs, (len << 2)); - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned len; - - PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); - - switch (f->sz) { - case FIXD: /* Range == 1 */ - if (f->lb > 2) { - BYTE_ALIGN(bs); - if (base && (f->attr & DECODE)) { - /* The IP Address */ - IFTHEN(f->lb == 4, - PRINT(" = %d.%d.%d.%d:%d", - bs->cur[0], bs->cur[1], - bs->cur[2], bs->cur[3], - bs->cur[4] * 256 + bs->cur[5])); - *((unsigned *) (base + f->offset)) = - bs->cur - bs->buf; - } - } - len = f->lb; - break; - case BYTE: /* Range == 256 */ - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 1); - len = (*bs->cur++) + f->lb; - break; - case SEMI: - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 2); - len = get_len(bs) + f->lb; - break; - default: /* 2 <= Range <= 255 */ - len = get_bits(bs, f->sz) + f->lb; - BYTE_ALIGN(bs); - break; - } - - bs->cur += len; - - PRINT("\n"); - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned len; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - switch (f->sz) { - case BYTE: /* Range == 256 */ - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 1); - len = (*bs->cur++) + f->lb; - break; - default: /* 2 <= Range <= 255 */ - len = get_bits(bs, f->sz) + f->lb; - BYTE_ALIGN(bs); - break; - } - - bs->cur += len << 1; - - CHECK_BOUND(bs, 0); - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len; - int err; - field_t *son; - unsigned char *beg = NULL; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - /* Decode? */ - base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; - - /* Extensible? */ - ext = (f->attr & EXT) ? get_bit(bs) : 0; - - /* Get fields bitmap */ - bmp = get_bitmap(bs, f->sz); - if (base) - *(unsigned *) base = bmp; - - /* Decode the root components */ - for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) { - if (son->attr & STOP) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", - son->name); - return H323_ERROR_STOP; - } - - if (son->attr & OPT) { /* Optional component */ - if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */ - continue; - } - - /* Decode */ - if (son->attr & OPEN) { /* Open field */ - CHECK_BOUND(bs, 2); - len = get_len(bs); - CHECK_BOUND(bs, len); - if (!base) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, - " ", son->name); - bs->cur += len; - continue; - } - beg = bs->cur; - - /* Decode */ - if ((err = (Decoders[son->type]) (bs, son, base, - level + 1)) < - H323_ERROR_NONE) - return err; - - bs->cur = beg + len; - bs->bit = 0; - } else if ((err = (Decoders[son->type]) (bs, son, base, - level + 1)) < - H323_ERROR_NONE) - return err; - } - - /* No extension? */ - if (!ext) - return H323_ERROR_NONE; - - /* Get the extension bitmap */ - bmp2_len = get_bits(bs, 7) + 1; - CHECK_BOUND(bs, (bmp2_len + 7) >> 3); - bmp2 = get_bitmap(bs, bmp2_len); - bmp |= bmp2 >> f->sz; - if (base) - *(unsigned *) base = bmp; - BYTE_ALIGN(bs); - - /* Decode the extension components */ - for (opt = 0; opt < bmp2_len; opt++, i++, son++) { - if (i < f->ub && son->attr & STOP) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", - son->name); - return H323_ERROR_STOP; - } - - if (!((0x80000000 >> opt) & bmp2)) /* Not present */ - continue; - - /* Check Range */ - if (i >= f->ub) { /* Newer Version? */ - CHECK_BOUND(bs, 2); - len = get_len(bs); - CHECK_BOUND(bs, len); - bs->cur += len; - continue; - } - - CHECK_BOUND(bs, 2); - len = get_len(bs); - CHECK_BOUND(bs, len); - if (!base || !(son->attr & DECODE)) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", - son->name); - bs->cur += len; - continue; - } - beg = bs->cur; - - if ((err = (Decoders[son->type]) (bs, son, base, - level + 1)) < - H323_ERROR_NONE) - return err; - - bs->cur = beg + len; - bs->bit = 0; - } - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned count, effective_count = 0, i, len = 0; - int err; - field_t *son; - unsigned char *beg = NULL; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - /* Decode? */ - base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; - - /* Decode item count */ - switch (f->sz) { - case BYTE: - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 1); - count = *bs->cur++; - break; - case WORD: - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 2); - count = *bs->cur++; - count <<= 8; - count = *bs->cur++; - break; - case SEMI: - BYTE_ALIGN(bs); - CHECK_BOUND(bs, 2); - count = get_len(bs); - break; - default: - count = get_bits(bs, f->sz); - break; - } - count += f->lb; - - /* Write Count */ - if (base) { - effective_count = count > f->ub ? f->ub : count; - *(unsigned *) base = effective_count; - base += sizeof(unsigned); - } - - /* Decode nested field */ - son = f->fields; - if (base) - base -= son->offset; - for (i = 0; i < count; i++) { - if (son->attr & OPEN) { - BYTE_ALIGN(bs); - len = get_len(bs); - CHECK_BOUND(bs, len); - if (!base || !(son->attr & DECODE)) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, - " ", son->name); - bs->cur += len; - continue; - } - beg = bs->cur; - - if ((err = (Decoders[son->type]) (bs, son, - i < - effective_count ? - base : NULL, - level + 1)) < - H323_ERROR_NONE) - return err; - - bs->cur = beg + len; - bs->bit = 0; - } else - if ((err = (Decoders[son->type]) (bs, son, - i < - effective_count ? - base : NULL, - level + 1)) < - H323_ERROR_NONE) - return err; - - if (base) - base += son->offset; - } - - return H323_ERROR_NONE; -} - - -/****************************************************************************/ -int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) -{ - unsigned type, ext, len = 0; - int err; - field_t *son; - unsigned char *beg = NULL; - - PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); - - /* Decode? */ - base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; - - /* Decode the choice index number */ - if ((f->attr & EXT) && get_bit(bs)) { - ext = 1; - type = get_bits(bs, 7) + f->lb; - } else { - ext = 0; - type = get_bits(bs, f->sz); - } - - /* Write Type */ - if (base) - *(unsigned *) base = type; - - /* Check Range */ - if (type >= f->ub) { /* Newer version? */ - BYTE_ALIGN(bs); - len = get_len(bs); - CHECK_BOUND(bs, len); - bs->cur += len; - return H323_ERROR_NONE; - } - - /* Transfer to son level */ - son = &f->fields[type]; - if (son->attr & STOP) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); - return H323_ERROR_STOP; - } - - if (ext || (son->attr & OPEN)) { - BYTE_ALIGN(bs); - len = get_len(bs); - CHECK_BOUND(bs, len); - if (!base || !(son->attr & DECODE)) { - PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", - son->name); - bs->cur += len; - return H323_ERROR_NONE; - } - beg = bs->cur; - - if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < - H323_ERROR_NONE) - return err; - - bs->cur = beg + len; - bs->bit = 0; - } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < - H323_ERROR_NONE) - return err; - - return H323_ERROR_NONE; -} - -/****************************************************************************/ -int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras) -{ - static field_t ras_message = { - FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT, - 0, _RasMessage - }; - bitstr_t bs; - - bs.buf = bs.beg = bs.cur = buf; - bs.end = buf + sz; - bs.bit = 0; - - return decode_choice(&bs, &ras_message, (char *) ras, 0); -} - -/****************************************************************************/ -static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg, - size_t sz, H323_UserInformation * uuie) -{ - static field_t h323_userinformation = { - FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT, - 0, _H323_UserInformation - }; - bitstr_t bs; - - bs.buf = buf; - bs.beg = bs.cur = beg; - bs.end = beg + sz; - bs.bit = 0; - - return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0); -} - -/****************************************************************************/ -int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, - MultimediaSystemControlMessage * - mscm) -{ - static field_t multimediasystemcontrolmessage = { - FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4, - DECODE | EXT, 0, _MultimediaSystemControlMessage - }; - bitstr_t bs; - - bs.buf = bs.beg = bs.cur = buf; - bs.end = buf + sz; - bs.bit = 0; - - return decode_choice(&bs, &multimediasystemcontrolmessage, - (char *) mscm, 0); -} - -/****************************************************************************/ -int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931) -{ - unsigned char *p = buf; - int len; - - if (!p || sz < 1) - return H323_ERROR_BOUND; - - /* Protocol Discriminator */ - if (*p != 0x08) { - PRINT("Unknown Protocol Discriminator\n"); - return H323_ERROR_RANGE; - } - p++; - sz--; - - /* CallReferenceValue */ - if (sz < 1) - return H323_ERROR_BOUND; - len = *p++; - sz--; - if (sz < len) - return H323_ERROR_BOUND; - p += len; - sz -= len; - - /* Message Type */ - if (sz < 1) - return H323_ERROR_BOUND; - q931->MessageType = *p++; - PRINT("MessageType = %02X\n", q931->MessageType); - if (*p & 0x80) { - p++; - sz--; - } - - /* Decode Information Elements */ - while (sz > 0) { - if (*p == 0x7e) { /* UserUserIE */ - if (sz < 3) - break; - p++; - len = *p++ << 8; - len |= *p++; - sz -= 3; - if (sz < len) - break; - p++; - len--; - return DecodeH323_UserInformation(buf, p, len, - &q931->UUIE); - } - p++; - sz--; - if (sz < 1) - break; - len = *p++; - if (sz < len) - break; - p += len; - sz -= len; - } - - PRINT("Q.931 UUIE not found\n"); - - return H323_ERROR_BOUND; -} diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c deleted file mode 100644 index 4b359618bedd..000000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c +++ /dev/null @@ -1,1926 +0,0 @@ -/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006 - * - * Copyright (c) 2006 Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - */ - -static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */ - {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE, - offsetof(TransportAddress_ipAddress, ip), NULL}, - {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */ - {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, -}; - -static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */ - {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ - {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, - {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, - _TransportAddress_ipSourceRoute_route}, - {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0, - _TransportAddress_ipSourceRoute_routing}, -}; - -static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */ - {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, - {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, - {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, -}; - -static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ - {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H221NonStandard[] = { /* SEQUENCE */ - {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _NonStandardIdentifier[] = { /* CHOICE */ - {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0, - _H221NonStandard}, -}; - -static field_t _NonStandardParameter[] = { /* SEQUENCE */ - {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0, - _NonStandardIdentifier}, - {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _TransportAddress[] = { /* CHOICE */ - {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE, - offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress}, - {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0, - _TransportAddress_ipSourceRoute}, - {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0, - _TransportAddress_ipxAddress}, - {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, - _TransportAddress_ip6Address}, - {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, - {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, - _NonStandardParameter}, -}; - -static field_t _AliasAddress[] = { /* CHOICE */ - {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL}, - {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL}, - {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL}, -}; - -static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _VendorIdentifier[] = { /* SEQUENCE */ - {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard}, - {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _GatekeeperInfo[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, -}; - -static field_t _H310Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H320Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H321Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H322Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H323Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H324Caps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _VoiceCaps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _T120OnlyCaps[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _SupportedProtocols[] = { /* CHOICE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0, - _NonStandardParameter}, - {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps}, - {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps}, - {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps}, - {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps}, - {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps}, - {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps}, - {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps}, - {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps}, - {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL}, -}; - -static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols}, -}; - -static field_t _GatewayInfo[] = { /* SEQUENCE */ - {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _GatewayInfo_protocol}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, -}; - -static field_t _McuInfo[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _TerminalInfo[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, -}; - -static field_t _EndpointType[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0, - _VendorIdentifier}, - {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, - _GatekeeperInfo}, - {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo}, - {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo}, - {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo}, - {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, - 0, NULL}, -}; - -static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */ - {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ - {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP, - 0, NULL}, -}; - -static field_t _Q954Details[] = { /* SEQUENCE */ - {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _QseriesOptions[] = { /* SEQUENCE */ - {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details}, -}; - -static field_t _CallType[] = { /* CHOICE */ - {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */ - {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */ - {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0, - _H245_NonStandardIdentifier_h221NonStandard}, -}; - -static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */ - {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0, - _H245_NonStandardIdentifier}, - {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H261VideoCapability[] = { /* SEQUENCE */ - {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, - NULL}, - {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H262VideoCapability[] = { /* SEQUENCE */ - {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0, - NULL}, - {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H263VideoCapability[] = { /* SEQUENCE */ - {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL}, - {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, - NULL}, - {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _IS11172VideoCapability[] = { /* SEQUENCE */ - {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _VideoCapability[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0, - _H261VideoCapability}, - {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0, - _H262VideoCapability}, - {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0, - _H263VideoCapability}, - {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0, - _IS11172VideoCapability}, - {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, -}; - -static field_t _AudioCapability_g7231[] = { /* SEQUENCE */ - {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _IS11172AudioCapability[] = { /* SEQUENCE */ - {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, -}; - -static field_t _IS13818AudioCapability[] = { /* SEQUENCE */ - {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, -}; - -static field_t _AudioCapability[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231}, - {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0, - _IS11172AudioCapability}, - {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0, - _IS13818AudioCapability}, - {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, - {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, - {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL}, -}; - -static field_t _DataProtocolCapability[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL}, - {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ - {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _T84Profile[] = { /* CHOICE */ - {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0, - _T84Profile_t84Restricted}, -}; - -static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */ - {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile}, -}; - -static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */ - {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _DataApplicationCapability_application[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT, - offsetof(DataApplicationCapability_application, t120), - _DataProtocolCapability}, - {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0, - _DataApplicationCapability_application_t84}, - {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0, - _DataApplicationCapability_application_nlpid}, - {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0, - _DataProtocolCapability}, - {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, - {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, - {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL}, - {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, -}; - -static field_t _DataApplicationCapability[] = { /* SEQUENCE */ - {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT, - offsetof(DataApplicationCapability, application), - _DataApplicationCapability_application}, - {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _EncryptionMode[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _DataType[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability}, - {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0, - _AudioCapability}, - {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data), - _DataApplicationCapability}, - {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0, - _EncryptionMode}, - {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL}, - {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, - {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, -}; - -static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */ - {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL}, - {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, - _H245_NonStandardParameter}, - {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0, - _H223LogicalChannelParameters_adaptationLayerType_al3}, - {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL}, - {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, - {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL}, -}; - -static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0, - _H223LogicalChannelParameters_adaptationLayerType}, - {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CRCLength[] = { /* CHOICE */ - {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V76HDLCParameters[] = { /* SEQUENCE */ - {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength}, - {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */ - {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */ - {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */ - {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0, - _V76LogicalChannelParameters_mode_eRM_recovery}, -}; - -static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */ - {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0, - _V76LogicalChannelParameters_mode_eRM}, - {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V75Parameters[] = { /* SEQUENCE */ - {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0, - _V76HDLCParameters}, - {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0, - _V76LogicalChannelParameters_suspendResume}, - {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0, - _V76LogicalChannelParameters_mode}, - {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters}, -}; - -static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, -}; - -static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */ - {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE, - offsetof(UnicastAddress_iPAddress, network), NULL}, - {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */ - {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, - {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, - {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, -}; - -static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */ - {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */ - {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */ - {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, -}; - -static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ - {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0, - _UnicastAddress_iPSourceRouteAddress_routing}, - {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, - {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, - _UnicastAddress_iPSourceRouteAddress_route}, -}; - -static field_t _UnicastAddress[] = { /* CHOICE */ - {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT, - offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress}, - {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0, - _UnicastAddress_iPXAddress}, - {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, - _UnicastAddress_iP6Address}, - {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0, - _UnicastAddress_iPSourceRouteAddress}, - {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, - {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, -}; - -static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */ - {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, - {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */ - {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _MulticastAddress[] = { /* CHOICE */ - {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0, - _MulticastAddress_iPAddress}, - {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, - _MulticastAddress_iP6Address}, - {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, - {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, -}; - -static field_t _H245_TransportAddress[] = { /* CHOICE */ - {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT, - offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress}, - {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0, - _MulticastAddress}, -}; - -static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _H2250LogicalChannelParameters_nonStandard}, - {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, - offsetof(H2250LogicalChannelParameters, mediaChannel), - _H245_TransportAddress}, - {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0, - NULL}, - {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, - offsetof(H2250LogicalChannelParameters, mediaControlChannel), - _H245_TransportAddress}, - {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT, - 0, NULL}, - {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL}, - {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0, - NULL}, - {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, - NULL}, - {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ - {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, - _H222LogicalChannelParameters}, - {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, - _H223LogicalChannelParameters}, - {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, - _V76LogicalChannelParameters}, - {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, - offsetof - (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters, - h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, - {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT, - offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, - dataType), _DataType}, - {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT, - offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, - multiplexParameters), - _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters}, - {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, - 0, NULL}, - {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ - {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, - _H223LogicalChannelParameters}, - {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, - _V76LogicalChannelParameters}, - {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, - offsetof - (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters, - h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, -}; - -static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType}, - {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT, - offsetof(OpenLogicalChannel_reverseLogicalChannelParameters, - multiplexParameters), - _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters}, - {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, - 0, NULL}, - {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */ - {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _Q2931Address_address[] = { /* CHOICE */ - {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL}, - {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, -}; - -static field_t _Q2931Address[] = { /* SEQUENCE */ - {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0, - _Q2931Address_address}, - {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ - {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address}, - {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT, - offsetof(NetworkAccessParameters_networkAddress, localAreaAddress), - _H245_TransportAddress}, -}; - -static field_t _NetworkAccessParameters[] = { /* SEQUENCE */ - {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, - _NetworkAccessParameters_distribution}, - {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT, - offsetof(NetworkAccessParameters, networkAddress), - _NetworkAccessParameters_networkAddress}, - {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, - NULL}, -}; - -static field_t _OpenLogicalChannel[] = { /* SEQUENCE */ - {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT, - offsetof(OpenLogicalChannel, forwardLogicalChannelParameters), - _OpenLogicalChannel_forwardLogicalChannelParameters}, - {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4, - DECODE | EXT | OPT, offsetof(OpenLogicalChannel, - reverseLogicalChannelParameters), - _OpenLogicalChannel_reverseLogicalChannelParameters}, - {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT, - offsetof(OpenLogicalChannel, separateStack), - _NetworkAccessParameters}, - {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, -}; - -static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Setup_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Setup_UUIE, h245Address), _TransportAddress}, - {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Setup_UUIE_sourceAddress}, - {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, - {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Setup_UUIE_destinationAddress}, - {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress}, - {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Setup_UUIE_destExtraCallInfo}, - {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Setup_UUIE_destExtraCRV}, - {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0, - _Setup_UUIE_conferenceGoal}, - {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0, - _QseriesOptions}, - {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, - {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress}, - {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart}, - {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0, - NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, - {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - NULL}, -}; - -static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, - _EndpointType}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(CallProceeding_UUIE, h245Address), _TransportAddress}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(CallProceeding_UUIE, fastStart), - _CallProceeding_UUIE_fastStart}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Connect_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Connect_UUIE, h245Address), _TransportAddress}, - {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, - _EndpointType}, - {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Alerting_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, - _EndpointType}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Alerting_UUIE, h245Address), _TransportAddress}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Information_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _ReleaseCompleteReason[] = { /* CHOICE */ - {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL}, - {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0, - NULL}, - {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0, - _ReleaseCompleteReason}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, -}; - -static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _FacilityReason[] = { /* CHOICE */ - {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Facility_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Facility_UUIE, alternativeAddress), _TransportAddress}, - {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Facility_UUIE_alternativeAliasAddress}, - {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, - {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT, - offsetof(Facility_UUIE, reason), _FacilityReason}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, - {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Facility_UUIE, h245Address), _TransportAddress}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, - {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL}, - {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, - NULL}, -}; - -static field_t _CallIdentifier[] = { /* SEQUENCE */ - {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, -}; - -static field_t _SecurityServiceMode[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, - {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _SecurityCapabilities[] = { /* SEQUENCE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0, - _SecurityServiceMode}, - {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0, - _SecurityServiceMode}, - {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0, - _SecurityServiceMode}, -}; - -static field_t _H245Security[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, - {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, - {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, -}; - -static field_t _DHset[] = { /* SEQUENCE */ - {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, - {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _TypedCertificate[] = { /* SEQUENCE */ - {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */ - {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _ClearToken[] = { /* SEQUENCE */ - {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset}, - {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL}, - {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, - _TypedCertificate}, - {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, - _H235_NonStandardParameter}, - {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL}, - {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, -}; - -static field_t _Params[] = { /* SEQUENCE */ - {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL}, - {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */ - {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, - {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, - {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoEPPwdHash_token}, -}; - -static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */ - {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, - {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoGKPwdHash_token}, -}; - -static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */ - {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */ - {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */ - {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */ - {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, - _CryptoToken_cryptoEncryptedToken_token}, -}; - -static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */ - {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */ - {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("token") SEQ, 0, 4, 4, SKIP, 0, - _CryptoToken_cryptoSignedToken_token}, -}; - -static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */ - {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, - {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, - _CryptoToken_cryptoHashedToken_token}, -}; - -static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */ - {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, - {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _CryptoToken[] = { /* CHOICE */ - {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0, - _CryptoToken_cryptoEncryptedToken}, - {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0, - _CryptoToken_cryptoSignedToken}, - {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0, - _CryptoToken_cryptoHashedToken}, - {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0, - _CryptoToken_cryptoPwdEncr}, -}; - -static field_t _CryptoH323Token[] = { /* CHOICE */ - {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoEPPwdHash}, - {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoGKPwdHash}, - {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoEPPwdEncr}, - {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0, - _CryptoH323Token_cryptoGKPwdEncr}, - {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0, - _CryptoH323Token_cryptoEPCert}, - {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0, - _CryptoH323Token_cryptoGKCert}, - {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0, - _CryptoH323Token_cryptoFastStart}, - {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0, - _CryptoToken}, -}; - -static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token}, -}; - -static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, - sizeof(OpenLogicalChannel), _OpenLogicalChannel} - , -}; - -static field_t _Progress_UUIE[] = { /* SEQUENCE */ - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, - _EndpointType}, - {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(Progress_UUIE, h245Address), _TransportAddress}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, - _CallIdentifier}, - {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, - _H245Security}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Progress_UUIE_tokens}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _Progress_UUIE_cryptoTokens}, - {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, - offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ - {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE}, - {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, callProceeding), - _CallProceeding_UUIE}, - {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE}, - {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE}, - {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, information), - _Information_UUIE}, - {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0, - _ReleaseComplete_UUIE}, - {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE}, - {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT, - offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE}, - {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, - {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, - {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, - {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, -}; - -static field_t _RequestMessage[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL}, - {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT, - offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel}, - {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL}, - {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL}, - {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL}, - {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, - {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, - {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0, - NULL}, -}; - -static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ - {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, - _H222LogicalChannelParameters}, - {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, - offsetof - (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters, - h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, -}; - -static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */ - {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT, - offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters, - multiplexParameters), - _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters}, - {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */ - {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, -}; - -static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ - {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _H2250LogicalChannelAckParameters_nonStandard}, - {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, - offsetof(H2250LogicalChannelAckParameters, mediaChannel), - _H245_TransportAddress}, - {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, - offsetof(H2250LogicalChannelAckParameters, mediaControlChannel), - _H245_TransportAddress}, - {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL}, - {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, -}; - -static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */ - {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT, - offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters, - h2250LogicalChannelAckParameters), - _H2250LogicalChannelAckParameters}, -}; - -static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ - {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4, - DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, - reverseLogicalChannelParameters), - _OpenLogicalChannelAck_reverseLogicalChannelParameters}, - {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL}, - {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1, - DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, - forwardMultiplexAckParameters), - _OpenLogicalChannelAck_forwardMultiplexAckParameters}, - {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, -}; - -static field_t _ResponseMessage[] = { /* CHOICE */ - {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0, - NULL}, - {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0, - NULL}, - {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0, - NULL}, - {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT, - offsetof(ResponseMessage, openLogicalChannelAck), - _OpenLogicalChannelAck}, - {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0, - NULL}, - {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0, - NULL}, - {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, - {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0, - NULL}, - {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, - {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, - {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0, - NULL}, - {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL}, -}; - -static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ - {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT, - offsetof(MultimediaSystemControlMessage, request), _RequestMessage}, - {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT, - offsetof(MultimediaSystemControlMessage, response), - _ResponseMessage}, - {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL}, - {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL}, -}; - -static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT, - sizeof(MultimediaSystemControlMessage), - _MultimediaSystemControlMessage} - , -}; - -static field_t _H323_UU_PDU[] = { /* SEQUENCE */ - {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT, - offsetof(H323_UU_PDU, h323_message_body), - _H323_UU_PDU_h323_message_body}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - NULL}, - {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT, - offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control}, - {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT, - 0, NULL}, - {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT, - 0, NULL}, - {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _H323_UserInformation[] = { /* SEQUENCE */ - {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT, - offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU}, - {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, -}; - -static field_t _GatekeeperRequest[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(GatekeeperRequest, rasAddress), _TransportAddress}, - {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, - {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _GatekeeperConfirm[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(GatekeeperConfirm, rasAddress), _TransportAddress}, - {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0, - NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, - sizeof(TransportAddress), _TransportAddress} - , -}; - -static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, - sizeof(TransportAddress), _TransportAddress} - , -}; - -static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _RegistrationRequest[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, - offsetof(RegistrationRequest, callSignalAddress), - _RegistrationRequest_callSignalAddress}, - {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE, - offsetof(RegistrationRequest, rasAddress), - _RegistrationRequest_rasAddress}, - {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, - {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _RegistrationRequest_terminalAlias}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0, - _VendorIdentifier}, - {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, - offsetof(RegistrationRequest, timeToLive), NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, - 0, NULL}, - {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, - NULL}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, - NULL}, - {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT, - 0, NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, - sizeof(TransportAddress), _TransportAddress} - , -}; - -static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _RegistrationConfirm[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, - offsetof(RegistrationConfirm, callSignalAddress), - _RegistrationConfirm_callSignalAddress}, - {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _RegistrationConfirm_terminalAlias}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, - {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, - offsetof(RegistrationConfirm, timeToLive), NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL}, - {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0, - NULL}, - {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0, - NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, - sizeof(TransportAddress), _TransportAddress} - , -}; - -static field_t _UnregistrationRequest[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, - offsetof(UnregistrationRequest, callSignalAddress), - _UnregistrationRequest_callSignalAddress}, - {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL}, - {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _CallModel[] = { /* CHOICE */ - {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL}, - {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, -}; - -static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _AdmissionRequest[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, - {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _AdmissionRequest_destinationInfo}, - {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(AdmissionRequest, destCallSignalAddress), - _TransportAddress}, - {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, - _AdmissionRequest_destExtraCallInfo}, - {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0, - _AdmissionRequest_srcInfo}, - {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, - offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress}, - {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL}, - {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, - {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL}, - {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, - {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, - NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _AdmissionConfirm[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL}, - {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel}, - {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(AdmissionConfirm, destCallSignalAddress), - _TransportAddress}, - {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, - {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL}, - {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, - 0, NULL}, - {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0, - NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, -}; - -static field_t _LocationRequest[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, - {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0, - _LocationRequest_destinationInfo}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(LocationRequest, replyAddress), _TransportAddress}, - {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, - NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, -}; - -static field_t _LocationConfirm[] = { /* SEQUENCE */ - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(LocationConfirm, callSignalAddress), _TransportAddress}, - {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(LocationConfirm, rasAddress), _TransportAddress}, - {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, - {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, - NULL}, - {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, - 0, NULL}, - {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, - {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */ - {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, - sizeof(TransportAddress), _TransportAddress} - , -}; - -static field_t _InfoRequestResponse[] = { /* SEQUENCE */ - {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, - _NonStandardParameter}, - {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, - {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, - {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, - {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, - offsetof(InfoRequestResponse, rasAddress), _TransportAddress}, - {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, - offsetof(InfoRequestResponse, callSignalAddress), - _InfoRequestResponse_callSignalAddress}, - {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, - {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, - {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, - {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, - {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL}, - {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, -}; - -static field_t _RasMessage[] = { /* CHOICE */ - {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT, - offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest}, - {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT, - offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm}, - {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, - {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT, - offsetof(RasMessage, registrationRequest), _RegistrationRequest}, - {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT, - offsetof(RasMessage, registrationConfirm), _RegistrationConfirm}, - {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, - {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT, - offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest}, - {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL}, - {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, - {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT, - offsetof(RasMessage, admissionRequest), _AdmissionRequest}, - {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT, - offsetof(RasMessage, admissionConfirm), _AdmissionConfirm}, - {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL}, - {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL}, - {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, - {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL}, - {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL}, - {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL}, - {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, - {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT, - offsetof(RasMessage, locationRequest), _LocationRequest}, - {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT, - offsetof(RasMessage, locationConfirm), _LocationConfirm}, - {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL}, - {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL}, - {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT, - offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse}, - {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL}, - {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL}, - {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL}, - {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0, - NULL}, - {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0, - NULL}, - {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL}, - {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL}, - {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0, - NULL}, - {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL}, -}; diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c new file mode 100644 index 000000000000..fb9ab0114c23 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -0,0 +1,596 @@ +/* + * H.323 extension for NAT alteration. + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * Based on the 'brute force' H.323 NAT module by + * Jozsef Kadlecsik + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#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, + unsigned int addroff, __be32 ip, __be16 port) +{ + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo); + struct { + __be32 ip; + __be16 port; + } __attribute__ ((__packed__)) buf; + struct tcphdr _tcph, *th; + + buf.ip = ip; + buf.port = port; + addroff += dataoff; + + if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) { + if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, + addroff, sizeof(buf), + (char *) &buf, sizeof(buf))) { + if (net_ratelimit()) + printk("nf_nat_h323: nf_nat_mangle_tcp_packet" + " error\n"); + return -1; + } + + /* Relocate data pointer */ + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, + sizeof(_tcph), &_tcph); + if (th == NULL) + return -1; + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + + th->doff * 4 + dataoff; + } else { + if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, + addroff, sizeof(buf), + (char *) &buf, sizeof(buf))) { + if (net_ratelimit()) + printk("nf_nat_h323: nf_nat_mangle_udp_packet" + " error\n"); + return -1; + } + /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy + * or pull everything in a linear buffer, so we can safely + * use the skb pointers now */ + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + + sizeof(struct udphdr); + } + + return 0; +} + +/****************************************************************************/ +static int set_h225_addr(struct sk_buff **pskb, + unsigned char **data, int dataoff, + TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 port) +{ + return set_addr(pskb, data, dataoff, taddr->ipAddress.ip, + addr->ip, port); +} + +/****************************************************************************/ +static int set_h245_addr(struct sk_buff **pskb, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 port) +{ + return set_addr(pskb, data, dataoff, + taddr->unicastAddress.iPAddress.network, + addr->ip, port); +} + +/****************************************************************************/ +static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int i; + __be16 port; + union nf_conntrack_address addr; + + for (i = 0; i < count; i++) { + if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) { + if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && + port == info->sig_port[dir]) { + /* GW->GK */ + + /* Fix for Gnomemeeting */ + if (i > 0 && + get_h225_addr(ct, *data, &taddr[0], + &addr, &port) && + (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]); + return set_h225_addr(pskb, data, 0, &taddr[i], + &ct->tuplehash[!dir]. + tuple.dst.u3, + info->sig_port[!dir]); + } 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]); + return set_h225_addr(pskb, data, 0, &taddr[i], + &ct->tuplehash[!dir]. + tuple.src.u3, + info->sig_port[!dir]); + } + } + } + + return 0; +} + +/****************************************************************************/ +static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count) +{ + int dir = CTINFO2DIR(ctinfo); + int i; + __be16 port; + union nf_conntrack_address addr; + + for (i = 0; i < count; i++) { + 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)); + return set_h225_addr(pskb, data, 0, &taddr[i], + &ct->tuplehash[!dir].tuple.dst.u3, + ct->tuplehash[!dir].tuple. + dst.u.udp.port); + } + } + + return 0; +} + +/****************************************************************************/ +static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + __be16 port, __be16 rtp_port, + struct nf_conntrack_expect *rtp_exp, + struct nf_conntrack_expect *rtcp_exp) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int i; + u_int16_t nated_port; + + /* Set expectations for NAT */ + rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; + rtp_exp->expectfn = nf_nat_follow_master; + rtp_exp->dir = !dir; + rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; + rtcp_exp->expectfn = nf_nat_follow_master; + rtcp_exp->dir = !dir; + + /* Lookup existing expects */ + for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) { + if (info->rtp_port[i][dir] == rtp_port) { + /* Expected */ + + /* Use allocated ports first. This will refresh + * the expects */ + rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir]; + rtcp_exp->tuple.dst.u.udp.port = + htons(ntohs(info->rtp_port[i][dir]) + 1); + break; + } else if (info->rtp_port[i][dir] == 0) { + /* Not expected */ + break; + } + } + + /* Run out of expectations */ + if (i >= H323_RTP_CHANNEL_MAX) { + if (net_ratelimit()) + printk("nf_nat_h323: out of expectations\n"); + return 0; + } + + /* Try to get a pair of ports. */ + 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) { + rtcp_exp->tuple.dst.u.udp.port = + htons(nated_port + 1); + if (nf_conntrack_expect_related(rtcp_exp) == 0) + break; + nf_conntrack_unexpect_related(rtp_exp); + } + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("nf_nat_h323: out of RTP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h245_addr(pskb, data, dataoff, taddr, + &ct->tuplehash[!dir].tuple.dst.u3, + htons((port & htons(1)) ? nated_port + 1 : + nated_port)) == 0) { + /* Save ports */ + 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); + return -1; + } + + /* 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)); + + return 0; +} + +/****************************************************************************/ +static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) +{ + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = ntohs(port); + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = nf_nat_follow_master; + exp->dir = !dir; + + /* 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) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("nf_nat_h323: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h245_addr(pskb, data, dataoff, taddr, + &ct->tuplehash[!dir].tuple.dst.u3, + htons(nated_port)) < 0) { + nf_conntrack_unexpect_related(exp); + 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)); + + return 0; +} + +/****************************************************************************/ +static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = ntohs(port); + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = nf_nat_follow_master; + exp->dir = !dir; + + /* Check existing expects */ + if (info->sig_port[dir] == port) + nated_port = ntohs(info->sig_port[!dir]); + + /* 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) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("nf_nat_q931: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h225_addr(pskb, data, dataoff, taddr, + &ct->tuplehash[!dir].tuple.dst.u3, + htons(nated_port)) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = htons(nated_port); + } else { + nf_conntrack_unexpect_related(exp); + 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)); + + return 0; +} + +/**************************************************************************** + * This conntrack expect function replaces nf_conntrack_q931_expect() + * which was set by nf_conntrack_h323.c. + ****************************************************************************/ +static void ip_nat_q931_expect(struct nf_conn *new, + struct nf_conntrack_expect *this) +{ + struct ip_nat_range range; + + if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ + nf_nat_follow_master(new, this); + return; + } + + /* This must be a fresh one. */ + BUG_ON(new->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; + + /* hook doesn't matter, but it has to do source manip */ + nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); + range.min = range.max = this->saved_proto; + range.min_ip = range.max_ip = + new->master->tuplehash[!this->dir].tuple.src.u3.ip; + + /* hook doesn't matter, but it has to do destination manip */ + nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); +} + +/****************************************************************************/ +static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress *taddr, int idx, + __be16 port, struct nf_conntrack_expect *exp) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = ntohs(port); + union nf_conntrack_address addr; + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = ip_nat_q931_expect; + exp->dir = !dir; + + /* Check existing expects */ + if (info->sig_port[dir] == port) + nated_port = ntohs(info->sig_port[!dir]); + + /* 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) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("nf_nat_ras: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h225_addr(pskb, data, 0, &taddr[idx], + &ct->tuplehash[!dir].tuple.dst.u3, + htons(nated_port)) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = htons(nated_port); + + /* Fix for Gnomemeeting */ + if (idx > 0 && + get_h225_addr(ct, *data, &taddr[0], &addr, &port) && + (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { + set_h225_addr_hook(pskb, data, 0, &taddr[0], + &ct->tuplehash[!dir].tuple.dst.u3, + info->sig_port[!dir]); + } + } else { + nf_conntrack_unexpect_related(exp); + return -1; + } + + /* 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)); + + return 0; +} + +/****************************************************************************/ +static void ip_nat_callforwarding_expect(struct nf_conn *new, + struct nf_conntrack_expect *this) +{ + struct nf_nat_range range; + + /* This must be a fresh one. */ + BUG_ON(new->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; + + /* hook doesn't matter, but it has to do source manip */ + nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); + range.min = range.max = this->saved_proto; + range.min_ip = range.max_ip = this->saved_ip; + + /* hook doesn't matter, but it has to do destination manip */ + nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); +} + +/****************************************************************************/ +static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) +{ + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port; + + /* Set expectations for NAT */ + exp->saved_ip = exp->tuple.dst.u3.ip; + exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip; + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = ip_nat_callforwarding_expect; + exp->dir = !dir; + + /* 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) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("nf_nat_q931: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (!set_h225_addr(pskb, data, dataoff, taddr, + &ct->tuplehash[!dir].tuple.dst.u3, + htons(nated_port)) == 0) { + nf_conntrack_unexpect_related(exp); + return -1; + } + + /* 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)); + + return 0; +} + +/****************************************************************************/ +static int __init init(void) +{ + BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL); + BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL); + BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL); + BUG_ON(rcu_dereference(nat_t120_hook) != NULL); + BUG_ON(rcu_dereference(nat_h245_hook) != NULL); + BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL); + BUG_ON(rcu_dereference(nat_q931_hook) != NULL); + + rcu_assign_pointer(set_h245_addr_hook, set_h245_addr); + rcu_assign_pointer(set_h225_addr_hook, set_h225_addr); + rcu_assign_pointer(set_sig_addr_hook, set_sig_addr); + rcu_assign_pointer(set_ras_addr_hook, set_ras_addr); + rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp); + rcu_assign_pointer(nat_t120_hook, nat_t120); + 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; +} + +/****************************************************************************/ +static void __exit fini(void) +{ + rcu_assign_pointer(set_h245_addr_hook, NULL); + rcu_assign_pointer(set_h225_addr_hook, NULL); + rcu_assign_pointer(set_sig_addr_hook, NULL); + rcu_assign_pointer(set_ras_addr_hook, NULL); + rcu_assign_pointer(nat_rtp_rtcp_hook, NULL); + rcu_assign_pointer(nat_t120_hook, NULL); + rcu_assign_pointer(nat_h245_hook, NULL); + rcu_assign_pointer(nat_callforwarding_hook, NULL); + rcu_assign_pointer(nat_q931_hook, NULL); + synchronize_rcu(); +} + +/****************************************************************************/ +module_init(init); +module_exit(fini); + +MODULE_AUTHOR("Jing Min Zhao "); +MODULE_DESCRIPTION("H.323 NAT helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_nat_h323"); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f85fd43b344b..d8f3451c95b6 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -160,6 +160,25 @@ config NF_CONNTRACK_FTP To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_H323 + tristate "H.323 protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + help + H.323 is a VoIP signalling protocol from ITU-T. As one of the most + important VoIP protocols, it is widely used by voice hardware and + software including voice gateways, IP phones, Netmeeting, OpenPhone, + Gnomemeeting, etc. + + With this module you can support H.323 on a connection tracking/NAT + firewall. + + This module supports RAS, Fast Start, H.245 Tunnelling, Call + Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat, + whiteboard, file transfer, etc. For more information, please + visit http://nath323.sourceforge.net/. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index a5ee93817427..69b554576b6b 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -20,8 +20,11 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o # connection tracking helpers +nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o + obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o +obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c new file mode 100644 index 000000000000..f6fad713d484 --- /dev/null +++ b/net/netfilter/nf_conntrack_h323_asn1.c @@ -0,0 +1,874 @@ +/**************************************************************************** + * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 + * conntrack/NAT module. + * + * Copyright (c) 2006 by Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * See ip_conntrack_helper_h323_asn1.h for details. + * + ****************************************************************************/ + +#ifdef __KERNEL__ +#include +#else +#include +#endif +#include + +/* Trace Flag */ +#ifndef H323_TRACE +#define H323_TRACE 0 +#endif + +#if H323_TRACE +#define TAB_SIZE 4 +#define IFTHEN(cond, act) if(cond){act;} +#ifdef __KERNEL__ +#define PRINT printk +#else +#define PRINT printf +#endif +#define FNAME(name) name, +#else +#define IFTHEN(cond, act) +#define PRINT(fmt, args...) +#define FNAME(name) +#endif + +/* ASN.1 Types */ +#define NUL 0 +#define BOOL 1 +#define OID 2 +#define INT 3 +#define ENUM 4 +#define BITSTR 5 +#define NUMSTR 6 +#define NUMDGT 6 +#define TBCDSTR 6 +#define OCTSTR 7 +#define PRTSTR 7 +#define IA5STR 7 +#define GENSTR 7 +#define BMPSTR 8 +#define SEQ 9 +#define SET 9 +#define SEQOF 10 +#define SETOF 10 +#define CHOICE 11 + +/* Constraint Types */ +#define FIXD 0 +/* #define BITS 1-8 */ +#define BYTE 9 +#define WORD 10 +#define CONS 11 +#define SEMI 12 +#define UNCO 13 + +/* ASN.1 Type Attributes */ +#define SKIP 0 +#define STOP 1 +#define DECODE 2 +#define EXT 4 +#define OPEN 8 +#define OPT 16 + + +/* ASN.1 Field Structure */ +typedef struct field_t { +#if H323_TRACE + char *name; +#endif + unsigned char type; + unsigned char sz; + unsigned char lb; + unsigned char ub; + unsigned short attr; + unsigned short offset; + struct field_t *fields; +} field_t; + +/* Bit Stream */ +typedef struct { + unsigned char *buf; + unsigned char *beg; + unsigned char *end; + unsigned char *cur; + unsigned bit; +} bitstr_t; + +/* Tool Functions */ +#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;} +#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;} +#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;} +#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND) +static unsigned get_len(bitstr_t * bs); +static unsigned get_bit(bitstr_t * bs); +static unsigned get_bits(bitstr_t * bs, unsigned b); +static unsigned get_bitmap(bitstr_t * bs, unsigned b); +static unsigned get_uint(bitstr_t * bs, int b); + +/* Decoder Functions */ +static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_int(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level); + +/* Decoder Functions Vector */ +typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int); +static decoder_t Decoders[] = { + decode_nul, + decode_bool, + decode_oid, + decode_int, + decode_enum, + decode_bitstr, + decode_numstr, + decode_octstr, + decode_bmpstr, + decode_seq, + decode_seqof, + decode_choice, +}; + +/**************************************************************************** + * H.323 Types + ****************************************************************************/ +#include "nf_conntrack_h323_types.c" + +/**************************************************************************** + * Functions + ****************************************************************************/ +/* Assume bs is aligned && v < 16384 */ +unsigned get_len(bitstr_t * bs) +{ + unsigned v; + + v = *bs->cur++; + + if (v & 0x80) { + v &= 0x3f; + v <<= 8; + v += *bs->cur++; + } + + return v; +} + +/****************************************************************************/ +unsigned get_bit(bitstr_t * bs) +{ + unsigned b = (*bs->cur) & (0x80 >> bs->bit); + + INC_BIT(bs); + + return b; +} + +/****************************************************************************/ +/* Assume b <= 8 */ +unsigned get_bits(bitstr_t * bs, unsigned b) +{ + unsigned v, l; + + v = (*bs->cur) & (0xffU >> bs->bit); + l = b + bs->bit; + + if (l < 8) { + v >>= 8 - l; + bs->bit = l; + } else if (l == 8) { + bs->cur++; + bs->bit = 0; + } else { /* l > 8 */ + + v <<= 8; + v += *(++bs->cur); + v >>= 16 - l; + bs->bit = l - 8; + } + + return v; +} + +/****************************************************************************/ +/* Assume b <= 32 */ +unsigned get_bitmap(bitstr_t * bs, unsigned b) +{ + unsigned v, l, shift, bytes; + + if (!b) + return 0; + + l = bs->bit + b; + + if (l < 8) { + v = (unsigned) (*bs->cur) << (bs->bit + 24); + bs->bit = l; + } else if (l == 8) { + v = (unsigned) (*bs->cur++) << (bs->bit + 24); + bs->bit = 0; + } else { + for (bytes = l >> 3, shift = 24, v = 0; bytes; + bytes--, shift -= 8) + v |= (unsigned) (*bs->cur++) << shift; + + if (l < 32) { + v |= (unsigned) (*bs->cur) << shift; + v <<= bs->bit; + } else if (l > 32) { + v <<= bs->bit; + v |= (*bs->cur) >> (8 - bs->bit); + } + + bs->bit = l & 0x7; + } + + v &= 0xffffffff << (32 - b); + + return v; +} + +/**************************************************************************** + * Assume bs is aligned and sizeof(unsigned int) == 4 + ****************************************************************************/ +unsigned get_uint(bitstr_t * bs, int b) +{ + unsigned v = 0; + + switch (b) { + case 4: + v |= *bs->cur++; + v <<= 8; + case 3: + v |= *bs->cur++; + v <<= 8; + case 2: + v |= *bs->cur++; + v <<= 8; + case 1: + v |= *bs->cur++; + break; + } + return v; +} + +/****************************************************************************/ +int decode_nul(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bool(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + INC_BIT(bs); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_oid(bitstr_t * bs, field_t * f, char *base, int level) +{ + int len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = *bs->cur++; + bs->cur += len; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_int(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + bs->cur++; + break; + case WORD: /* 257 <= Range <= 64K */ + BYTE_ALIGN(bs); + bs->cur += 2; + break; + case CONS: /* 64K < Range < 4G */ + len = get_bits(bs, 2) + 1; + BYTE_ALIGN(bs); + if (base && (f->attr & DECODE)) { /* timeToLive */ + unsigned v = get_uint(bs, len) + f->lb; + PRINT(" = %u", v); + *((unsigned *) (base + f->offset)) = v; + } + bs->cur += len; + break; + case UNCO: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + len = get_len(bs); + bs->cur += len; + break; + default: /* 2 <= Range <= 255 */ + INC_BITS(bs, f->sz); + break; + } + + PRINT("\n"); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_enum(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + if ((f->attr & EXT) && get_bit(bs)) { + INC_BITS(bs, 7); + } else { + INC_BITS(bs, f->sz); + } + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + BYTE_ALIGN(bs); + switch (f->sz) { + case FIXD: /* fixed length > 16 */ + len = f->lb; + break; + case WORD: /* 2-byte length */ + CHECK_BOUND(bs, 2); + len = (*bs->cur++) << 8; + len += (*bs->cur++) + f->lb; + break; + case SEMI: + CHECK_BOUND(bs, 2); + len = get_len(bs); + break; + default: + len = 0; + break; + } + + bs->cur += len >> 3; + bs->bit = len & 7; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + + BYTE_ALIGN(bs); + INC_BITS(bs, (len << 2)); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case FIXD: /* Range == 1 */ + if (f->lb > 2) { + BYTE_ALIGN(bs); + if (base && (f->attr & DECODE)) { + /* The IP Address */ + IFTHEN(f->lb == 4, + PRINT(" = %d.%d.%d.%d:%d", + bs->cur[0], bs->cur[1], + bs->cur[2], bs->cur[3], + bs->cur[4] * 256 + bs->cur[5])); + *((unsigned *) (base + f->offset)) = + bs->cur - bs->buf; + } + } + len = f->lb; + break; + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = (*bs->cur++) + f->lb; + break; + case SEMI: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + len = get_len(bs) + f->lb; + break; + default: /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + BYTE_ALIGN(bs); + break; + } + + bs->cur += len; + + PRINT("\n"); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = (*bs->cur++) + f->lb; + break; + default: /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + BYTE_ALIGN(bs); + break; + } + + bs->cur += len << 1; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Extensible? */ + ext = (f->attr & EXT) ? get_bit(bs) : 0; + + /* Get fields bitmap */ + bmp = get_bitmap(bs, f->sz); + if (base) + *(unsigned *) base = bmp; + + /* Decode the root components */ + for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) { + if (son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + return H323_ERROR_STOP; + } + + if (son->attr & OPT) { /* Optional component */ + if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */ + continue; + } + + /* Decode */ + if (son->attr & OPEN) { /* Open field */ + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, + " ", son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + /* Decode */ + if ((err = (Decoders[son->type]) (bs, son, base, + level + 1)) < + H323_ERROR_NONE) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else if ((err = (Decoders[son->type]) (bs, son, base, + level + 1)) < + H323_ERROR_NONE) + return err; + } + + /* No extension? */ + if (!ext) + return H323_ERROR_NONE; + + /* Get the extension bitmap */ + bmp2_len = get_bits(bs, 7) + 1; + CHECK_BOUND(bs, (bmp2_len + 7) >> 3); + bmp2 = get_bitmap(bs, bmp2_len); + bmp |= bmp2 >> f->sz; + if (base) + *(unsigned *) base = bmp; + BYTE_ALIGN(bs); + + /* Decode the extension components */ + for (opt = 0; opt < bmp2_len; opt++, i++, son++) { + if (i < f->ub && son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + return H323_ERROR_STOP; + } + + if (!((0x80000000 >> opt) & bmp2)) /* Not present */ + continue; + + /* Check Range */ + if (i >= f->ub) { /* Newer Version? */ + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + bs->cur += len; + continue; + } + + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, base, + level + 1)) < + H323_ERROR_NONE) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned count, effective_count = 0, i, len = 0; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Decode item count */ + switch (f->sz) { + case BYTE: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + count = *bs->cur++; + break; + case WORD: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + count = *bs->cur++; + count <<= 8; + count = *bs->cur++; + break; + case SEMI: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + count = get_len(bs); + break; + default: + count = get_bits(bs, f->sz); + break; + } + count += f->lb; + + /* Write Count */ + if (base) { + effective_count = count > f->ub ? f->ub : count; + *(unsigned *) base = effective_count; + base += sizeof(unsigned); + } + + /* Decode nested field */ + son = f->fields; + if (base) + base -= son->offset; + for (i = 0; i < count; i++) { + if (son->attr & OPEN) { + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, + " ", son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, + i < + effective_count ? + base : NULL, + level + 1)) < + H323_ERROR_NONE) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else + if ((err = (Decoders[son->type]) (bs, son, + i < + effective_count ? + base : NULL, + level + 1)) < + H323_ERROR_NONE) + return err; + + if (base) + base += son->offset; + } + + return H323_ERROR_NONE; +} + + +/****************************************************************************/ +int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned type, ext, len = 0; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Decode the choice index number */ + if ((f->attr & EXT) && get_bit(bs)) { + ext = 1; + type = get_bits(bs, 7) + f->lb; + } else { + ext = 0; + type = get_bits(bs, f->sz); + } + + /* Write Type */ + if (base) + *(unsigned *) base = type; + + /* Check Range */ + if (type >= f->ub) { /* Newer version? */ + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + bs->cur += len; + return H323_ERROR_NONE; + } + + /* Transfer to son level */ + son = &f->fields[type]; + if (son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); + return H323_ERROR_STOP; + } + + if (ext || (son->attr & OPEN)) { + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + bs->cur += len; + return H323_ERROR_NONE; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < + H323_ERROR_NONE) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < + H323_ERROR_NONE) + return err; + + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras) +{ + static field_t ras_message = { + FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT, + 0, _RasMessage + }; + bitstr_t bs; + + bs.buf = bs.beg = bs.cur = buf; + bs.end = buf + sz; + bs.bit = 0; + + return decode_choice(&bs, &ras_message, (char *) ras, 0); +} + +/****************************************************************************/ +static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg, + size_t sz, H323_UserInformation * uuie) +{ + static field_t h323_userinformation = { + FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT, + 0, _H323_UserInformation + }; + bitstr_t bs; + + bs.buf = buf; + bs.beg = bs.cur = beg; + bs.end = beg + sz; + bs.bit = 0; + + return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0); +} + +/****************************************************************************/ +int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, + MultimediaSystemControlMessage * + mscm) +{ + static field_t multimediasystemcontrolmessage = { + FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4, + DECODE | EXT, 0, _MultimediaSystemControlMessage + }; + bitstr_t bs; + + bs.buf = bs.beg = bs.cur = buf; + bs.end = buf + sz; + bs.bit = 0; + + return decode_choice(&bs, &multimediasystemcontrolmessage, + (char *) mscm, 0); +} + +/****************************************************************************/ +int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931) +{ + unsigned char *p = buf; + int len; + + if (!p || sz < 1) + return H323_ERROR_BOUND; + + /* Protocol Discriminator */ + if (*p != 0x08) { + PRINT("Unknown Protocol Discriminator\n"); + return H323_ERROR_RANGE; + } + p++; + sz--; + + /* CallReferenceValue */ + if (sz < 1) + return H323_ERROR_BOUND; + len = *p++; + sz--; + if (sz < len) + return H323_ERROR_BOUND; + p += len; + sz -= len; + + /* Message Type */ + if (sz < 1) + return H323_ERROR_BOUND; + q931->MessageType = *p++; + PRINT("MessageType = %02X\n", q931->MessageType); + if (*p & 0x80) { + p++; + sz--; + } + + /* Decode Information Elements */ + while (sz > 0) { + if (*p == 0x7e) { /* UserUserIE */ + if (sz < 3) + break; + p++; + len = *p++ << 8; + len |= *p++; + sz -= 3; + if (sz < len) + break; + p++; + len--; + return DecodeH323_UserInformation(buf, p, len, + &q931->UUIE); + } + p++; + sz--; + if (sz < 1) + break; + len = *p++; + if (sz < len) + break; + p += len; + sz -= len; + } + + PRINT("Q.931 UUIE not found\n"); + + return H323_ERROR_BOUND; +} diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c new file mode 100644 index 000000000000..6d8568959f82 --- /dev/null +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -0,0 +1,1856 @@ +/* + * H.323 connection tracking helper + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * Based on the 'brute force' H.323 connection tracking module by + * Jozsef Kadlecsik + * + * For more information, please see http://nath323.sourceforge.net/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#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); +MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ"); + +static int gkrouted_only __read_mostly = 1; +module_param(gkrouted_only, int, 0600); +MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); + +static int callforward_filter __read_mostly = 1; +module_param(callforward_filter, bool, 0600); +MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations " + "if both endpoints are on different sides " + "(determined by routing information)"); + +/* Hooks for NAT */ +int (*set_h245_addr_hook) (struct sk_buff **pskb, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 port) + __read_mostly; +int (*set_h225_addr_hook) (struct sk_buff **pskb, + unsigned char **data, int dataoff, + TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 port) + __read_mostly; +int (*set_sig_addr_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count) __read_mostly; +int (*set_ras_addr_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count) __read_mostly; +int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, + __be16 port, __be16 rtp_port, + struct nf_conntrack_expect *rtp_exp, + struct nf_conntrack_expect *rtcp_exp) __read_mostly; +int (*nat_t120_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) __read_mostly; +int (*nat_h245_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) __read_mostly; +int (*nat_callforwarding_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr, __be16 port, + struct nf_conntrack_expect *exp) __read_mostly; +int (*nat_q931_hook) (struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress *taddr, int idx, + __be16 port, struct nf_conntrack_expect *exp) + __read_mostly; + +static DEFINE_SPINLOCK(nf_h323_lock); +static char *h323_buffer; + +static struct nf_conntrack_helper nf_conntrack_helper_h245; +static struct nf_conntrack_helper nf_conntrack_helper_q931[]; +static struct nf_conntrack_helper nf_conntrack_helper_ras[]; + +/****************************************************************************/ +static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo, + unsigned char **data, int *datalen, int *dataoff) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + struct tcphdr _tcph, *th; + int tcpdatalen; + int tcpdataoff; + unsigned char *tpkt; + int tpktlen; + int tpktoff; + + /* Get TCP header */ + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) + return 0; + + /* Get TCP data offset */ + tcpdataoff = protoff + th->doff * 4; + + /* Get TCP data length */ + tcpdatalen = (*pskb)->len - tcpdataoff; + if (tcpdatalen <= 0) /* No TCP data */ + goto clear_out; + + if (*data == NULL) { /* first TPKT */ + /* Get first TPKT pointer */ + tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen, + h323_buffer); + BUG_ON(tpkt == NULL); + + /* Validate TPKT identifier */ + 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]); + if (info->tpkt_len[dir] <= tcpdatalen) { + /* Yes, there was a TPKT header + * received */ + *data = tpkt; + *datalen = info->tpkt_len[dir]; + *dataoff = 0; + goto out; + } + + /* Fragmented TPKT */ + if (net_ratelimit()) + printk("nf_ct_h323: " + "fragmented TPKT\n"); + goto clear_out; + } + + /* It is not even a TPKT */ + return 0; + } + tpktoff = 0; + } else { /* Next TPKT */ + tpktoff = *dataoff + *datalen; + tcpdatalen -= tpktoff; + if (tcpdatalen <= 4) /* No more TPKT */ + goto clear_out; + tpkt = *data + *datalen; + + /* Validate TPKT identifier */ + if (tpkt[0] != 0x03 || tpkt[1] != 0) + goto clear_out; + } + + /* Validate TPKT length */ + tpktlen = tpkt[2] * 256 + tpkt[3]; + if (tpktlen < 4) + goto clear_out; + 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); + info->tpkt_len[dir] = tpktlen - 4; + return 0; + } + + if (net_ratelimit()) + printk("nf_ct_h323: incomplete TPKT (fragmented?)\n"); + goto clear_out; + } + + /* This is the encapsulated data */ + *data = tpkt + 4; + *datalen = tpktlen - 4; + *dataoff = tpktoff + 4; + + out: + /* Clear TPKT length */ + info->tpkt_len[dir] = 0; + return 1; + + clear_out: + info->tpkt_len[dir] = 0; + return 0; +} + +/****************************************************************************/ +static int get_h245_addr(struct nf_conn *ct, unsigned char *data, + H245_TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 *port) +{ + unsigned char *p; + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + int len; + + if (taddr->choice != eH245_TransportAddress_unicastAddress) + return 0; + + switch (taddr->unicastAddress.choice) { + case eUnicastAddress_iPAddress: + if (family != AF_INET) + return 0; + p = data + taddr->unicastAddress.iPAddress.network; + len = 4; + break; + case eUnicastAddress_iP6Address: + if (family != AF_INET6) + return 0; + p = data + taddr->unicastAddress.iP6Address.network; + len = 16; + break; + default: + return 0; + } + + memcpy(addr, p, len); + memset((void *)addr + len, 0, sizeof(*addr) - len); + memcpy(port, p + len, sizeof(__be16)); + + return 1; +} + +/****************************************************************************/ +static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + __be16 rtp_port, rtcp_port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *rtp_exp; + struct nf_conntrack_expect *rtcp_exp; + typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp; + + /* Read RTP or RTCP address */ + if (!get_h245_addr(ct, *data, taddr, &addr, &port) || + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || + port == 0) + return 0; + + /* RTP port is even */ + port &= htons(~1); + rtp_port = port; + rtcp_port = htons(ntohs(port) + 1); + + /* Create expect for RTP */ + if ((rtp_exp = nf_conntrack_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); + + /* Create expect for RTCP */ + if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) { + nf_conntrack_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); + + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + sizeof(ct->tuplehash[dir].tuple.src.u3)) && + (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && + ct->status & IPS_NAT_MASK) { + /* NAT needed */ + 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) { + 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); + ret = -1; + } + } else + ret = -1; + } + + nf_conntrack_expect_put(rtp_exp); + nf_conntrack_expect_put(rtcp_exp); + + return ret; +} + +/****************************************************************************/ +static int expect_t120(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress *taddr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + typeof(nat_t120_hook) nat_t120; + + /* Read T.120 address */ + if (!get_h245_addr(ct, *data, taddr, &addr, &port) || + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || + port == 0) + return 0; + + /* Create expect for T.120 connections */ + if ((exp = nf_conntrack_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); + exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */ + + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + sizeof(ct->tuplehash[dir].tuple.src.u3)) && + (nat_t120 = rcu_dereference(nat_t120_hook)) && + ct->status & IPS_NAT_MASK) { + /* NAT needed */ + ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, + port, exp); + } else { /* Conntrack only */ + if (nf_conntrack_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); + + return ret; +} + +/****************************************************************************/ +static int process_h245_channel(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H2250LogicalChannelParameters *channel) +{ + int ret; + + if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { + /* RTP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &channel->mediaChannel); + if (ret < 0) + return -1; + } + + if (channel-> + options & eH2250LogicalChannelParameters_mediaControlChannel) { + /* RTCP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &channel->mediaControlChannel); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + OpenLogicalChannel *olc) +{ + int ret; + + DEBUGP("nf_ct_h323: OpenLogicalChannel\n"); + + if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) + { + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olc-> + forwardLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olc->options & + eOpenLogicalChannel_reverseLogicalChannelParameters) && + (olc->reverseLogicalChannelParameters.options & + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters) + && (olc->reverseLogicalChannelParameters.multiplexParameters. + choice == + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) + { + ret = + process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olc-> + reverseLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olc->options & eOpenLogicalChannel_separateStack) && + olc->forwardLogicalChannelParameters.dataType.choice == + eDataType_data && + olc->forwardLogicalChannelParameters.dataType.data.application. + choice == eDataApplicationCapability_application_t120 && + olc->forwardLogicalChannelParameters.dataType.data.application. + t120.choice == eDataProtocolCapability_separateLANStack && + olc->separateStack.networkAddress.choice == + eNetworkAccessParameters_networkAddress_localAreaAddress) { + ret = expect_t120(pskb, ct, ctinfo, data, dataoff, + &olc->separateStack.networkAddress. + localAreaAddress); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + OpenLogicalChannelAck *olca) +{ + H2250LogicalChannelAckParameters *ack; + int ret; + + DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n"); + + if ((olca->options & + eOpenLogicalChannelAck_reverseLogicalChannelParameters) && + (olca->reverseLogicalChannelParameters.options & + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters) + && (olca->reverseLogicalChannelParameters.multiplexParameters. + choice == + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) + { + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olca-> + reverseLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olca->options & + eOpenLogicalChannelAck_forwardMultiplexAckParameters) && + (olca->forwardMultiplexAckParameters.choice == + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)) + { + ack = &olca->forwardMultiplexAckParameters. + h2250LogicalChannelAckParameters; + if (ack->options & + eH2250LogicalChannelAckParameters_mediaChannel) { + /* RTP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &ack->mediaChannel); + if (ret < 0) + return -1; + } + + if (ack->options & + eH2250LogicalChannelAckParameters_mediaControlChannel) { + /* RTCP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &ack->mediaControlChannel); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + MultimediaSystemControlMessage *mscm) +{ + switch (mscm->choice) { + case eMultimediaSystemControlMessage_request: + if (mscm->request.choice == + eRequestMessage_openLogicalChannel) { + return process_olc(pskb, ct, ctinfo, data, dataoff, + &mscm->request.openLogicalChannel); + } + DEBUGP("nf_ct_h323: H.245 Request %d\n", + mscm->request.choice); + break; + case eMultimediaSystemControlMessage_response: + if (mscm->response.choice == + eResponseMessage_openLogicalChannelAck) { + return process_olca(pskb, ct, ctinfo, data, dataoff, + &mscm->response. + openLogicalChannelAck); + } + DEBUGP("nf_ct_h323: H.245 Response %d\n", + mscm->response.choice); + break; + default: + DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice); + break; + } + + return 0; +} + +/****************************************************************************/ +static int h245_help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + static MultimediaSystemControlMessage mscm; + unsigned char *data = NULL; + int datalen; + int dataoff; + int ret; + + /* 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) { + return NF_ACCEPT; + } + DEBUGP("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); + NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); + + /* Decode H.245 signal */ + ret = DecodeMultimediaSystemControlMessage(data, datalen, + &mscm); + if (ret < 0) { + if (net_ratelimit()) + printk("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; + } + + /* Process H.245 signal */ + if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0) + goto drop; + } + + spin_unlock_bh(&nf_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&nf_h323_lock); + if (net_ratelimit()) + printk("nf_ct_h245: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { + .name = "H.245", + .me = THIS_MODULE, + .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 +}; + +/****************************************************************************/ +int get_h225_addr(struct nf_conn *ct, unsigned char *data, + TransportAddress *taddr, + union nf_conntrack_address *addr, __be16 *port) +{ + unsigned char *p; + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + int len; + + switch (taddr->choice) { + case eTransportAddress_ipAddress: + if (family != AF_INET) + return 0; + p = data + taddr->ipAddress.ip; + len = 4; + break; + case eTransportAddress_ip6Address: + if (family != AF_INET6) + return 0; + p = data + taddr->ip6Address.ip6; + len = 16; + break; + default: + return 0; + } + + memcpy(addr, p, len); + memset((void *)addr + len, 0, sizeof(*addr) - len); + memcpy(port, p + len, sizeof(__be16)); + + return 1; +} + +/****************************************************************************/ +static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + typeof(nat_h245_hook) nat_h245; + + /* Read h245Address */ + if (!get_h225_addr(ct, *data, taddr, &addr, &port) || + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || + port == 0) + return 0; + + /* Create expect for h245 connection */ + if ((exp = nf_conntrack_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); + exp->helper = &nf_conntrack_helper_h245; + + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + sizeof(ct->tuplehash[dir].tuple.src.u3)) && + (nat_h245 = rcu_dereference(nat_h245_hook)) && + ct->status & IPS_NAT_MASK) { + /* NAT needed */ + ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, + port, exp); + } else { /* Conntrack only */ + if (nf_conntrack_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); + + return ret; +} + +/* If the calling party is on the same side of the forward-to party, + * we don't need to track the second call */ +static int callforward_do_filter(union nf_conntrack_address *src, + union nf_conntrack_address *dst, + int family) +{ + struct flowi fl1, fl2; + int ret = 0; + + memset(&fl1, 0, sizeof(fl1)); + memset(&fl2, 0, sizeof(fl2)); + + switch (family) { + case AF_INET: { + struct rtable *rt1, *rt2; + + fl1.fl4_dst = src->ip; + fl2.fl4_dst = dst->ip; + if (ip_route_output_key(&rt1, &fl1) == 0) { + if (ip_route_output_key(&rt2, &fl2) == 0) { + if (rt1->rt_gateway == rt2->rt_gateway && + rt1->u.dst.dev == rt2->u.dst.dev) + ret = 1; + dst_release(&rt2->u.dst); + } + dst_release(&rt1->u.dst); + } + break; + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: { + struct rt6_info *rt1, *rt2; + + memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst)); + memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst)); + rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1); + if (rt1) { + rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2); + if (rt2) { + if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, + sizeof(rt1->rt6i_gateway)) && + rt1->u.dst.dev == rt2->u.dst.dev) + ret = 1; + dst_release(&rt2->u.dst); + } + dst_release(&rt1->u.dst); + } + break; + } +#endif + } + return ret; + +} + +/****************************************************************************/ +static int expect_callforwarding(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress *taddr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + typeof(nat_callforwarding_hook) nat_callforwarding; + + /* Read alternativeAddress */ + if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0) + return 0; + + /* If the calling party is on the same side of the forward-to party, + * we don't need to track the second call */ + 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"); + return 0; + } + + /* Create expect for the second call leg */ + if ((exp = nf_conntrack_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); + exp->helper = nf_conntrack_helper_q931; + + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, + &ct->tuplehash[!dir].tuple.dst.u3, + sizeof(ct->tuplehash[dir].tuple.src.u3)) && + (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && + ct->status & IPS_NAT_MASK) { + /* Need NAT */ + ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, + taddr, port, exp); + } else { /* Conntrack only */ + if (nf_conntrack_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); + + return ret; +} + +/****************************************************************************/ +static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Setup_UUIE *setup) +{ + int dir = CTINFO2DIR(ctinfo); + int ret; + int i; + __be16 port; + union nf_conntrack_address addr; + typeof(set_h225_addr_hook) set_h225_addr; + + DEBUGP("nf_ct_q931: Setup\n"); + + if (setup->options & eSetup_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &setup->h245Address); + if (ret < 0) + return -1; + } + + set_h225_addr = rcu_dereference(set_h225_addr_hook); + if ((setup->options & eSetup_UUIE_destCallSignalAddress) && + (set_h225_addr) && ct->status && IPS_NAT_MASK && + 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)); + ret = set_h225_addr(pskb, data, dataoff, + &setup->destCallSignalAddress, + &ct->tuplehash[!dir].tuple.src.u3, + ct->tuplehash[!dir].tuple.src.u.tcp.port); + if (ret < 0) + return -1; + } + + if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && + (set_h225_addr) && ct->status & IPS_NAT_MASK && + 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)); + ret = set_h225_addr(pskb, data, dataoff, + &setup->sourceCallSignalAddress, + &ct->tuplehash[!dir].tuple.dst.u3, + ct->tuplehash[!dir].tuple.dst.u.tcp.port); + if (ret < 0) + return -1; + } + + if (setup->options & eSetup_UUIE_fastStart) { + for (i = 0; i < setup->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &setup->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_callproceeding(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + CallProceeding_UUIE *callproc) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: CallProceeding\n"); + + if (callproc->options & eCallProceeding_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &callproc->h245Address); + if (ret < 0) + return -1; + } + + if (callproc->options & eCallProceeding_UUIE_fastStart) { + for (i = 0; i < callproc->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &callproc->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Connect_UUIE *connect) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: Connect\n"); + + if (connect->options & eConnect_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &connect->h245Address); + if (ret < 0) + return -1; + } + + if (connect->options & eConnect_UUIE_fastStart) { + for (i = 0; i < connect->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &connect->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Alerting_UUIE *alert) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: Alerting\n"); + + if (alert->options & eAlerting_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &alert->h245Address); + if (ret < 0) + return -1; + } + + if (alert->options & eAlerting_UUIE_fastStart) { + for (i = 0; i < alert->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &alert->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_information(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Information_UUIE *info) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: Information\n"); + + if (info->options & eInformation_UUIE_fastStart) { + for (i = 0; i < info->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &info->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Facility_UUIE *facility) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: Facility\n"); + + if (facility->reason.choice == eFacilityReason_callForwarded) { + if (facility->options & eFacility_UUIE_alternativeAddress) + return expect_callforwarding(pskb, ct, ctinfo, data, + dataoff, + &facility-> + alternativeAddress); + return 0; + } + + if (facility->options & eFacility_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &facility->h245Address); + if (ret < 0) + return -1; + } + + if (facility->options & eFacility_UUIE_fastStart) { + for (i = 0; i < facility->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &facility->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Progress_UUIE *progress) +{ + int ret; + int i; + + DEBUGP("nf_ct_q931: Progress\n"); + + if (progress->options & eProgress_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &progress->h245Address); + if (ret < 0) + return -1; + } + + if (progress->options & eProgress_UUIE_fastStart) { + for (i = 0; i < progress->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &progress->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, Q931 *q931) +{ + H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu; + int i; + int ret = 0; + + switch (pdu->h323_message_body.choice) { + case eH323_UU_PDU_h323_message_body_setup: + ret = process_setup(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.setup); + break; + case eH323_UU_PDU_h323_message_body_callProceeding: + ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body. + callProceeding); + break; + case eH323_UU_PDU_h323_message_body_connect: + ret = process_connect(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.connect); + break; + case eH323_UU_PDU_h323_message_body_alerting: + ret = process_alerting(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.alerting); + break; + case eH323_UU_PDU_h323_message_body_information: + ret = process_information(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body. + information); + break; + case eH323_UU_PDU_h323_message_body_facility: + ret = process_facility(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.facility); + break; + case eH323_UU_PDU_h323_message_body_progress: + ret = process_progress(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.progress); + break; + default: + DEBUGP("nf_ct_q931: Q.931 signal %d\n", + pdu->h323_message_body.choice); + break; + } + + if (ret < 0) + return -1; + + if (pdu->options & eH323_UU_PDU_h245Control) { + for (i = 0; i < pdu->h245Control.count; i++) { + ret = process_h245(pskb, ct, ctinfo, data, dataoff, + &pdu->h245Control.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int q931_help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + static Q931 q931; + unsigned char *data = NULL; + int datalen; + int dataoff; + int ret; + + /* 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) { + return NF_ACCEPT; + } + DEBUGP("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); + NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); + + /* Decode Q.931 signal */ + ret = DecodeQ931(data, datalen, &q931); + if (ret < 0) { + if (net_ratelimit()) + printk("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; + } + + /* Process Q.931 signal */ + if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0) + goto drop; + } + + spin_unlock_bh(&nf_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&nf_h323_lock); + if (net_ratelimit()) + printk("nf_ct_q931: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { + { + .name = "Q.931", + .me = THIS_MODULE, + /* T.120 and H.245 */ + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4, + .timeout = 240, + .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 + }, + { + .name = "Q.931", + .me = THIS_MODULE, + /* T.120 and H.245 */ + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4, + .timeout = 240, + .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 + }, +}; + +/****************************************************************************/ +static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff, + int *datalen) +{ + struct udphdr _uh, *uh; + int dataoff; + + uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh); + if (uh == NULL) + return NULL; + dataoff = protoff + sizeof(_uh); + if (dataoff >= (*pskb)->len) + return NULL; + *datalen = (*pskb)->len - dataoff; + return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer); +} + +/****************************************************************************/ +static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, + union nf_conntrack_address *addr, + __be16 port) +{ + struct nf_conntrack_expect *exp; + struct nf_conntrack_tuple tuple; + + memset(&tuple.src.u3, 0, sizeof(tuple.src.u3)); + tuple.src.u.tcp.port = 0; + memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3)); + tuple.dst.u.tcp.port = port; + tuple.dst.protonum = IPPROTO_TCP; + + exp = __nf_conntrack_expect_find(&tuple); + if (exp && exp->master == ct) + return exp; + return NULL; +} + +/****************************************************************************/ +static int set_expect_timeout(struct nf_conntrack_expect *exp, + unsigned timeout) +{ + if (!exp || !del_timer(&exp->timeout)) + return 0; + + exp->timeout.expires = jiffies + timeout * HZ; + add_timer(&exp->timeout); + + return 1; +} + +/****************************************************************************/ +static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress *taddr, int count) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + int i; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + typeof(nat_q931_hook) nat_q931; + + /* Look for the first related address */ + for (i = 0; i < count; i++) { + if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, + sizeof(addr)) == 0 && port != 0) + break; + } + + if (i >= count) /* Not found */ + return 0; + + /* Create expect for Q.931 */ + if ((exp = nf_conntrack_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); + exp->helper = nf_conntrack_helper_q931; + exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ + + nat_q931 = rcu_dereference(nat_q931_hook); + 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) { + DEBUGP("nf_ct_ras: expect Q.931 "); + NF_CT_DUMP_TUPLE(&exp->tuple); + + /* Save port for looking up expect in processing RCF */ + info->sig_port[dir] = port; + } else + ret = -1; + } + + nf_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, GatekeeperRequest *grq) +{ + typeof(set_ras_addr_hook) set_ras_addr; + + DEBUGP("nf_ct_ras: GRQ\n"); + + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ + return set_ras_addr(pskb, ct, ctinfo, data, + &grq->rasAddress, 1); + return 0; +} + +/****************************************************************************/ +static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, GatekeeperConfirm *gcf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + + DEBUGP("nf_ct_ras: GCF\n"); + + if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port)) + return 0; + + /* Registration port is the same as discovery port */ + if (!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && + port == ct->tuplehash[dir].tuple.src.u.udp.port) + return 0; + + /* Avoid RAS expectation loops. A GCF is never expected. */ + if (test_bit(IPS_EXPECTED_BIT, &ct->status)) + return 0; + + /* Need new expect */ + if ((exp = nf_conntrack_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); + exp->helper = nf_conntrack_helper_ras; + + if (nf_conntrack_expect_related(exp) == 0) { + DEBUGP("nf_ct_ras: expect RAS "); + NF_CT_DUMP_TUPLE(&exp->tuple); + } else + ret = -1; + + nf_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RegistrationRequest *rrq) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int ret; + typeof(set_ras_addr_hook) set_ras_addr; + + DEBUGP("nf_ct_ras: RRQ\n"); + + ret = expect_q931(pskb, ct, ctinfo, data, + rrq->callSignalAddress.item, + rrq->callSignalAddress.count); + if (ret < 0) + return -1; + + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr && ct->status & IPS_NAT_MASK) { + ret = set_ras_addr(pskb, ct, ctinfo, data, + rrq->rasAddress.item, + rrq->rasAddress.count); + if (ret < 0) + return -1; + } + + if (rrq->options & eRegistrationRequest_timeToLive) { + DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); + info->timeout = rrq->timeToLive; + } else + info->timeout = default_rrq_ttl; + + return 0; +} + +/****************************************************************************/ +static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RegistrationConfirm *rcf) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret; + struct nf_conntrack_expect *exp; + typeof(set_sig_addr_hook) set_sig_addr; + + DEBUGP("nf_ct_ras: RCF\n"); + + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr && ct->status & IPS_NAT_MASK) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + rcf->callSignalAddress.item, + rcf->callSignalAddress.count); + if (ret < 0) + return -1; + } + + if (rcf->options & eRegistrationConfirm_timeToLive) { + DEBUGP("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); + nf_ct_refresh(ct, *pskb, info->timeout * HZ); + + /* Set expect timeout */ + read_lock_bh(&nf_conntrack_lock); + 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); + NF_CT_DUMP_TUPLE(&exp->tuple); + set_expect_timeout(exp, info->timeout); + } + read_unlock_bh(&nf_conntrack_lock); + } + + return 0; +} + +/****************************************************************************/ +static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, UnregistrationRequest *urq) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret; + typeof(set_sig_addr_hook) set_sig_addr; + + DEBUGP("nf_ct_ras: URQ\n"); + + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr && ct->status & IPS_NAT_MASK) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + urq->callSignalAddress.item, + urq->callSignalAddress.count); + if (ret < 0) + return -1; + } + + /* Clear old expect */ + nf_ct_remove_expectations(ct); + info->sig_port[dir] = 0; + info->sig_port[!dir] = 0; + + /* Give it 30 seconds for UCF or URJ */ + nf_ct_refresh(ct, *pskb, 30 * HZ); + + return 0; +} + +/****************************************************************************/ +static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, AdmissionRequest *arq) +{ + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + __be16 port; + union nf_conntrack_address addr; + typeof(set_h225_addr_hook) set_h225_addr; + + DEBUGP("nf_ct_ras: ARQ\n"); + + set_h225_addr = rcu_dereference(set_h225_addr_hook); + if ((arq->options & eAdmissionRequest_destCallSignalAddress) && + get_h225_addr(ct, *data, &arq->destCallSignalAddress, + &addr, &port) && + !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && + port == info->sig_port[dir] && + set_h225_addr && ct->status & IPS_NAT_MASK) { + /* Answering ARQ */ + return set_h225_addr(pskb, data, 0, + &arq->destCallSignalAddress, + &ct->tuplehash[!dir].tuple.dst.u3, + info->sig_port[!dir]); + } + + if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && + get_h225_addr(ct, *data, &arq->srcCallSignalAddress, + &addr, &port) && + !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && + set_h225_addr && ct->status & IPS_NAT_MASK) { + /* Calling ARQ */ + return set_h225_addr(pskb, data, 0, + &arq->srcCallSignalAddress, + &ct->tuplehash[!dir].tuple.dst.u3, + port); + } + + return 0; +} + +/****************************************************************************/ +static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, AdmissionConfirm *acf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + typeof(set_sig_addr_hook) set_sig_addr; + + DEBUGP("nf_ct_ras: ACF\n"); + + if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress, + &addr, &port)) + return 0; + + if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) { + /* Answering ACF */ + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr && ct->status & IPS_NAT_MASK) + return set_sig_addr(pskb, ct, ctinfo, data, + &acf->destCallSignalAddress, 1); + return 0; + } + + /* Need new expect */ + if ((exp = nf_conntrack_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); + exp->flags = NF_CT_EXPECT_PERMANENT; + exp->helper = nf_conntrack_helper_q931; + + if (nf_conntrack_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); + + return ret; +} + +/****************************************************************************/ +static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, LocationRequest *lrq) +{ + typeof(set_ras_addr_hook) set_ras_addr; + + DEBUGP("nf_ct_ras: LRQ\n"); + + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr && ct->status & IPS_NAT_MASK) + return set_ras_addr(pskb, ct, ctinfo, data, + &lrq->replyAddress, 1); + return 0; +} + +/****************************************************************************/ +static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, LocationConfirm *lcf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + __be16 port; + union nf_conntrack_address addr; + struct nf_conntrack_expect *exp; + + DEBUGP("nf_ct_ras: LCF\n"); + + if (!get_h225_addr(ct, *data, &lcf->callSignalAddress, + &addr, &port)) + return 0; + + /* Need new expect for call signal */ + if ((exp = nf_conntrack_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); + exp->flags = NF_CT_EXPECT_PERMANENT; + exp->helper = nf_conntrack_helper_q931; + + if (nf_conntrack_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); + + /* Ignore rasAddress */ + + return ret; +} + +/****************************************************************************/ +static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, InfoRequestResponse *irr) +{ + int ret; + typeof(set_ras_addr_hook) set_ras_addr; + typeof(set_sig_addr_hook) set_sig_addr; + + DEBUGP("nf_ct_ras: IRR\n"); + + set_ras_addr = rcu_dereference(set_ras_addr_hook); + if (set_ras_addr && ct->status & IPS_NAT_MASK) { + ret = set_ras_addr(pskb, ct, ctinfo, data, + &irr->rasAddress, 1); + if (ret < 0) + return -1; + } + + set_sig_addr = rcu_dereference(set_sig_addr_hook); + if (set_sig_addr && ct->status & IPS_NAT_MASK) { + ret = set_sig_addr(pskb, ct, ctinfo, data, + irr->callSignalAddress.item, + irr->callSignalAddress.count); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RasMessage *ras) +{ + switch (ras->choice) { + case eRasMessage_gatekeeperRequest: + return process_grq(pskb, ct, ctinfo, data, + &ras->gatekeeperRequest); + case eRasMessage_gatekeeperConfirm: + return process_gcf(pskb, ct, ctinfo, data, + &ras->gatekeeperConfirm); + case eRasMessage_registrationRequest: + return process_rrq(pskb, ct, ctinfo, data, + &ras->registrationRequest); + case eRasMessage_registrationConfirm: + return process_rcf(pskb, ct, ctinfo, data, + &ras->registrationConfirm); + case eRasMessage_unregistrationRequest: + return process_urq(pskb, ct, ctinfo, data, + &ras->unregistrationRequest); + case eRasMessage_admissionRequest: + return process_arq(pskb, ct, ctinfo, data, + &ras->admissionRequest); + case eRasMessage_admissionConfirm: + return process_acf(pskb, ct, ctinfo, data, + &ras->admissionConfirm); + case eRasMessage_locationRequest: + return process_lrq(pskb, ct, ctinfo, data, + &ras->locationRequest); + case eRasMessage_locationConfirm: + return process_lcf(pskb, ct, ctinfo, data, + &ras->locationConfirm); + case eRasMessage_infoRequestResponse: + return process_irr(pskb, ct, ctinfo, data, + &ras->infoRequestResponse); + default: + DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice); + break; + } + + return 0; +} + +/****************************************************************************/ +static int ras_help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + static RasMessage ras; + unsigned char *data; + int datalen = 0; + int ret; + + DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len); + + spin_lock_bh(&nf_h323_lock); + + /* Get UDP data */ + data = get_udp_data(pskb, protoff, &datalen); + if (data == NULL) + goto accept; + DEBUGP("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) { + if (net_ratelimit()) + printk("nf_ct_ras: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); + goto accept; + } + + /* Process RAS message */ + if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) + goto drop; + + accept: + spin_unlock_bh(&nf_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&nf_h323_lock); + if (net_ratelimit()) + printk("nf_ct_ras: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { + { + .name = "RAS", + .me = THIS_MODULE, + .max_expected = 32, + .timeout = 240, + .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, + }, + { + .name = "RAS", + .me = THIS_MODULE, + .max_expected = 32, + .timeout = 240, + .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, + }, +}; + +/****************************************************************************/ +static void __exit nf_conntrack_h323_fini(void) +{ + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]); + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); + 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"); +} + +/****************************************************************************/ +static int __init nf_conntrack_h323_init(void) +{ + int ret; + + h323_buffer = kmalloc(65536, GFP_KERNEL); + if (!h323_buffer) + return -ENOMEM; + ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]); + if (ret < 0) + goto err1; + ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]); + if (ret < 0) + goto err2; + ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]); + if (ret < 0) + goto err3; + ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); + if (ret < 0) + goto err4; + DEBUGP("nf_ct_h323: init success\n"); + return 0; + +err4: + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); +err3: + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); +err2: + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); +err1: + return ret; +} + +/****************************************************************************/ +module_init(nf_conntrack_h323_init); +module_exit(nf_conntrack_h323_fini); + +EXPORT_SYMBOL_GPL(get_h225_addr); +EXPORT_SYMBOL_GPL(set_h245_addr_hook); +EXPORT_SYMBOL_GPL(set_h225_addr_hook); +EXPORT_SYMBOL_GPL(set_sig_addr_hook); +EXPORT_SYMBOL_GPL(set_ras_addr_hook); +EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); +EXPORT_SYMBOL_GPL(nat_t120_hook); +EXPORT_SYMBOL_GPL(nat_h245_hook); +EXPORT_SYMBOL_GPL(nat_callforwarding_hook); +EXPORT_SYMBOL_GPL(nat_q931_hook); + +MODULE_AUTHOR("Jing Min Zhao "); +MODULE_DESCRIPTION("H.323 connection tracking helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_h323"); diff --git a/net/netfilter/nf_conntrack_h323_types.c b/net/netfilter/nf_conntrack_h323_types.c new file mode 100644 index 000000000000..4c6f8b3b1208 --- /dev/null +++ b/net/netfilter/nf_conntrack_h323_types.c @@ -0,0 +1,1927 @@ +/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006 + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + */ + +static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE, + offsetof(TransportAddress_ipAddress, ip), NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */ + {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */ + {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, + _TransportAddress_ipSourceRoute_route}, + {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _TransportAddress_ipSourceRoute_routing}, +}; + +static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */ + {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, + {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE, + offsetof(TransportAddress_ip6Address, ip6), NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H221NonStandard[] = { /* SEQUENCE */ + {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _NonStandardIdentifier[] = { /* CHOICE */ + {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0, + _H221NonStandard}, +}; + +static field_t _NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _NonStandardIdentifier}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress[] = { /* CHOICE */ + {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE, + offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress}, + {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0, + _TransportAddress_ipSourceRoute}, + {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0, + _TransportAddress_ipxAddress}, + {FNAME("ip6Address") SEQ, 0, 2, 2, DECODE | EXT, + offsetof(TransportAddress, ip6Address), _TransportAddress_ip6Address}, + {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, + _NonStandardParameter}, +}; + +static field_t _AliasAddress[] = { /* CHOICE */ + {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL}, + {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL}, + {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL}, +}; + +static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _VendorIdentifier[] = { /* SEQUENCE */ + {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard}, + {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _GatekeeperInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _H310Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H320Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H321Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H322Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H323Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H324Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _VoiceCaps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T120OnlyCaps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _SupportedProtocols[] = { /* CHOICE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0, + _NonStandardParameter}, + {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps}, + {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps}, + {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps}, + {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps}, + {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps}, + {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps}, + {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps}, + {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps}, + {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL}, +}; + +static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols}, +}; + +static field_t _GatewayInfo[] = { /* SEQUENCE */ + {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _GatewayInfo_protocol}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _McuInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _TerminalInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _EndpointType[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0, + _VendorIdentifier}, + {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, + _GatekeeperInfo}, + {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo}, + {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo}, + {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo}, + {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, + 0, NULL}, +}; + +static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */ + {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ + {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP, + 0, NULL}, +}; + +static field_t _Q954Details[] = { /* SEQUENCE */ + {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _QseriesOptions[] = { /* SEQUENCE */ + {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details}, +}; + +static field_t _CallType[] = { /* CHOICE */ + {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */ + {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */ + {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0, + _H245_NonStandardIdentifier_h221NonStandard}, +}; + +static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0, + _H245_NonStandardIdentifier}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H261VideoCapability[] = { /* SEQUENCE */ + {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H262VideoCapability[] = { /* SEQUENCE */ + {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H263VideoCapability[] = { /* SEQUENCE */ + {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _IS11172VideoCapability[] = { /* SEQUENCE */ + {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _VideoCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0, + _H261VideoCapability}, + {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0, + _H262VideoCapability}, + {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0, + _H263VideoCapability}, + {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0, + _IS11172VideoCapability}, + {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _AudioCapability_g7231[] = { /* SEQUENCE */ + {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _IS11172AudioCapability[] = { /* SEQUENCE */ + {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _IS13818AudioCapability[] = { /* SEQUENCE */ + {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _AudioCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231}, + {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0, + _IS11172AudioCapability}, + {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0, + _IS13818AudioCapability}, + {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, + {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL}, +}; + +static field_t _DataProtocolCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ + {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T84Profile[] = { /* CHOICE */ + {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0, + _T84Profile_t84Restricted}, +}; + +static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */ + {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile}, +}; + +static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */ + {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _DataApplicationCapability_application[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT, + offsetof(DataApplicationCapability_application, t120), + _DataProtocolCapability}, + {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0, + _DataApplicationCapability_application_t84}, + {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0, + _DataApplicationCapability_application_nlpid}, + {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, + {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, + {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _DataApplicationCapability[] = { /* SEQUENCE */ + {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT, + offsetof(DataApplicationCapability, application), + _DataApplicationCapability_application}, + {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _EncryptionMode[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _DataType[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability}, + {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0, + _AudioCapability}, + {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data), + _DataApplicationCapability}, + {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _EncryptionMode}, + {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, + {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, +}; + +static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */ + {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL}, + {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0, + _H223LogicalChannelParameters_adaptationLayerType_al3}, + {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL}, + {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, + {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0, + _H223LogicalChannelParameters_adaptationLayerType}, + {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CRCLength[] = { /* CHOICE */ + {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76HDLCParameters[] = { /* SEQUENCE */ + {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength}, + {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */ + {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */ + {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */ + {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode_eRM_recovery}, +}; + +static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */ + {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode_eRM}, + {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V75Parameters[] = { /* SEQUENCE */ + {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0, + _V76HDLCParameters}, + {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _V76LogicalChannelParameters_suspendResume}, + {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode}, + {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters}, +}; + +static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, +}; + +static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE, + offsetof(UnicastAddress_iPAddress, network), NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */ + {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, + {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */ + {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */ + {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ + {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0, + _UnicastAddress_iPSourceRouteAddress_routing}, + {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, + _UnicastAddress_iPSourceRouteAddress_route}, +}; + +static field_t _UnicastAddress[] = { /* CHOICE */ + {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT, + offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress}, + {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0, + _UnicastAddress_iPXAddress}, + {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, + _UnicastAddress_iP6Address}, + {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0, + _UnicastAddress_iPSourceRouteAddress}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress[] = { /* CHOICE */ + {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0, + _MulticastAddress_iPAddress}, + {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, + _MulticastAddress_iP6Address}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, +}; + +static field_t _H245_TransportAddress[] = { /* CHOICE */ + {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT, + offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress}, + {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0, + _MulticastAddress}, +}; + +static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _H2250LogicalChannelParameters_nonStandard}, + {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelParameters, mediaChannel), + _H245_TransportAddress}, + {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelParameters, mediaControlChannel), + _H245_TransportAddress}, + {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT, + 0, NULL}, + {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL}, + {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, + NULL}, + {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, + _H222LogicalChannelParameters}, + {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, + _H223LogicalChannelParameters}, + {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, + _V76LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, + {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT, + offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, + dataType), _DataType}, + {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT, + offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters}, + {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, + 0, NULL}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, + _H223LogicalChannelParameters}, + {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, + _V76LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, +}; + +static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType}, + {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT, + offsetof(OpenLogicalChannel_reverseLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters}, + {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, + 0, NULL}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */ + {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Q2931Address_address[] = { /* CHOICE */ + {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL}, + {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _Q2931Address[] = { /* SEQUENCE */ + {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _Q2931Address_address}, + {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ + {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address}, + {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT, + offsetof(NetworkAccessParameters_networkAddress, localAreaAddress), + _H245_TransportAddress}, +}; + +static field_t _NetworkAccessParameters[] = { /* SEQUENCE */ + {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, + _NetworkAccessParameters_distribution}, + {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT, + offsetof(NetworkAccessParameters, networkAddress), + _NetworkAccessParameters_networkAddress}, + {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, +}; + +static field_t _OpenLogicalChannel[] = { /* SEQUENCE */ + {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT, + offsetof(OpenLogicalChannel, forwardLogicalChannelParameters), + _OpenLogicalChannel_forwardLogicalChannelParameters}, + {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4, + DECODE | EXT | OPT, offsetof(OpenLogicalChannel, + reverseLogicalChannelParameters), + _OpenLogicalChannel_reverseLogicalChannelParameters}, + {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT, + offsetof(OpenLogicalChannel, separateStack), + _NetworkAccessParameters}, + {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Setup_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, h245Address), _TransportAddress}, + {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_sourceAddress}, + {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destinationAddress}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destExtraCallInfo}, + {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destExtraCRV}, + {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0, + _Setup_UUIE_conferenceGoal}, + {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0, + _QseriesOptions}, + {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, + {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress}, + {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart}, + {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, +}; + +static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(CallProceeding_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(CallProceeding_UUIE, fastStart), + _CallProceeding_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Connect_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Connect_UUIE, h245Address), _TransportAddress}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Alerting_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Alerting_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Information_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _ReleaseCompleteReason[] = { /* CHOICE */ + {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0, + NULL}, + {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0, + _ReleaseCompleteReason}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _FacilityReason[] = { /* CHOICE */ + {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Facility_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Facility_UUIE, alternativeAddress), _TransportAddress}, + {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Facility_UUIE_alternativeAliasAddress}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, + {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT, + offsetof(Facility_UUIE, reason), _FacilityReason}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Facility_UUIE, h245Address), _TransportAddress}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, +}; + +static field_t _CallIdentifier[] = { /* SEQUENCE */ + {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, +}; + +static field_t _SecurityServiceMode[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, + {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _SecurityCapabilities[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, + {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, + {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, +}; + +static field_t _H245Security[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, + {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, + {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, +}; + +static field_t _DHset[] = { /* SEQUENCE */ + {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TypedCertificate[] = { /* SEQUENCE */ + {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _ClearToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset}, + {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL}, + {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, + _TypedCertificate}, + {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, + _H235_NonStandardParameter}, + {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, +}; + +static field_t _Params[] = { /* SEQUENCE */ + {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL}, + {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */ + {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdHash_token}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */ + {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdHash_token}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoEncryptedToken_token}, +}; + +static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 4, 4, SKIP, 0, + _CryptoToken_cryptoSignedToken_token}, +}; + +static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoHashedToken_token}, +}; + +static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken[] = { /* CHOICE */ + {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0, + _CryptoToken_cryptoEncryptedToken}, + {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0, + _CryptoToken_cryptoSignedToken}, + {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoHashedToken}, + {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoPwdEncr}, +}; + +static field_t _CryptoH323Token[] = { /* CHOICE */ + {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdHash}, + {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdHash}, + {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdEncr}, + {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdEncr}, + {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoEPCert}, + {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoGKCert}, + {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoFastStart}, + {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0, + _CryptoToken}, +}; + +static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token}, +}; + +static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Progress_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Progress_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, + _CallIdentifier}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + _H245Security}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Progress_UUIE_tokens}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Progress_UUIE_cryptoTokens}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ + {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE}, + {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, callProceeding), + _CallProceeding_UUIE}, + {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE}, + {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE}, + {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, information), + _Information_UUIE}, + {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0, + _ReleaseComplete_UUIE}, + {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE}, + {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE}, + {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, +}; + +static field_t _RequestMessage[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT, + offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel}, + {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL}, + {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL}, + {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL}, + {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, + {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0, + NULL}, +}; + +static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, + _H222LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, +}; + +static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT, + offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, +}; + +static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _H2250LogicalChannelAckParameters_nonStandard}, + {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelAckParameters, mediaChannel), + _H245_TransportAddress}, + {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelAckParameters, mediaControlChannel), + _H245_TransportAddress}, + {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL}, + {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */ + {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT, + offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters, + h2250LogicalChannelAckParameters), + _H2250LogicalChannelAckParameters}, +}; + +static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ + {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4, + DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, + reverseLogicalChannelParameters), + _OpenLogicalChannelAck_reverseLogicalChannelParameters}, + {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL}, + {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1, + DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, + forwardMultiplexAckParameters), + _OpenLogicalChannelAck_forwardMultiplexAckParameters}, + {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _ResponseMessage[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT, + offsetof(ResponseMessage, openLogicalChannelAck), + _OpenLogicalChannelAck}, + {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, + {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0, + NULL}, + {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL}, +}; + +static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ + {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT, + offsetof(MultimediaSystemControlMessage, request), _RequestMessage}, + {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT, + offsetof(MultimediaSystemControlMessage, response), + _ResponseMessage}, + {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL}, + {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL}, +}; + +static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT, + sizeof(MultimediaSystemControlMessage), + _MultimediaSystemControlMessage} + , +}; + +static field_t _H323_UU_PDU[] = { /* SEQUENCE */ + {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT, + offsetof(H323_UU_PDU, h323_message_body), + _H323_UU_PDU_h323_message_body}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT, + offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control}, + {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT, + 0, NULL}, + {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT, + 0, NULL}, + {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _H323_UserInformation[] = { /* SEQUENCE */ + {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT, + offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU}, + {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _GatekeeperRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(GatekeeperRequest, rasAddress), _TransportAddress}, + {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _GatekeeperConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(GatekeeperConfirm, rasAddress), _TransportAddress}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _RegistrationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationRequest, callSignalAddress), + _RegistrationRequest_callSignalAddress}, + {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationRequest, rasAddress), + _RegistrationRequest_rasAddress}, + {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _RegistrationRequest_terminalAlias}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0, + _VendorIdentifier}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, + offsetof(RegistrationRequest, timeToLive), NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, + NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _RegistrationConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationConfirm, callSignalAddress), + _RegistrationConfirm_callSignalAddress}, + {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _RegistrationConfirm_terminalAlias}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, + offsetof(RegistrationConfirm, timeToLive), NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0, + NULL}, + {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _UnregistrationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(UnregistrationRequest, callSignalAddress), + _UnregistrationRequest_callSignalAddress}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL}, + {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _CallModel[] = { /* CHOICE */ + {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, + {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _AdmissionRequest_destinationInfo}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(AdmissionRequest, destCallSignalAddress), + _TransportAddress}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _AdmissionRequest_destExtraCallInfo}, + {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0, + _AdmissionRequest_srcInfo}, + {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress}, + {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL}, + {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL}, + {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _AdmissionConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL}, + {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(AdmissionConfirm, destCallSignalAddress), + _TransportAddress}, + {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _LocationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0, + _LocationRequest_destinationInfo}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationRequest, replyAddress), _TransportAddress}, + {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _LocationConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationConfirm, callSignalAddress), _TransportAddress}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationConfirm, rasAddress), _TransportAddress}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _InfoRequestResponse[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(InfoRequestResponse, rasAddress), _TransportAddress}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(InfoRequestResponse, callSignalAddress), + _InfoRequestResponse_callSignalAddress}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RasMessage[] = { /* CHOICE */ + {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT, + offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest}, + {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT, + offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm}, + {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, + {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT, + offsetof(RasMessage, registrationRequest), _RegistrationRequest}, + {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT, + offsetof(RasMessage, registrationConfirm), _RegistrationConfirm}, + {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, + {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT, + offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest}, + {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL}, + {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT, + offsetof(RasMessage, admissionRequest), _AdmissionRequest}, + {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT, + offsetof(RasMessage, admissionConfirm), _AdmissionConfirm}, + {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL}, + {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL}, + {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL}, + {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL}, + {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL}, + {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT, + offsetof(RasMessage, locationRequest), _LocationRequest}, + {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT, + offsetof(RasMessage, locationConfirm), _LocationConfirm}, + {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL}, + {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL}, + {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT, + offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse}, + {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL}, + {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL}, + {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL}, + {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0, + NULL}, + {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0, + NULL}, + {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL}, + {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0, + NULL}, + {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL}, +}; -- cgit v1.2.3-70-g09d2 From 869f37d8e48f3911eb70f38a994feaa8f8380008 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:09:06 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add IRC helper port Add nf_conntrack port of the IRC conntrack/NAT helper. Since DCC doesn't support IPv6 yet, the helper is still IPv4 only. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_irc.h | 15 ++ net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 1 + net/ipv4/netfilter/nf_nat_irc.c | 101 +++++++++++ net/netfilter/Kconfig | 15 ++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_irc.c | 281 +++++++++++++++++++++++++++++ 7 files changed, 419 insertions(+) create mode 100644 include/linux/netfilter/nf_conntrack_irc.h create mode 100644 net/ipv4/netfilter/nf_nat_irc.c create mode 100644 net/netfilter/nf_conntrack_irc.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h new file mode 100644 index 000000000000..2ab6b8255911 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_irc.h @@ -0,0 +1,15 @@ +#ifndef _NF_CONNTRACK_IRC_H +#define _NF_CONNTRACK_IRC_H + +#ifdef __KERNEL__ + +#define IRC_PORT 6667 + +extern unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp); + +#endif /* __KERNEL__ */ +#endif /* _NF_CONNTRACK_IRC_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index e14156d1122e..4555f721dfc1 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -500,6 +500,11 @@ config IP_NF_NAT_IRC default IP_NF_NAT if IP_NF_IRC=y default m if IP_NF_IRC=m +config NF_NAT_IRC + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_IRC + config IP_NF_NAT_TFTP tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index bdaba4700e3b..56733c370327 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o +obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c new file mode 100644 index 000000000000..9b8c0daea744 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_irc.c @@ -0,0 +1,101 @@ +/* IRC extension for TCP NAT alteration. + * + * (C) 2000-2001 by Harald Welte + * (C) 2004 Rusty Russell IBM Corporation + * based on a copy of RR's ip_nat_ftp.c + * + * 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 + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("IRC (DCC) NAT helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_nat_irc"); + +static unsigned int help(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp) +{ + char buffer[sizeof("4294967296 65635")]; + u_int32_t ip; + 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; + exp->expectfn = nf_nat_follow_master; + + /* 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) + break; + } + + if (port == 0) + return NF_DROP; + + 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); + + ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, + matchoff, matchlen, buffer, + strlen(buffer)); + if (ret != NF_ACCEPT) + nf_conntrack_unexpect_related(exp); + return ret; +} + +static void __exit nf_nat_irc_fini(void) +{ + rcu_assign_pointer(nf_nat_irc_hook, NULL); + synchronize_rcu(); +} + +static int __init nf_nat_irc_init(void) +{ + BUG_ON(rcu_dereference(nf_nat_irc_hook)); + rcu_assign_pointer(nf_nat_irc_hook, help); + return 0; +} + +/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */ +static int warn_set(const char *val, struct kernel_param *kp) +{ + printk(KERN_INFO KBUILD_MODNAME + ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n"); + return 0; +} +module_param_call(ports, warn_set, NULL, NULL, 0); + +module_init(nf_nat_irc_init); +module_exit(nf_nat_irc_fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d8f3451c95b6..bd50897d8fbb 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -179,6 +179,21 @@ config NF_CONNTRACK_H323 To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_IRC + tristate "IRC protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + help + There is a commonly-used extension to IRC called + Direct Client-to-Client Protocol (DCC). This enables users to send + files to each other, and also chat to each other without the need + of a server. DCC Sending is used anywhere you send files over IRC, + and DCC Chat is most commonly used by Eggdrop bots. If you are + using NAT, this extension will enable you to send files and initiate + chats. Note that you do NOT need this extension to get files or + have others initiate chats, or everything else in IRC. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 69b554576b6b..343fd4896406 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -25,6 +25,7 @@ nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o +obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c new file mode 100644 index 000000000000..ed01db634399 --- /dev/null +++ b/net/netfilter/nf_conntrack_irc.c @@ -0,0 +1,281 @@ +/* IRC extension for IP connection tracking, Version 1.21 + * (C) 2000-2002 by Harald Welte + * based on RR's ip_conntrack_ftp.c + * + * 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 + +#define MAX_PORTS 8 +static unsigned short ports[MAX_PORTS]; +static int ports_c; +static unsigned int max_dcc_channels = 8; +static unsigned int dcc_timeout __read_mostly = 300; +/* This is slow, but it's simple. --RR */ +static char *irc_buffer; +static DEFINE_SPINLOCK(irc_buffer_lock); + +unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct nf_conntrack_expect *exp) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_irc_hook); + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_irc"); + +module_param_array(ports, ushort, &ports_c, 0400); +MODULE_PARM_DESC(ports, "port numbers of IRC servers"); +module_param(max_dcc_channels, uint, 0400); +MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per " + "IRC session"); +module_param(dcc_timeout, uint, 0400); +MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); + +static const char *dccprotos[] = { + "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " +}; + +#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 + * data_end pointer to last byte of dcc command data + * ip returns parsed ip of dcc command + * port returns parsed port of dcc command + * ad_beg_p returns pointer to first byte of addr data + * ad_end_p returns pointer to last byte of addr data + */ +static int parse_dcc(char *data, char *data_end, u_int32_t *ip, + u_int16_t *port, char **ad_beg_p, char **ad_end_p) +{ + /* at least 12: "AAAAAAAA P\1\n" */ + while (*data++ != ' ') + if (data > data_end - 12) + return -1; + + *ad_beg_p = data; + *ip = simple_strtoul(data, &data, 10); + + /* skip blanks between ip and port */ + while (*data == ' ') { + if (data >= data_end) + return -1; + data++; + } + + *port = simple_strtoul(data, &data, 10); + *ad_end_p = data; + + return 0; +} + +static int help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + unsigned int dataoff; + struct tcphdr _tcph, *th; + char *data, *data_limit, *ib_ptr; + int dir = CTINFO2DIR(ctinfo); + struct nf_conntrack_expect *exp; + struct nf_conntrack_tuple *tuple; + u_int32_t dcc_ip; + u_int16_t dcc_port; + __be16 port; + int i, ret = NF_ACCEPT; + char *addr_beg_p, *addr_end_p; + typeof(nf_nat_irc_hook) nf_nat_irc; + + /* If packet is coming from IRC server */ + if (dir == IP_CT_DIR_REPLY) + return NF_ACCEPT; + + /* 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) + return NF_ACCEPT; + + /* Not a full tcp header? */ + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) + return NF_ACCEPT; + + /* No data? */ + dataoff = protoff + th->doff*4; + if (dataoff >= (*pskb)->len) + return NF_ACCEPT; + + spin_lock_bh(&irc_buffer_lock); + ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, + irc_buffer); + BUG_ON(ib_ptr == NULL); + + data = ib_ptr; + data_limit = ib_ptr + (*pskb)->len - dataoff; + + /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 + * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ + while (data < data_limit - (19 + MINMATCHLEN)) { + if (memcmp(data, "\1DCC ", 5)) { + data++; + continue; + } + 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)); + + for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { + if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { + /* no match */ + continue; + } + data += strlen(dccprotos[i]); + DEBUGP("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"); + continue; + } + DEBUGP("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; + if (tuple->src.u3.ip != htonl(dcc_ip) && + tuple->dst.u3.ip != htonl(dcc_ip)) { + if (net_ratelimit()) + printk(KERN_WARNING + "Forged DCC command from " + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n", + NIPQUAD(tuple->src.u3.ip), + HIPQUAD(dcc_ip), dcc_port); + continue; + } + + exp = nf_conntrack_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_nat_irc = rcu_dereference(nf_nat_irc_hook); + if (nf_nat_irc && ct->status & IPS_NAT_MASK) + ret = nf_nat_irc(pskb, ctinfo, + addr_beg_p - ib_ptr, + addr_end_p - addr_beg_p, + exp); + else if (nf_conntrack_expect_related(exp) != 0) + ret = NF_DROP; + nf_conntrack_expect_put(exp); + goto out; + } + } + out: + spin_unlock_bh(&irc_buffer_lock); + return ret; +} + +static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly; +static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly; + +static void nf_conntrack_irc_fini(void); + +static int __init nf_conntrack_irc_init(void) +{ + int i, ret; + char *tmpname; + + if (max_dcc_channels < 1) { + printk("nf_ct_irc: max_dcc_channels must not be zero\n"); + return -EINVAL; + } + + irc_buffer = kmalloc(65536, GFP_KERNEL); + if (!irc_buffer) + return -ENOMEM; + + /* If no port given, default to standard irc port */ + if (ports_c == 0) + ports[ports_c++] = IRC_PORT; + + for (i = 0; i < ports_c; i++) { + 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; + irc[i].help = help; + + tmpname = &irc_names[i][0]; + if (ports[i] == IRC_PORT) + sprintf(tmpname, "irc"); + else + sprintf(tmpname, "irc-%u", i); + irc[i].name = tmpname; + + ret = nf_conntrack_helper_register(&irc[i]); + if (ret) { + printk("nf_ct_irc: failed to register helper " + "for pf: %u port: %u\n", + irc[i].tuple.src.l3num, ports[i]); + nf_conntrack_irc_fini(); + return ret; + } + } + return 0; +} + +/* This function is intentionally _NOT_ defined as __exit, because + * it is needed by the init function */ +static void nf_conntrack_irc_fini(void) +{ + int i; + + for (i = 0; i < ports_c; i++) + nf_conntrack_helper_unregister(&irc[i]); + kfree(irc_buffer); +} + +module_init(nf_conntrack_irc_init); +module_exit(nf_conntrack_irc_fini); -- cgit v1.2.3-70-g09d2 From 92703eee4ccde3c55ee067a89c373e8a51a8adf9 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:09:24 -0800 Subject: [NETFILTER]: nf_conntrack: add NetBIOS name service helper port Add nf_conntrack port of the NetBIOS name service conntrack helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/Kconfig | 19 +++++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_netbios_ns.c | 125 ++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 net/netfilter/nf_conntrack_netbios_ns.c (limited to 'net') diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index bd50897d8fbb..d1a365d83c53 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -194,6 +194,25 @@ config NF_CONNTRACK_IRC To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_NETBIOS_NS + tristate "NetBIOS name service protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + help + NetBIOS name service requests are sent as broadcast messages from an + unprivileged port and responded to with unicast messages to the + same port. This make them hard to firewall properly because connection + tracking doesn't deal with broadcasts. This helper tracks locally + originating NetBIOS name service requests and the corresponding + responses. It relies on correct IP address configuration, specifically + netmask and broadcast address. When properly configured, the output + of "ip address show" should look similar to this: + + $ ip -4 address show eth0 + 4: eth0: mtu 1500 qdisc pfifo_fast qlen 1000 + inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0 + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 343fd4896406..67144b2af647 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o +obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c new file mode 100644 index 000000000000..4fad3ad0b886 --- /dev/null +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -0,0 +1,125 @@ +/* + * NetBIOS name service broadcast connection tracking helper + * + * (c) 2005 Patrick McHardy + * + * 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. + */ +/* + * This helper tracks locally originating NetBIOS name service + * requests by issuing permanent expectations (valid until + * timing out) matching all reply connections from the + * destination network. The only NetBIOS specific thing is + * actually the port number. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define NMBD_PORT 137 + +MODULE_AUTHOR("Patrick McHardy "); +MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_netbios_ns"); + +static unsigned int timeout __read_mostly = 3; +module_param(timeout, uint, 0400); +MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); + +static int help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + struct nf_conntrack_expect *exp; + struct iphdr *iph = (*pskb)->nh.iph; + struct rtable *rt = (struct rtable *)(*pskb)->dst; + struct in_device *in_dev; + __be32 mask = 0; + + /* we're only interested in locally generated packets */ + if ((*pskb)->sk == NULL) + goto out; + if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) + goto out; + if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) + goto out; + + rcu_read_lock(); + in_dev = __in_dev_get_rcu(rt->u.dst.dev); + if (in_dev != NULL) { + for_primary_ifa(in_dev) { + if (ifa->ifa_broadcast == iph->daddr) { + mask = ifa->ifa_mask; + break; + } + } endfor_ifa(in_dev); + } + rcu_read_unlock(); + + if (mask == 0) + goto out; + + exp = nf_conntrack_expect_alloc(ct); + if (exp == NULL) + goto out; + + exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + exp->tuple.src.u.udp.port = htons(NMBD_PORT); + + 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; + + nf_conntrack_expect_related(exp); + nf_conntrack_expect_put(exp); + + nf_ct_refresh(ct, *pskb, timeout * HZ); +out: + return NF_ACCEPT; +} + +static struct nf_conntrack_helper helper __read_mostly = { + .name = "netbios-ns", + .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, +}; + +static int __init nf_conntrack_netbios_ns_init(void) +{ + helper.timeout = timeout; + return nf_conntrack_helper_register(&helper); +} + +static void __exit nf_conntrack_netbios_ns_fini(void) +{ + nf_conntrack_helper_unregister(&helper); +} + +module_init(nf_conntrack_netbios_ns_init); +module_exit(nf_conntrack_netbios_ns_fini); -- cgit v1.2.3-70-g09d2 From f09943fefe6b702e40893d35b4f10fd1064037fe Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:09:41 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add PPTP helper port Add nf_conntrack port of the PPtP conntrack/NAT helper. Since there seems to be no IPv6-capable PPtP implementation the helper only support IPv4. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_pptp.h | 321 ++++++++++++ include/linux/netfilter/nf_conntrack_proto_gre.h | 112 +++++ include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 2 + include/net/netfilter/nf_conntrack.h | 4 + include/net/netfilter/nf_conntrack_helper.h | 2 + include/net/netfilter/nf_conntrack_tuple.h | 6 + net/ipv4/netfilter/Kconfig | 10 + net/ipv4/netfilter/Makefile | 4 + net/ipv4/netfilter/nf_nat_pptp.c | 315 ++++++++++++ net/ipv4/netfilter/nf_nat_proto_gre.c | 179 +++++++ net/netfilter/Kconfig | 23 + net/netfilter/Makefile | 2 + net/netfilter/nf_conntrack_core.c | 4 + net/netfilter/nf_conntrack_pptp.c | 607 +++++++++++++++++++++++ net/netfilter/nf_conntrack_proto_gre.c | 305 ++++++++++++ 15 files changed, 1896 insertions(+) create mode 100644 include/linux/netfilter/nf_conntrack_pptp.h create mode 100644 include/linux/netfilter/nf_conntrack_proto_gre.h create mode 100644 net/ipv4/netfilter/nf_nat_pptp.c create mode 100644 net/ipv4/netfilter/nf_nat_proto_gre.c create mode 100644 net/netfilter/nf_conntrack_pptp.c create mode 100644 net/netfilter/nf_conntrack_proto_gre.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h new file mode 100644 index 000000000000..fb049ec11ff2 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -0,0 +1,321 @@ +/* PPTP constants and structs */ +#ifndef _NF_CONNTRACK_PPTP_H +#define _NF_CONNTRACK_PPTP_H + +/* state of the control session */ +enum pptp_ctrlsess_state { + PPTP_SESSION_NONE, /* no session present */ + PPTP_SESSION_ERROR, /* some session error */ + PPTP_SESSION_STOPREQ, /* stop_sess request seen */ + PPTP_SESSION_REQUESTED, /* start_sess request seen */ + PPTP_SESSION_CONFIRMED, /* session established */ +}; + +/* state of the call inside the control session */ +enum pptp_ctrlcall_state { + PPTP_CALL_NONE, + PPTP_CALL_ERROR, + PPTP_CALL_OUT_REQ, + PPTP_CALL_OUT_CONF, + PPTP_CALL_IN_REQ, + PPTP_CALL_IN_REP, + PPTP_CALL_IN_CONF, + PPTP_CALL_CLEAR_REQ, +}; + +/* conntrack private data */ +struct nf_ct_pptp_master { + enum pptp_ctrlsess_state sstate; /* session state */ + enum pptp_ctrlcall_state cstate; /* call state */ + __be16 pac_call_id; /* call id of PAC */ + __be16 pns_call_id; /* call id of PNS */ + + /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack + * and therefore imposes a fixed limit on the number of maps */ + struct nf_ct_gre_keymap *keymap[IP_CT_DIR_MAX]; +}; + +struct nf_nat_pptp { + __be16 pns_call_id; /* NAT'ed PNS call id */ + __be16 pac_call_id; /* NAT'ed PAC call id */ +}; + +#ifdef __KERNEL__ + +#define PPTP_CONTROL_PORT 1723 + +#define PPTP_PACKET_CONTROL 1 +#define PPTP_PACKET_MGMT 2 + +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d + +struct pptp_pkt_hdr { + __u16 packetLength; + __be16 packetType; + __be32 magicCookie; +}; + +/* PptpControlMessageType values */ +#define PPTP_START_SESSION_REQUEST 1 +#define PPTP_START_SESSION_REPLY 2 +#define PPTP_STOP_SESSION_REQUEST 3 +#define PPTP_STOP_SESSION_REPLY 4 +#define PPTP_ECHO_REQUEST 5 +#define PPTP_ECHO_REPLY 6 +#define PPTP_OUT_CALL_REQUEST 7 +#define PPTP_OUT_CALL_REPLY 8 +#define PPTP_IN_CALL_REQUEST 9 +#define PPTP_IN_CALL_REPLY 10 +#define PPTP_IN_CALL_CONNECT 11 +#define PPTP_CALL_CLEAR_REQUEST 12 +#define PPTP_CALL_DISCONNECT_NOTIFY 13 +#define PPTP_WAN_ERROR_NOTIFY 14 +#define PPTP_SET_LINK_INFO 15 + +#define PPTP_MSG_MAX 15 + +/* PptpGeneralError values */ +#define PPTP_ERROR_CODE_NONE 0 +#define PPTP_NOT_CONNECTED 1 +#define PPTP_BAD_FORMAT 2 +#define PPTP_BAD_VALUE 3 +#define PPTP_NO_RESOURCE 4 +#define PPTP_BAD_CALLID 5 +#define PPTP_REMOVE_DEVICE_ERROR 6 + +struct PptpControlHeader { + __be16 messageType; + __u16 reserved; +}; + +/* FramingCapability Bitmap Values */ +#define PPTP_FRAME_CAP_ASYNC 0x1 +#define PPTP_FRAME_CAP_SYNC 0x2 + +/* BearerCapability Bitmap Values */ +#define PPTP_BEARER_CAP_ANALOG 0x1 +#define PPTP_BEARER_CAP_DIGITAL 0x2 + +struct PptpStartSessionRequest { + __be16 protocolVersion; + __u16 reserved1; + __be32 framingCapability; + __be32 bearerCapability; + __be16 maxChannels; + __be16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStartSessionResultCode Values */ +#define PPTP_START_OK 1 +#define PPTP_START_GENERAL_ERROR 2 +#define PPTP_START_ALREADY_CONNECTED 3 +#define PPTP_START_NOT_AUTHORIZED 4 +#define PPTP_START_UNKNOWN_PROTOCOL 5 + +struct PptpStartSessionReply { + __be16 protocolVersion; + __u8 resultCode; + __u8 generalErrorCode; + __be32 framingCapability; + __be32 bearerCapability; + __be16 maxChannels; + __be16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStopReasons */ +#define PPTP_STOP_NONE 1 +#define PPTP_STOP_PROTOCOL 2 +#define PPTP_STOP_LOCAL_SHUTDOWN 3 + +struct PptpStopSessionRequest { + __u8 reason; + __u8 reserved1; + __u16 reserved2; +}; + +/* PptpStopSessionResultCode */ +#define PPTP_STOP_OK 1 +#define PPTP_STOP_GENERAL_ERROR 2 + +struct PptpStopSessionReply { + __u8 resultCode; + __u8 generalErrorCode; + __u16 reserved1; +}; + +struct PptpEchoRequest { + __be32 identNumber; +}; + +/* PptpEchoReplyResultCode */ +#define PPTP_ECHO_OK 1 +#define PPTP_ECHO_GENERAL_ERROR 2 + +struct PptpEchoReply { + __be32 identNumber; + __u8 resultCode; + __u8 generalErrorCode; + __u16 reserved; +}; + +/* PptpFramingType */ +#define PPTP_ASYNC_FRAMING 1 +#define PPTP_SYNC_FRAMING 2 +#define PPTP_DONT_CARE_FRAMING 3 + +/* PptpCallBearerType */ +#define PPTP_ANALOG_TYPE 1 +#define PPTP_DIGITAL_TYPE 2 +#define PPTP_DONT_CARE_BEARER_TYPE 3 + +struct PptpOutCallRequest { + __be16 callID; + __be16 callSerialNumber; + __be32 minBPS; + __be32 maxBPS; + __be32 bearerType; + __be32 framingType; + __be16 packetWindow; + __be16 packetProcDelay; + __be16 phoneNumberLength; + __u16 reserved1; + __u8 phoneNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpCallResultCode */ +#define PPTP_OUTCALL_CONNECT 1 +#define PPTP_OUTCALL_GENERAL_ERROR 2 +#define PPTP_OUTCALL_NO_CARRIER 3 +#define PPTP_OUTCALL_BUSY 4 +#define PPTP_OUTCALL_NO_DIAL_TONE 5 +#define PPTP_OUTCALL_TIMEOUT 6 +#define PPTP_OUTCALL_DONT_ACCEPT 7 + +struct PptpOutCallReply { + __be16 callID; + __be16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __be16 causeCode; + __be32 connectSpeed; + __be16 packetWindow; + __be16 packetProcDelay; + __be32 physChannelID; +}; + +struct PptpInCallRequest { + __be16 callID; + __be16 callSerialNumber; + __be32 callBearerType; + __be32 physChannelID; + __be16 dialedNumberLength; + __be16 dialingNumberLength; + __u8 dialedNumber[64]; + __u8 dialingNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpInCallResultCode */ +#define PPTP_INCALL_ACCEPT 1 +#define PPTP_INCALL_GENERAL_ERROR 2 +#define PPTP_INCALL_DONT_ACCEPT 3 + +struct PptpInCallReply { + __be16 callID; + __be16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __be16 packetWindow; + __be16 packetProcDelay; + __u16 reserved; +}; + +struct PptpInCallConnected { + __be16 peersCallID; + __u16 reserved; + __be32 connectSpeed; + __be16 packetWindow; + __be16 packetProcDelay; + __be32 callFramingType; +}; + +struct PptpClearCallRequest { + __be16 callID; + __u16 reserved; +}; + +struct PptpCallDisconnectNotify { + __be16 callID; + __u8 resultCode; + __u8 generalErrorCode; + __be16 causeCode; + __u16 reserved; + __u8 callStatistics[128]; +}; + +struct PptpWanErrorNotify { + __be16 peersCallID; + __u16 reserved; + __be32 crcErrors; + __be32 framingErrors; + __be32 hardwareOverRuns; + __be32 bufferOverRuns; + __be32 timeoutErrors; + __be32 alignmentErrors; +}; + +struct PptpSetLinkInfo { + __be16 peersCallID; + __u16 reserved; + __be32 sendAccm; + __be32 recvAccm; +}; + +union pptp_ctrl_union { + struct PptpStartSessionRequest sreq; + struct PptpStartSessionReply srep; + struct PptpStopSessionRequest streq; + struct PptpStopSessionReply strep; + struct PptpOutCallRequest ocreq; + struct PptpOutCallReply ocack; + struct PptpInCallRequest icreq; + struct PptpInCallReply icack; + struct PptpInCallConnected iccon; + struct PptpClearCallRequest clrreq; + struct PptpCallDisconnectNotify disc; + struct PptpWanErrorNotify wanerr; + struct PptpSetLinkInfo setlink; +}; + +/* crap needed for nf_conntrack_compat.h */ +struct nf_conn; +struct nf_conntrack_expect; +enum ip_conntrack_info; + +extern int +(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb, + struct nf_conn *ct, enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +extern int +(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb, + struct nf_conn *ct, enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +extern void +(*nf_nat_pptp_hook_exp_gre)(struct nf_conntrack_expect *exp_orig, + struct nf_conntrack_expect *exp_reply); + +extern void +(*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct, + struct nf_conntrack_expect *exp); + +#endif /* __KERNEL__ */ +#endif /* _NF_CONNTRACK_PPTP_H */ diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h new file mode 100644 index 000000000000..4e6bbce04ff8 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -0,0 +1,112 @@ +#ifndef _CONNTRACK_PROTO_GRE_H +#define _CONNTRACK_PROTO_GRE_H +#include + +/* GRE PROTOCOL HEADER */ + +/* GRE Version field */ +#define GRE_VERSION_1701 0x0 +#define GRE_VERSION_PPTP 0x1 + +/* GRE Protocol field */ +#define GRE_PROTOCOL_PPTP 0x880B + +/* GRE Flags */ +#define GRE_FLAG_C 0x80 +#define GRE_FLAG_R 0x40 +#define GRE_FLAG_K 0x20 +#define GRE_FLAG_S 0x10 +#define GRE_FLAG_A 0x80 + +#define GRE_IS_C(f) ((f)&GRE_FLAG_C) +#define GRE_IS_R(f) ((f)&GRE_FLAG_R) +#define GRE_IS_K(f) ((f)&GRE_FLAG_K) +#define GRE_IS_S(f) ((f)&GRE_FLAG_S) +#define GRE_IS_A(f) ((f)&GRE_FLAG_A) + +/* GRE is a mess: Four different standards */ +struct gre_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 rec:3, + srr:1, + seq:1, + key:1, + routing:1, + csum:1, + version:3, + reserved:4, + ack:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 csum:1, + routing:1, + key:1, + seq:1, + srr:1, + rec:3, + ack:1, + reserved:4, + version:3; +#else +#error "Adjust your defines" +#endif + __be16 protocol; +}; + +/* modified GRE header for PPTP */ +struct gre_hdr_pptp { + __u8 flags; /* bitfield */ + __u8 version; /* should be GRE_VERSION_PPTP */ + __be16 protocol; /* should be GRE_PROTOCOL_PPTP */ + __be16 payload_len; /* size of ppp payload, not inc. gre header */ + __be16 call_id; /* peer's call_id for this session */ + __be32 seq; /* sequence number. Present if S==1 */ + __be32 ack; /* seq number of highest packet recieved by */ + /* sender in this session */ +}; + +struct nf_ct_gre { + unsigned int stream_timeout; + unsigned int timeout; +}; + +#ifdef __KERNEL__ +#include + +struct nf_conn; + +/* structure for original <-> reply keymap */ +struct nf_ct_gre_keymap { + struct list_head list; + struct nf_conntrack_tuple tuple; +}; + +/* add new tuple->key_reply pair to keymap */ +int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, + struct nf_conntrack_tuple *t); + +/* delete keymap entries */ +void nf_ct_gre_keymap_destroy(struct nf_conn *ct); + +/* get pointer to gre key, if present */ +static inline __be32 *gre_key(struct gre_hdr *greh) +{ + if (!greh->key) + return NULL; + if (greh->csum || greh->routing) + return (__be32 *)(greh+sizeof(*greh)+4); + return (__be32 *)(greh+sizeof(*greh)); +} + +/* get pointer ot gre csum, if present */ +static inline __sum16 *gre_csum(struct gre_hdr *greh) +{ + if (!greh->csum) + return NULL; + return (__sum16 *)(greh+sizeof(*greh)); +} + +extern void nf_ct_gre_keymap_flush(void); +extern void nf_nat_need_gre(void); + +#endif /* __KERNEL__ */ +#endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index a1c57ee0a4fa..1401ccc051c4 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -11,10 +11,12 @@ #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 { diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 1646076933b1..032b36a0e378 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -33,6 +34,7 @@ union nf_conntrack_proto { struct ip_ct_tcp tcp; struct ip_ct_icmp icmp; struct nf_ct_icmpv6 icmpv6; + struct nf_ct_gre gre; }; union nf_conntrack_expect_proto { @@ -41,12 +43,14 @@ union nf_conntrack_expect_proto { /* Add protocol helper include file here */ #include +#include #include /* per conntrack: application helper private data */ union nf_conntrack_help { /* insert conntrack helper private data (master) here */ struct nf_ct_ftp_master ct_ftp_info; + struct nf_ct_pptp_master ct_pptp_info; struct nf_ct_h323_master ct_h323_info; }; diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index fbba9e8b95fc..8c72ac9f0ab8 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -34,6 +34,8 @@ struct nf_conntrack_helper struct nf_conn *ct, enum ip_conntrack_info conntrackinfo); + void (*destroy)(struct nf_conn *ct); + int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct); }; diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index c96a9c576736..5d72b16e876f 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -49,6 +49,9 @@ union nf_conntrack_man_proto struct { __be16 port; } sctp; + struct { + __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */ + } gre; }; /* The manipulable part of the tuple. */ @@ -84,6 +87,9 @@ struct nf_conntrack_tuple struct { __be16 port; } sctp; + struct { + __be16 key; + } gre; } u; /* The protocol. */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 4555f721dfc1..c3327ac024de 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -484,6 +484,10 @@ config IP_NF_NAT_SNMP_BASIC # '&&' (6) # # (6) Returns the result of min(/expr/, /expr/). +config NF_NAT_PROTO_GRE + tristate + depends on NF_NAT && NF_CT_PROTO_GRE + config IP_NF_NAT_FTP tristate depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT @@ -528,6 +532,12 @@ config IP_NF_NAT_PPTP default IP_NF_NAT if IP_NF_PPTP=y default m if IP_NF_PPTP=m +config NF_NAT_PPTP + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_PPTP + select NF_NAT_PROTO_GRE + config IP_NF_NAT_H323 tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 56733c370327..ef33ff2cdda9 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -54,6 +54,10 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o +obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o + +# NAT protocols (nf_nat) +obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c new file mode 100644 index 000000000000..0ae45b79a4eb --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -0,0 +1,315 @@ +/* + * nf_nat_pptp.c + * + * NAT support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * TODO: - NAT to a unique tuple, not to TCP source port + * (needs netfilter tuple reservation) + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define NF_NAT_PPTP_VERSION "3.0" + +#define REQ_CID(req, off) (*(__be16 *)((char *)(req) + (off))) + +MODULE_LICENSE("GPL"); +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) +{ + struct nf_conn *master = ct->master; + struct nf_conntrack_expect *other_exp; + struct nf_conntrack_tuple t; + struct nf_ct_pptp_master *ct_pptp_info; + struct nf_nat_pptp *nat_pptp_info; + struct ip_nat_range range; + + ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; + nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; + + /* And here goes the grand finale of corrosion... */ + if (exp->dir == IP_CT_DIR_ORIGINAL) { + DEBUGP("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; + t.src.u.gre.key = ct_pptp_info->pac_call_id; + t.dst.u3.ip = master->tuplehash[!exp->dir].tuple.dst.u3.ip; + t.dst.u.gre.key = ct_pptp_info->pns_call_id; + t.dst.protonum = IPPROTO_GRE; + } else { + DEBUGP("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; + t.src.u.gre.key = nat_pptp_info->pns_call_id; + t.dst.u3.ip = master->tuplehash[exp->dir].tuple.dst.u3.ip; + t.dst.u.gre.key = nat_pptp_info->pac_call_id; + t.dst.protonum = IPPROTO_GRE; + } + + DEBUGP("trying to unexpect other dir: "); + NF_CT_DUMP_TUPLE(&t); + other_exp = nf_conntrack_expect_find_get(&t); + if (other_exp) { + nf_conntrack_unexpect_related(other_exp); + nf_conntrack_expect_put(other_exp); + DEBUGP("success\n"); + } else { + DEBUGP("not found!\n"); + } + + /* This must be a fresh one. */ + BUG_ON(ct->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; + if (exp->dir == IP_CT_DIR_ORIGINAL) { + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.min = range.max = exp->saved_proto; + } + /* hook doesn't matter, but it has to do source manip */ + nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; + if (exp->dir == IP_CT_DIR_REPLY) { + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.min = range.max = exp->saved_proto; + } + /* hook doesn't matter, but it has to do destination manip */ + nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); +} + +/* outbound packets == from PNS to PAC */ +static int +pptp_outbound_pkt(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) + +{ + struct nf_ct_pptp_master *ct_pptp_info; + struct nf_nat_pptp *nat_pptp_info; + u_int16_t msg; + __be16 new_callid; + unsigned int cid_off; + + ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info; + nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info; + + new_callid = ct_pptp_info->pns_call_id; + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REQUEST: + cid_off = offsetof(union pptp_ctrl_union, ocreq.callID); + /* FIXME: ideally we would want to reserve a call ID + * here. current netfilter NAT core is not able to do + * this :( For now we use TCP source port. This breaks + * multiple calls within one control session */ + + /* save original call ID in nat_info */ + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; + + /* don't use tcph->source since we are at a DSTmanip + * hook (e.g. PREROUTING) and pkt is not mangled yet */ + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; + + /* save new call ID in ct info */ + ct_pptp_info->pns_call_id = new_callid; + break; + case PPTP_IN_CALL_REPLY: + cid_off = offsetof(union pptp_ctrl_union, icack.callID); + break; + case PPTP_CALL_CLEAR_REQUEST: + 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]); + /* fall through */ + case PPTP_SET_LINK_INFO: + /* only need to NAT in case PAC is behind NAT box */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + /* 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)); + + /* mangle packet */ + if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, + cid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), + sizeof(new_callid), (char *)&new_callid, + sizeof(new_callid)) == 0) + return NF_DROP; + return NF_ACCEPT; +} + +static void +pptp_exp_gre(struct nf_conntrack_expect *expect_orig, + struct nf_conntrack_expect *expect_reply) +{ + struct nf_conn *ct = expect_orig->master; + struct nf_ct_pptp_master *ct_pptp_info; + struct nf_nat_pptp *nat_pptp_info; + + ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info; + nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info; + + /* save original PAC call ID in nat_info */ + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; + + /* alter expectation for PNS->PAC direction */ + expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id; + expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id; + expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id; + expect_orig->dir = IP_CT_DIR_ORIGINAL; + + /* alter expectation for PAC->PNS direction */ + expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id; + expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id; + expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id; + expect_reply->dir = IP_CT_DIR_REPLY; +} + +/* inbound packets == from PAC to PNS */ +static int +pptp_inbound_pkt(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) +{ + struct nf_nat_pptp *nat_pptp_info; + u_int16_t msg; + __be16 new_pcid; + unsigned int pcid_off; + + nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info; + new_pcid = nat_pptp_info->pns_call_id; + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REPLY: + pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID); + break; + case PPTP_IN_CALL_CONNECT: + pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID); + break; + case PPTP_IN_CALL_REQUEST: + /* only need to nat in case PAC is behind NAT box */ + return NF_ACCEPT; + case PPTP_WAN_ERROR_NOTIFY: + pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID); + break; + case PPTP_CALL_DISCONNECT_NOTIFY: + pcid_off = offsetof(union pptp_ctrl_union, disc.callID); + break; + case PPTP_SET_LINK_INFO: + 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]); + /* fall through */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST, + * 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)); + + if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, + pcid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), + sizeof(new_pcid), (char *)&new_pcid, + sizeof(new_pcid)) == 0) + return NF_DROP; + return NF_ACCEPT; +} + +static int __init nf_nat_helper_pptp_init(void) +{ + nf_nat_need_gre(); + + BUG_ON(rcu_dereference(nf_nat_pptp_hook_outbound)); + rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt); + + BUG_ON(rcu_dereference(nf_nat_pptp_hook_inbound)); + rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt); + + BUG_ON(rcu_dereference(nf_nat_pptp_hook_exp_gre)); + rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre); + + BUG_ON(rcu_dereference(nf_nat_pptp_hook_expectfn)); + rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected); + return 0; +} + +static void __exit nf_nat_helper_pptp_fini(void) +{ + rcu_assign_pointer(nf_nat_pptp_hook_expectfn, NULL); + rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, NULL); + rcu_assign_pointer(nf_nat_pptp_hook_inbound, NULL); + rcu_assign_pointer(nf_nat_pptp_hook_outbound, NULL); + synchronize_rcu(); +} + +module_init(nf_nat_helper_pptp_init); +module_exit(nf_nat_helper_pptp_fini); diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c new file mode 100644 index 000000000000..d3de579e09d2 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c @@ -0,0 +1,179 @@ +/* + * nf_nat_proto_gre.c + * + * NAT protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +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, + enum nf_nat_manip_type maniptype, + const union nf_conntrack_man_proto *min, + const union nf_conntrack_man_proto *max) +{ + __be16 key; + + if (maniptype == IP_NAT_MANIP_SRC) + key = tuple->src.u.gre.key; + else + key = tuple->dst.u.gre.key; + + return ntohs(key) >= ntohs(min->gre.key) && + ntohs(key) <= ntohs(max->gre.key); +} + +/* generate unique tuple ... */ +static int +gre_unique_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_nat_range *range, + enum nf_nat_manip_type maniptype, + const struct nf_conn *conntrack) +{ + static u_int16_t key; + __be16 *keyptr; + unsigned int min, i, range_size; + + if (maniptype == IP_NAT_MANIP_SRC) + keyptr = &tuple->src.u.gre.key; + else + keyptr = &tuple->dst.u.gre.key; + + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { + DEBUGP("%p: NATing GRE PPTP\n", conntrack); + min = 1; + range_size = 0xffff; + } else { + min = ntohs(range->min.gre.key); + range_size = ntohs(range->max.gre.key) - min + 1; + } + + DEBUGP("min = %u, range_size = %u\n", min, range_size); + + for (i = 0; i < range_size; i++, key++) { + *keyptr = htons(min + key % range_size); + if (!nf_nat_used_tuple(tuple, conntrack)) + return 1; + } + + DEBUGP("%p: no NAT mapping\n", conntrack); + return 0; +} + +/* manipulate a GRE packet according to maniptype */ +static int +gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, + const struct nf_conntrack_tuple *tuple, + enum nf_nat_manip_type maniptype) +{ + struct gre_hdr *greh; + struct gre_hdr_pptp *pgreh; + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + unsigned int hdroff = iphdroff + iph->ihl * 4; + + /* pgreh includes two optional 32bit fields which are not required + * to be there. That's where the magic '8' comes from */ + if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8)) + return 0; + + greh = (void *)(*pskb)->data + hdroff; + pgreh = (struct gre_hdr_pptp *)greh; + + /* we only have destination manip of a packet, since 'source key' + * is not present in the packet itself */ + if (maniptype != IP_NAT_MANIP_DST) + return 1; + switch (greh->version) { + case 0: + if (!greh->key) { + DEBUGP("can't nat GRE w/o key\n"); + break; + } + if (greh->csum) { + /* FIXME: Never tested this code... */ + nf_proto_csum_replace4(gre_csum(greh), *pskb, + *(gre_key(greh)), + tuple->dst.u.gre.key, 0); + } + *(gre_key(greh)) = tuple->dst.u.gre.key; + break; + case GRE_VERSION_PPTP: + DEBUGP("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"); + return 0; + } + return 1; +} + +static struct nf_nat_protocol gre __read_mostly = { + .name = "GRE", + .protonum = IPPROTO_GRE, + .manip_pkt = gre_manip_pkt, + .in_range = gre_in_range, + .unique_tuple = gre_unique_tuple, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .range_to_nfattr = nf_nat_port_range_to_nfattr, + .nfattr_to_range = nf_nat_port_nfattr_to_range, +#endif +}; + +int __init nf_nat_proto_gre_init(void) +{ + return nf_nat_protocol_register(&gre); +} + +void __exit nf_nat_proto_gre_fini(void) +{ + nf_nat_protocol_unregister(&gre); +} + +module_init(nf_nat_proto_gre_init); +module_exit(nf_nat_proto_gre_fini); + +void nf_nat_need_gre(void) +{ + return; +} +EXPORT_SYMBOL_GPL(nf_nat_need_gre); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d1a365d83c53..6b2eb26ae03f 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -120,6 +120,10 @@ config NF_CONNTRACK_EVENTS If unsure, say `N'. +config NF_CT_PROTO_GRE + tristate + depends on EXPERIMENTAL && NF_CONNTRACK + config NF_CT_PROTO_SCTP tristate 'SCTP protocol on new connection tracking support (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK @@ -213,6 +217,25 @@ config NF_CONNTRACK_NETBIOS_NS To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_PPTP + tristate "PPtP protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + select NF_CT_PROTO_GRE + help + This module adds support for PPTP (Point to Point Tunnelling + Protocol, RFC2637) connection tracking and NAT. + + If you are running PPTP sessions over a stateful firewall or NAT + box, you may want to enable this feature. + + Please note that not all PPTP modes of operation are supported yet. + Specifically these limitations exist: + - Blindy assumes that control connections are always established + in PNS->PAC direction. This is a violation of RFC2637. + - Only supports a single call within each session + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 67144b2af647..897bed4cbd79 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o # SCTP protocol connection tracking +obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o # netlink interface for nf_conntrack @@ -27,6 +28,7 @@ obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o +obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index aa8beabfeebb..ed756c928bc4 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -300,6 +300,7 @@ static void destroy_conntrack(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; + struct nf_conn_help *help = nfct_help(ct); struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -310,6 +311,9 @@ destroy_conntrack(struct nf_conntrack *nfct) nf_conntrack_event(IPCT_DESTROY, ct); set_bit(IPS_DYING_BIT, &ct->status); + if (help && help->helper && help->helper->destroy) + help->helper->destroy(ct); + /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to nf_conntrack_lock!!! -HW */ diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c new file mode 100644 index 000000000000..f0ff00e0d052 --- /dev/null +++ b/net/netfilter/nf_conntrack_pptp.c @@ -0,0 +1,607 @@ +/* + * Connection tracking support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * Limitations: + * - We blindly assume that control connections are always + * established in PNS->PAC direction. This is a violation + * of RFFC2673 + * - We can only support one single call within each session + * TODO: + * - testing of incoming PPTP calls + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define NF_CT_PPTP_VERSION "3.1" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); +MODULE_ALIAS("ip_conntrack_pptp"); + +static DEFINE_SPINLOCK(nf_pptp_lock); + +int +(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb, + struct nf_conn *ct, enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); + +int +(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb, + struct nf_conn *ct, enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_inbound); + +void +(*nf_nat_pptp_hook_exp_gre)(struct nf_conntrack_expect *expect_orig, + struct nf_conntrack_expect *expect_reply) + __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_exp_gre); + +void +(*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct, + struct nf_conntrack_expect *exp) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); + +#if 0 +/* PptpControlMessageType names */ +const char *pptp_msg_name[] = { + "UNKNOWN_MESSAGE", + "START_SESSION_REQUEST", + "START_SESSION_REPLY", + "STOP_SESSION_REQUEST", + "STOP_SESSION_REPLY", + "ECHO_REQUEST", + "ECHO_REPLY", + "OUT_CALL_REQUEST", + "OUT_CALL_REPLY", + "IN_CALL_REQUEST", + "IN_CALL_REPLY", + "IN_CALL_CONNECT", + "CALL_CLEAR_REQUEST", + "CALL_DISCONNECT_NOTIFY", + "WAN_ERROR_NOTIFY", + "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 +#define MINS * 60 SECS +#define HOURS * 60 MINS + +#define PPTP_GRE_TIMEOUT (10 MINS) +#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS) + +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"); + + /* increase timeout of GRE data channel conntrack entry */ + ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; + ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; + + /* Can you see how rusty this code is, compared with the pre-2.6.11 + * one? That's what happened to my shiny newnat of 2002 ;( -HW */ + + rcu_read_lock(); + nf_nat_pptp_expectfn = rcu_dereference(nf_nat_pptp_hook_expectfn); + if (nf_nat_pptp_expectfn && ct->status & IPS_NAT_MASK) + nf_nat_pptp_expectfn(ct, exp); + else { + struct nf_conntrack_tuple inv_t; + struct nf_conntrack_expect *exp_other; + + /* obviously this tuple inversion only works until you do NAT */ + nf_ct_invert_tuplepr(&inv_t, &exp->tuple); + DEBUGP("trying to unexpect other dir: "); + NF_CT_DUMP_TUPLE(&inv_t); + + exp_other = nf_conntrack_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); + } else { + DEBUGP("not found\n"); + } + } + rcu_read_unlock(); +} + +static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_expect *exp; + struct nf_conn *sibling; + + DEBUGP("trying to timeout ct or exp for tuple "); + NF_CT_DUMP_TUPLE(t); + + h = nf_conntrack_find_get(t, NULL); + if (h) { + sibling = nf_ct_tuplehash_to_ctrack(h); + DEBUGP("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)) + sibling->timeout.function((unsigned long)sibling); + nf_ct_put(sibling); + return 1; + } else { + exp = nf_conntrack_expect_find_get(t); + if (exp) { + DEBUGP("unexpect_related of expect %p\n", exp); + nf_conntrack_unexpect_related(exp); + nf_conntrack_expect_put(exp); + return 1; + } + } + return 0; +} + +/* timeout GRE data connections */ +static void pptp_destroy_siblings(struct nf_conn *ct) +{ + struct nf_conn_help *help = nfct_help(ct); + struct nf_conntrack_tuple t; + + nf_ct_gre_keymap_destroy(ct); + + /* try original (pns->pac) tuple */ + memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t)); + t.dst.protonum = IPPROTO_GRE; + 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"); + + /* try reply (pac->pns) tuple */ + memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); + t.dst.protonum = IPPROTO_GRE; + 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"); +} + +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */ +static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) +{ + struct nf_conntrack_expect *exp_orig, *exp_reply; + enum ip_conntrack_dir dir; + int ret = 1; + typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre; + + exp_orig = nf_conntrack_expect_alloc(ct); + if (exp_orig == NULL) + goto out; + + exp_reply = nf_conntrack_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); + 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); + 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) + goto out_put_both; + if (nf_conntrack_expect_related(exp_reply) != 0) + goto out_unexpect_orig; + + /* Add GRE keymap entries */ + if (nf_ct_gre_keymap_add(ct, IP_CT_DIR_ORIGINAL, &exp_orig->tuple) != 0) + goto out_unexpect_both; + if (nf_ct_gre_keymap_add(ct, IP_CT_DIR_REPLY, &exp_reply->tuple) != 0) { + nf_ct_gre_keymap_destroy(ct); + goto out_unexpect_both; + } + ret = 0; + +out_put_both: + nf_conntrack_expect_put(exp_reply); +out_put_orig: + nf_conntrack_expect_put(exp_orig); +out: + return ret; + +out_unexpect_both: + nf_conntrack_unexpect_related(exp_reply); +out_unexpect_orig: + nf_conntrack_unexpect_related(exp_orig); + goto out_put_both; +} + +static inline int +pptp_inbound_pkt(struct sk_buff **pskb, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq, + unsigned int reqlen, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; + u_int16_t msg; + __be16 cid = 0, pcid = 0; + typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; + + msg = ntohs(ctlh->messageType); + DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); + + switch (msg) { + case PPTP_START_SESSION_REPLY: + /* server confirms new control session */ + if (info->sstate < PPTP_SESSION_REQUESTED) + goto invalid; + if (pptpReq->srep.resultCode == PPTP_START_OK) + info->sstate = PPTP_SESSION_CONFIRMED; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_STOP_SESSION_REPLY: + /* server confirms end of control session */ + if (info->sstate > PPTP_SESSION_STOPREQ) + goto invalid; + if (pptpReq->strep.resultCode == PPTP_STOP_OK) + info->sstate = PPTP_SESSION_NONE; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_OUT_CALL_REPLY: + /* server accepted call, we now expect GRE frames */ + if (info->sstate != PPTP_SESSION_CONFIRMED) + goto invalid; + if (info->cstate != PPTP_CALL_OUT_REQ && + info->cstate != PPTP_CALL_OUT_CONF) + goto invalid; + + cid = pptpReq->ocack.callID; + 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)); + + if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { + info->cstate = PPTP_CALL_OUT_CONF; + info->pac_call_id = cid; + exp_gre(ct, cid, pcid); + } else + info->cstate = PPTP_CALL_NONE; + break; + + case PPTP_IN_CALL_REQUEST: + /* server tells us about incoming call request */ + if (info->sstate != PPTP_SESSION_CONFIRMED) + goto invalid; + + cid = pptpReq->icreq.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + info->cstate = PPTP_CALL_IN_REQ; + info->pac_call_id = cid; + break; + + case PPTP_IN_CALL_CONNECT: + /* server tells us about incoming call established */ + if (info->sstate != PPTP_SESSION_CONFIRMED) + goto invalid; + if (info->cstate != PPTP_CALL_IN_REP && + info->cstate != PPTP_CALL_IN_CONF) + goto invalid; + + pcid = pptpReq->iccon.peersCallID; + cid = info->pac_call_id; + + if (info->pns_call_id != pcid) + goto invalid; + + DEBUGP("%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 */ + exp_gre(ct, cid, pcid); + break; + + case PPTP_CALL_DISCONNECT_NOTIFY: + /* server confirms disconnect */ + cid = pptpReq->disc.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_destroy_siblings(ct); + break; + + case PPTP_WAN_ERROR_NOTIFY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + + default: + goto invalid; + } + + nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); + if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) + return nf_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq); + 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)); + return NF_ACCEPT; +} + +static inline int +pptp_outbound_pkt(struct sk_buff **pskb, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq, + unsigned int reqlen, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; + u_int16_t msg; + __be16 cid = 0, pcid = 0; + typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; + + msg = ntohs(ctlh->messageType); + DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); + + switch (msg) { + case PPTP_START_SESSION_REQUEST: + /* client requests for new control session */ + if (info->sstate != PPTP_SESSION_NONE) + goto invalid; + info->sstate = PPTP_SESSION_REQUESTED; + break; + + case PPTP_STOP_SESSION_REQUEST: + /* client requests end of control session */ + info->sstate = PPTP_SESSION_STOPREQ; + break; + + case PPTP_OUT_CALL_REQUEST: + /* client initiating connection to server */ + if (info->sstate != PPTP_SESSION_CONFIRMED) + goto invalid; + 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)); + info->pns_call_id = cid; + break; + + case PPTP_IN_CALL_REPLY: + /* client answers incoming call */ + if (info->cstate != PPTP_CALL_IN_REQ && + info->cstate != PPTP_CALL_IN_REP) + goto invalid; + + cid = pptpReq->icack.callID; + 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)); + + if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { + /* part two of the three-way handshake */ + info->cstate = PPTP_CALL_IN_REP; + info->pns_call_id = cid; + } else + info->cstate = PPTP_CALL_NONE; + break; + + case PPTP_CALL_CLEAR_REQUEST: + /* client requests hangup of call */ + if (info->sstate != PPTP_SESSION_CONFIRMED) + goto invalid; + /* FUTURE: iterate over all calls and check if + * call ID is valid. We don't do this without newnat, + * because we only know about last call */ + info->cstate = PPTP_CALL_CLEAR_REQ; + break; + + case PPTP_SET_LINK_INFO: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + + default: + goto invalid; + } + + nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); + if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) + return nf_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq); + 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)); + return NF_ACCEPT; +} + +static const unsigned int pptp_msg_size[] = { + [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest), + [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply), + [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest), + [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply), + [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest), + [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply), + [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest), + [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply), + [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected), + [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest), + [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify), + [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify), + [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo), +}; + +/* track caller id inside control connection, call expect_related */ +static int +conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) + +{ + int dir = CTINFO2DIR(ctinfo); + struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; + struct tcphdr _tcph, *tcph; + struct pptp_pkt_hdr _pptph, *pptph; + struct PptpControlHeader _ctlh, *ctlh; + union pptp_ctrl_union _pptpReq, *pptpReq; + unsigned int tcplen = (*pskb)->len - protoff; + unsigned int datalen, reqlen, nexthdr_off; + int oldsstate, oldcstate; + int ret; + u_int16_t msg; + + /* don't do any tracking before tcp handshake complete */ + if (ctinfo != IP_CT_ESTABLISHED && + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + return NF_ACCEPT; + + nexthdr_off = protoff; + tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); + BUG_ON(!tcph); + nexthdr_off += tcph->doff * 4; + datalen = tcplen - tcph->doff * 4; + + pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); + if (!pptph) { + DEBUGP("no full PPTP header, can't track\n"); + return NF_ACCEPT; + } + nexthdr_off += sizeof(_pptph); + datalen -= sizeof(_pptph); + + /* 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"); + return NF_ACCEPT; + } + + ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); + if (!ctlh) + return NF_ACCEPT; + nexthdr_off += sizeof(_ctlh); + datalen -= sizeof(_ctlh); + + reqlen = datalen; + msg = ntohs(ctlh->messageType); + if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg]) + return NF_ACCEPT; + if (reqlen > sizeof(*pptpReq)) + reqlen = sizeof(*pptpReq); + + pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); + if (!pptpReq) + return NF_ACCEPT; + + oldsstate = info->sstate; + oldcstate = info->cstate; + + spin_lock_bh(&nf_pptp_lock); + + /* FIXME: We just blindly assume that the control connection is always + * established from PNS->PAC. However, RFC makes no guarantee */ + if (dir == IP_CT_DIR_ORIGINAL) + /* client -> server (PNS -> PAC) */ + ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, + ctinfo); + else + /* 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); + spin_unlock_bh(&nf_pptp_lock); + + return ret; +} + +/* control protocol helper */ +static struct nf_conntrack_helper pptp __read_mostly = { + .name = "pptp", + .me = THIS_MODULE, + .max_expected = 2, + .timeout = 5 * 60, + .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, +}; + +static int __init nf_conntrack_pptp_init(void) +{ + return nf_conntrack_helper_register(&pptp); +} + +static void __exit nf_conntrack_pptp_fini(void) +{ + nf_conntrack_helper_unregister(&pptp); + nf_ct_gre_keymap_flush(); +} + +module_init(nf_conntrack_pptp_init); +module_exit(nf_conntrack_pptp_fini); diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c new file mode 100644 index 000000000000..ac193ce70249 --- /dev/null +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -0,0 +1,305 @@ +/* + * ip_conntrack_proto_gre.c - Version 3.0 + * + * Connection tracking protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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); + +void nf_ct_gre_keymap_flush(void) +{ + struct list_head *pos, *n; + + write_lock_bh(&nf_ct_gre_lock); + list_for_each_safe(pos, n, &gre_keymap_list) { + list_del(pos); + kfree(pos); + } + write_unlock_bh(&nf_ct_gre_lock); +} +EXPORT_SYMBOL(nf_ct_gre_keymap_flush); + +static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, + const struct nf_conntrack_tuple *t) +{ + return km->tuple.src.l3num == t->src.l3num && + !memcmp(&km->tuple.src.u3, &t->src.u3, sizeof(t->src.u3)) && + !memcmp(&km->tuple.dst.u3, &t->dst.u3, sizeof(t->dst.u3)) && + km->tuple.dst.protonum == t->dst.protonum && + km->tuple.dst.u.all == t->dst.u.all; +} + +/* look up the source key for a given tuple */ +static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t) +{ + struct nf_ct_gre_keymap *km; + __be16 key = 0; + + read_lock_bh(&nf_ct_gre_lock); + list_for_each_entry(km, &gre_keymap_list, list) { + if (gre_key_cmpfn(km, t)) { + key = km->tuple.src.u.gre.key; + break; + } + } + read_unlock_bh(&nf_ct_gre_lock); + + DEBUGP("lookup src key 0x%x for ", key); + NF_CT_DUMP_TUPLE(t); + + return key; +} + +/* add a single keymap entry, associate with specified master ct */ +int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, + struct nf_conntrack_tuple *t) +{ + struct nf_conn_help *help = nfct_help(ct); + struct nf_ct_gre_keymap **kmp, *km; + + BUG_ON(strcmp(help->helper->name, "pptp")); + kmp = &help->help.ct_pptp_info.keymap[dir]; + if (*kmp) { + /* check whether it's a retransmission */ + list_for_each_entry(km, &gre_keymap_list, list) { + 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); + return -EEXIST; + } + + km = kmalloc(sizeof(*km), GFP_ATOMIC); + if (!km) + return -ENOMEM; + memcpy(&km->tuple, t, sizeof(*t)); + *kmp = km; + + DEBUGP("adding new entry %p: ", km); + NF_CT_DUMP_TUPLE(&km->tuple); + + write_lock_bh(&nf_ct_gre_lock); + list_add_tail(&km->list, &gre_keymap_list); + write_unlock_bh(&nf_ct_gre_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add); + +/* destroy the keymap entries associated with specified master ct */ +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); + BUG_ON(strcmp(help->helper->name, "pptp")); + + 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]); + 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; + } + } + write_unlock_bh(&nf_ct_gre_lock); +} +EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy); + +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ + +/* invert gre part of tuple */ +static int gre_invert_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_tuple *orig) +{ + tuple->dst.u.gre.key = orig->src.u.gre.key; + tuple->src.u.gre.key = orig->dst.u.gre.key; + return 1; +} + +/* gre hdr info to tuple */ +static int gre_pkt_to_tuple(const struct sk_buff *skb, + unsigned int dataoff, + struct nf_conntrack_tuple *tuple) +{ + struct gre_hdr_pptp _pgrehdr, *pgrehdr; + __be16 srckey; + struct gre_hdr _grehdr, *grehdr; + + /* first only delinearize old RFC1701 GRE header */ + grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); + if (!grehdr || grehdr->version != GRE_VERSION_PPTP) { + /* try to behave like "nf_conntrack_proto_generic" */ + tuple->src.u.all = 0; + tuple->dst.u.all = 0; + return 1; + } + + /* PPTP header is variable length, only need up to the call_id field */ + pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr); + if (!pgrehdr) + return 1; + + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { + DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); + return 0; + } + + tuple->dst.u.gre.key = pgrehdr->call_id; + srckey = gre_keymap_lookup(tuple); + tuple->src.u.gre.key = srckey; + + return 1; +} + +/* print gre part of tuple */ +static int gre_print_tuple(struct seq_file *s, + const struct nf_conntrack_tuple *tuple) +{ + return seq_printf(s, "srckey=0x%x dstkey=0x%x ", + ntohs(tuple->src.u.gre.key), + ntohs(tuple->dst.u.gre.key)); +} + +/* print private data for conntrack */ +static int gre_print_conntrack(struct seq_file *s, + const struct nf_conn *ct) +{ + return seq_printf(s, "timeout=%u, stream_timeout=%u ", + (ct->proto.gre.timeout / HZ), + (ct->proto.gre.stream_timeout / HZ)); +} + +/* Returns verdict for packet, and may modify conntrack */ +static int gre_packet(struct nf_conn *ct, + const struct sk_buff *skb, + unsigned int dataoff, + enum ip_conntrack_info ctinfo, + int pf, + unsigned int hooknum) +{ + /* If we've seen traffic both ways, this is a GRE connection. + * Extend timeout. */ + if (ct->status & IPS_SEEN_REPLY) { + nf_ct_refresh_acct(ct, ctinfo, skb, + ct->proto.gre.stream_timeout); + /* Also, more likely to be important, and not a probe. */ + set_bit(IPS_ASSURED_BIT, &ct->status); + nf_conntrack_event_cache(IPCT_STATUS, skb); + } else + nf_ct_refresh_acct(ct, ctinfo, skb, + ct->proto.gre.timeout); + + return NF_ACCEPT; +} + +/* Called when a new connection for this protocol found. */ +static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, + unsigned int dataoff) +{ + DEBUGP(": "); + NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + + /* initialize to sane value. Ideally a conntrack helper + * (e.g. in case of pptp) is increasing them */ + ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT; + ct->proto.gre.timeout = GRE_TIMEOUT; + + return 1; +} + +/* Called when a conntrack entry has already been removed from the hashes + * and is about to be deleted from memory */ +static void gre_destroy(struct nf_conn *ct) +{ + struct nf_conn *master = ct->master; + DEBUGP(" entering\n"); + + if (!master) + DEBUGP("no master !?!\n"); + else + nf_ct_gre_keymap_destroy(master); +} + +/* protocol helper struct */ +static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { + .l3proto = AF_INET, + .l4proto = IPPROTO_GRE, + .name = "gre", + .pkt_to_tuple = gre_pkt_to_tuple, + .invert_tuple = gre_invert_tuple, + .print_tuple = gre_print_tuple, + .print_conntrack = gre_print_conntrack, + .packet = gre_packet, + .new = gre_new, + .destroy = gre_destroy, + .me = THIS_MODULE, +#if defined(CONFIG_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_NF_CONNTRACK_NETLINK_MODULE) + .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, + .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, +#endif +}; + +static int __init nf_ct_proto_gre_init(void) +{ + return nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4); +} + +static void nf_ct_proto_gre_fini(void) +{ + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); + nf_ct_gre_keymap_flush(); +} + +module_init(nf_ct_proto_gre_init); +module_exit(nf_ct_proto_gre_fini); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From 9fafcd7b203229c3f3893a475741afc27e276306 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:09:57 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add SIP helper port Add IPv4 and IPv6 capable nf_conntrack port of the SIP conntrack/NAT helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_sip.h | 41 +++ net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 1 + net/ipv4/netfilter/nf_nat_sip.c | 283 +++++++++++++++ net/netfilter/Kconfig | 12 + net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_sip.c | 530 +++++++++++++++++++++++++++++ 7 files changed, 873 insertions(+) create mode 100644 include/linux/netfilter/nf_conntrack_sip.h create mode 100644 net/ipv4/netfilter/nf_nat_sip.c create mode 100644 net/netfilter/nf_conntrack_sip.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h new file mode 100644 index 000000000000..bb7f2041db74 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -0,0 +1,41 @@ +#ifndef __NF_CONNTRACK_SIP_H__ +#define __NF_CONNTRACK_SIP_H__ +#ifdef __KERNEL__ + +#define SIP_PORT 5060 +#define SIP_TIMEOUT 3600 + +enum sip_header_pos { + POS_REG_REQ_URI, + POS_REQ_URI, + POS_FROM, + POS_TO, + POS_VIA, + POS_CONTACT, + POS_CONTENT, + POS_MEDIA, + POS_OWNER_IP4, + POS_CONNECTION_IP4, + POS_OWNER_IP6, + POS_CONNECTION_IP6, + POS_SDP_HEADER, +}; + +extern unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + const char **dptr); +extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conntrack_expect *exp, + const char *dptr); + +extern int ct_sip_get_info(struct nf_conn *ct, const char *dptr, size_t dlen, + unsigned int *matchoff, unsigned int *matchlen, + enum sip_header_pos pos); +extern int ct_sip_lnlen(const char *line, const char *limit); +extern const char *ct_sip_search(const char *needle, const char *haystack, + size_t needle_len, size_t haystack_len, + int case_sensitive); +#endif /* __KERNEL__ */ +#endif /* __NF_CONNTRACK_SIP_H__ */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index c3327ac024de..83e83f553ccb 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -555,6 +555,11 @@ config IP_NF_NAT_SIP default IP_NF_NAT if IP_NF_SIP=y default m if IP_NF_SIP=m +config NF_NAT_SIP + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_SIP + # mangle + specific targets config IP_NF_MANGLE tristate "Packet mangling" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index ef33ff2cdda9..167b65e89aca 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o +obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o # NAT protocols (nf_nat) obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c new file mode 100644 index 000000000000..3d524b957310 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -0,0 +1,283 @@ +/* SIP extension for UDP NAT alteration. + * + * (C) 2005 by Christian Hentschel + * based on RR's ip_nat_ftp.c and other modules. + * + * 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 +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hentschel "); +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")]; + char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; + unsigned int srclen, srciplen; + unsigned int dstlen, dstiplen; + } addr[IP_CT_DIR_MAX]; +}; + +static void addr_map_init(struct nf_conn *ct, struct addr_map *map) +{ + struct nf_conntrack_tuple *t; + enum ip_conntrack_dir dir; + unsigned int n; + + for (dir = 0; dir < IP_CT_DIR_MAX; dir++) { + t = &ct->tuplehash[dir].tuple; + + n = sprintf(map->addr[dir].src, "%u.%u.%u.%u", + NIPQUAD(t->src.u3.ip)); + map->addr[dir].srciplen = n; + n += sprintf(map->addr[dir].src + n, ":%u", + ntohs(t->src.u.udp.port)); + map->addr[dir].srclen = n; + + n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u", + NIPQUAD(t->dst.u3.ip)); + map->addr[dir].dstiplen = n; + n += sprintf(map->addr[dir].dst + n, ":%u", + ntohs(t->dst.u.udp.port)); + map->addr[dir].dstlen = n; + } +} + +static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, + struct nf_conn *ct, const char **dptr, size_t dlen, + enum sip_header_pos pos, struct addr_map *map) +{ + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + unsigned int matchlen, matchoff, addrlen; + char *addr; + + if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) + return 1; + + if ((matchlen == map->addr[dir].srciplen || + matchlen == map->addr[dir].srclen) && + memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) { + addr = map->addr[!dir].dst; + addrlen = map->addr[!dir].dstlen; + } else if ((matchlen == map->addr[dir].dstiplen || + matchlen == map->addr[dir].dstlen) && + memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) { + addr = map->addr[!dir].src; + addrlen = map->addr[!dir].srclen; + } else + return 1; + + if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, addr, addrlen)) + return 0; + *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + return 1; + +} + +static unsigned int ip_nat_sip(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + const char **dptr) +{ + enum sip_header_pos pos; + struct addr_map map; + int dataoff, datalen; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + datalen = (*pskb)->len - dataoff; + if (datalen < sizeof("SIP/2.0") - 1) + return NF_DROP; + + addr_map_init(ct, &map); + + /* Basic rules: requests and responses. */ + if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) { + /* 10.2: Constructing the REGISTER Request: + * + * The "userinfo" and "@" components of the SIP URI MUST NOT + * be present. + */ + if (datalen >= sizeof("REGISTER") - 1 && + strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0) + pos = POS_REG_REQ_URI; + else + pos = POS_REQ_URI; + + if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map)) + return NF_DROP; + } + + if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || + !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) + return NF_DROP; + return NF_ACCEPT; +} + +static unsigned int mangle_sip_packet(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + const char **dptr, size_t dlen, + char *buffer, int bufflen, + enum sip_header_pos pos) +{ + unsigned int matchlen, matchoff; + + if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) + return 0; + + if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, buffer, bufflen)) + return 0; + + /* We need to reload this. Thanks Patrick. */ + *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + return 1; +} + +static int mangle_content_len(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + const char *dptr) +{ + unsigned int dataoff, matchoff, matchlen; + char buffer[sizeof("65536")]; + int bufflen; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + + /* Get actual SDP lenght */ + if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, + &matchlen, POS_SDP_HEADER) > 0) { + + /* since ct_sip_get_info() give us a pointer passing 'v=' + we need to add 2 bytes in this count. */ + int c_len = (*pskb)->len - dataoff - matchoff + 2; + + /* Now, update SDP length */ + if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, + &matchlen, POS_CONTENT) > 0) { + + bufflen = sprintf(buffer, "%u", c_len); + return nf_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, + buffer, bufflen); + } + } + return 0; +} + +static unsigned int mangle_sdp(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + __be32 newip, u_int16_t port, + const char *dptr) +{ + char buffer[sizeof("nnn.nnn.nnn.nnn")]; + unsigned int dataoff, bufflen; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + + /* Mangle owner and contact info. */ + bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, POS_OWNER_IP4)) + return 0; + + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, POS_CONNECTION_IP4)) + return 0; + + /* Mangle media port. */ + bufflen = sprintf(buffer, "%u", port); + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, POS_MEDIA)) + return 0; + + return mangle_content_len(pskb, ctinfo, ct, dptr); +} + +/* So, this packet has hit the connection tracking matching code. + Mangle it, and change the expectation to match the new version. */ +static unsigned int ip_nat_sdp(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conntrack_expect *exp, + const char *dptr) +{ + struct nf_conn *ct = exp->master; + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + __be32 newip; + u_int16_t port; + + DEBUGP("ip_nat_sdp():\n"); + + /* Connection will come from reply */ + newip = ct->tuplehash[!dir].tuple.dst.u3.ip; + + exp->tuple.dst.u3.ip = newip; + exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; + exp->dir = !dir; + + /* When you see the packet, we need to NAT it the same as the + this one. */ + exp->expectfn = nf_nat_follow_master; + + /* 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) + break; + } + + if (port == 0) + return NF_DROP; + + if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { + nf_conntrack_unexpect_related(exp); + return NF_DROP; + } + return NF_ACCEPT; +} + +static void __exit nf_nat_sip_fini(void) +{ + rcu_assign_pointer(nf_nat_sip_hook, NULL); + rcu_assign_pointer(nf_nat_sdp_hook, NULL); + synchronize_rcu(); +} + +static int __init nf_nat_sip_init(void) +{ + BUG_ON(rcu_dereference(nf_nat_sip_hook)); + BUG_ON(rcu_dereference(nf_nat_sdp_hook)); + rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); + rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp); + return 0; +} + +module_init(nf_nat_sip_init); +module_exit(nf_nat_sip_fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 6b2eb26ae03f..e73891194b31 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -236,6 +236,18 @@ config NF_CONNTRACK_PPTP To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_SIP + tristate "SIP protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + help + SIP is an application-layer control protocol that can establish, + modify, and terminate multimedia sessions (conferences) such as + Internet telephony calls. With the ip_conntrack_sip and + the nf_nat_sip modules you can support the protocol on a connection + tracking/NATing firewall. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 897bed4cbd79..86da21700aa3 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o +obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c new file mode 100644 index 000000000000..e0c06795a943 --- /dev/null +++ b/net/netfilter/nf_conntrack_sip.c @@ -0,0 +1,530 @@ +/* SIP extension for IP connection tracking. + * + * (C) 2005 by Christian Hentschel + * based on RR's ip_conntrack_ftp.c and other modules. + * + * 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 + +#include +#include +#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"); +MODULE_ALIAS("ip_conntrack_sip"); + +#define MAX_PORTS 8 +static unsigned short ports[MAX_PORTS]; +static int ports_c; +module_param_array(ports, ushort, &ports_c, 0400); +MODULE_PARM_DESC(ports, "port numbers of SIP servers"); + +static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT; +module_param(sip_timeout, uint, 0600); +MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); + +unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conn *ct, + const char **dptr) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_sip_hook); + +unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conntrack_expect *exp, + const char *dptr) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_sdp_hook); + +static int digits_len(struct nf_conn *, const char *, const char *, int *); +static int epaddr_len(struct nf_conn *, const char *, const char *, int *); +static int skp_digits_len(struct nf_conn *, const char *, const char *, int *); +static int skp_epaddr_len(struct nf_conn *, const char *, const char *, int *); + +struct sip_header_nfo { + const char *lname; + const char *sname; + const char *ln_str; + size_t lnlen; + size_t snlen; + size_t ln_strlen; + int case_sensitive; + int (*match_len)(struct nf_conn *, const char *, + const char *, int *); +}; + +static const struct sip_header_nfo ct_sip_hdrs[] = { + [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */ + .lname = "sip:", + .lnlen = sizeof("sip:") - 1, + .ln_str = ":", + .ln_strlen = sizeof(":") - 1, + .match_len = epaddr_len, + }, + [POS_REQ_URI] = { /* SIP request URI */ + .lname = "sip:", + .lnlen = sizeof("sip:") - 1, + .ln_str = "@", + .ln_strlen = sizeof("@") - 1, + .match_len = epaddr_len, + }, + [POS_FROM] = { /* SIP From header */ + .lname = "From:", + .lnlen = sizeof("From:") - 1, + .sname = "\r\nf:", + .snlen = sizeof("\r\nf:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len, + }, + [POS_TO] = { /* SIP To header */ + .lname = "To:", + .lnlen = sizeof("To:") - 1, + .sname = "\r\nt:", + .snlen = sizeof("\r\nt:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len + }, + [POS_VIA] = { /* SIP Via header */ + .lname = "Via:", + .lnlen = sizeof("Via:") - 1, + .sname = "\r\nv:", + .snlen = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */ + .ln_str = "UDP ", + .ln_strlen = sizeof("UDP ") - 1, + .match_len = epaddr_len, + }, + [POS_CONTACT] = { /* SIP Contact header */ + .lname = "Contact:", + .lnlen = sizeof("Contact:") - 1, + .sname = "\r\nm:", + .snlen = sizeof("\r\nm:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len + }, + [POS_CONTENT] = { /* SIP Content length header */ + .lname = "Content-Length:", + .lnlen = sizeof("Content-Length:") - 1, + .sname = "\r\nl:", + .snlen = sizeof("\r\nl:") - 1, + .ln_str = ":", + .ln_strlen = sizeof(":") - 1, + .match_len = skp_digits_len + }, + [POS_MEDIA] = { /* SDP media info */ + .case_sensitive = 1, + .lname = "\nm=", + .lnlen = sizeof("\nm=") - 1, + .sname = "\rm=", + .snlen = sizeof("\rm=") - 1, + .ln_str = "audio ", + .ln_strlen = sizeof("audio ") - 1, + .match_len = digits_len + }, + [POS_OWNER_IP4] = { /* SDP owner address*/ + .case_sensitive = 1, + .lname = "\no=", + .lnlen = sizeof("\no=") - 1, + .sname = "\ro=", + .snlen = sizeof("\ro=") - 1, + .ln_str = "IN IP4 ", + .ln_strlen = sizeof("IN IP4 ") - 1, + .match_len = epaddr_len + }, + [POS_CONNECTION_IP4] = {/* SDP connection info */ + .case_sensitive = 1, + .lname = "\nc=", + .lnlen = sizeof("\nc=") - 1, + .sname = "\rc=", + .snlen = sizeof("\rc=") - 1, + .ln_str = "IN IP4 ", + .ln_strlen = sizeof("IN IP4 ") - 1, + .match_len = epaddr_len + }, + [POS_OWNER_IP6] = { /* SDP owner address*/ + .case_sensitive = 1, + .lname = "\no=", + .lnlen = sizeof("\no=") - 1, + .sname = "\ro=", + .snlen = sizeof("\ro=") - 1, + .ln_str = "IN IP6 ", + .ln_strlen = sizeof("IN IP6 ") - 1, + .match_len = epaddr_len + }, + [POS_CONNECTION_IP6] = {/* SDP connection info */ + .case_sensitive = 1, + .lname = "\nc=", + .lnlen = sizeof("\nc=") - 1, + .sname = "\rc=", + .snlen = sizeof("\rc=") - 1, + .ln_str = "IN IP6 ", + .ln_strlen = sizeof("IN IP6 ") - 1, + .match_len = epaddr_len + }, + [POS_SDP_HEADER] = { /* SDP version header */ + .case_sensitive = 1, + .lname = "\nv=", + .lnlen = sizeof("\nv=") - 1, + .sname = "\rv=", + .snlen = sizeof("\rv=") - 1, + .ln_str = "=", + .ln_strlen = sizeof("=") - 1, + .match_len = digits_len + } +}; + +/* get line lenght until first CR or LF seen. */ +int ct_sip_lnlen(const char *line, const char *limit) +{ + const char *k = line; + + while ((line <= limit) && (*line == '\r' || *line == '\n')) + line++; + + while (line <= limit) { + if (*line == '\r' || *line == '\n') + break; + line++; + } + return line - k; +} +EXPORT_SYMBOL_GPL(ct_sip_lnlen); + +/* Linear string search, case sensitive. */ +const char *ct_sip_search(const char *needle, const char *haystack, + size_t needle_len, size_t haystack_len, + int case_sensitive) +{ + const char *limit = haystack + (haystack_len - needle_len); + + while (haystack <= limit) { + if (case_sensitive) { + if (strncmp(haystack, needle, needle_len) == 0) + return haystack; + } else { + if (strnicmp(haystack, needle, needle_len) == 0) + return haystack; + } + haystack++; + } + return NULL; +} +EXPORT_SYMBOL_GPL(ct_sip_search); + +static int digits_len(struct nf_conn *ct, const char *dptr, + const char *limit, int *shift) +{ + int len = 0; + while (dptr <= limit && isdigit(*dptr)) { + dptr++; + len++; + } + return len; +} + +/* get digits lenght, skiping blank spaces. */ +static int skp_digits_len(struct nf_conn *ct, const char *dptr, + const char *limit, int *shift) +{ + for (; dptr <= limit && *dptr == ' '; dptr++) + (*shift)++; + + return digits_len(ct, dptr, limit, shift); +} + +static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp, + union nf_conntrack_address *addr, const char *limit) +{ + const char *end; + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + int ret = 0; + + switch (family) { + case AF_INET: + ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); + break; + case AF_INET6: + ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); + break; + default: + BUG(); + } + + if (ret == 0 || end == cp) + return 0; + if (endp) + *endp = end; + return 1; +} + +/* skip ip address. returns its length. */ +static int epaddr_len(struct nf_conn *ct, const char *dptr, + const char *limit, int *shift) +{ + union nf_conntrack_address addr; + const char *aux = dptr; + + if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { + DEBUGP("ip: %s parse failed.!\n", dptr); + return 0; + } + + /* Port number */ + if (*dptr == ':') { + dptr++; + dptr += digits_len(ct, dptr, limit, shift); + } + return dptr - aux; +} + +/* get address length, skiping user info. */ +static int skp_epaddr_len(struct nf_conn *ct, const char *dptr, + const char *limit, int *shift) +{ + int s = *shift; + + for (; dptr <= limit && *dptr != '@'; dptr++) + (*shift)++; + + if (*dptr == '@') { + dptr++; + (*shift)++; + } else + *shift = s; + + return epaddr_len(ct, dptr, limit, shift); +} + +/* Returns 0 if not found, -1 error parsing. */ +int ct_sip_get_info(struct nf_conn *ct, + const char *dptr, size_t dlen, + unsigned int *matchoff, + unsigned int *matchlen, + enum sip_header_pos pos) +{ + const struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos]; + const char *limit, *aux, *k = dptr; + int shift = 0; + + limit = dptr + (dlen - hnfo->lnlen); + + while (dptr <= limit) { + if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) && + (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { + dptr++; + continue; + } + aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen, + ct_sip_lnlen(dptr, limit), + hnfo->case_sensitive); + if (!aux) { + DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, + hnfo->lname); + return -1; + } + aux += hnfo->ln_strlen; + + *matchlen = hnfo->match_len(ct, aux, limit, &shift); + if (!*matchlen) + return -1; + + *matchoff = (aux - k) + shift; + + DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, + *matchlen); + return 1; + } + DEBUGP("%s header not found.\n", hnfo->lname); + return 0; +} +EXPORT_SYMBOL_GPL(ct_sip_get_info); + +static int set_expected_rtp(struct sk_buff **pskb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + union nf_conntrack_address *addr, + __be16 port, + const char *dptr) +{ + struct nf_conntrack_expect *exp; + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + int family = ct->tuplehash[!dir].tuple.src.l3num; + int ret; + typeof(nf_nat_sdp_hook) nf_nat_sdp; + + exp = nf_conntrack_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_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) + ret = NF_DROP; + else + ret = NF_ACCEPT; + } + nf_conntrack_expect_put(exp); + + return ret; +} + +static int sip_help(struct sk_buff **pskb, + unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + union nf_conntrack_address addr; + unsigned int dataoff, datalen; + const char *dptr; + int ret = NF_ACCEPT; + int matchoff, matchlen; + u_int16_t port; + enum sip_header_pos pos; + typeof(nf_nat_sip_hook) nf_nat_sip; + + /* No Data ? */ + dataoff = protoff + sizeof(struct udphdr); + if (dataoff >= (*pskb)->len) + return NF_ACCEPT; + + nf_ct_refresh(ct, *pskb, sip_timeout * HZ); + + if (!skb_is_nonlinear(*pskb)) + dptr = (*pskb)->data + dataoff; + else { + DEBUGP("Copy of skbuff not supported yet.\n"); + goto out; + } + + nf_nat_sip = rcu_dereference(nf_nat_sip_hook); + if (nf_nat_sip && ct->status & IPS_NAT_MASK) { + if (!nf_nat_sip(pskb, ctinfo, ct, &dptr)) { + ret = NF_DROP; + goto out; + } + } + + datalen = (*pskb)->len - dataoff; + if (datalen < sizeof("SIP/2.0 200") - 1) + goto out; + + /* RTP info only in some SDP pkts */ + if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 && + memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) { + goto out; + } + /* Get address and port from SDP packet. */ + pos = family == AF_INET ? POS_CONNECTION_IP4 : POS_CONNECTION_IP6; + if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen, pos) > 0) { + + /* We'll drop only if there are parse problems. */ + if (!parse_addr(ct, dptr + matchoff, NULL, &addr, + dptr + datalen)) { + ret = NF_DROP; + goto out; + } + if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen, + POS_MEDIA) > 0) { + + port = simple_strtoul(dptr + matchoff, NULL, 10); + if (port < 1024) { + ret = NF_DROP; + goto out; + } + ret = set_expected_rtp(pskb, ct, ctinfo, &addr, + htons(port), dptr); + } + } +out: + return ret; +} + +static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; +static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly; + +static void nf_conntrack_sip_fini(void) +{ + int i, j; + + for (i = 0; i < ports_c; i++) { + for (j = 0; j < 2; j++) { + if (sip[i][j].me == NULL) + continue; + nf_conntrack_helper_unregister(&sip[i][j]); + } + } +} + +static int __init nf_conntrack_sip_init(void) +{ + int i, j, ret; + char *tmpname; + + if (ports_c == 0) + ports[ports_c++] = SIP_PORT; + + for (i = 0; i < ports_c; i++) { + memset(&sip[i], 0, sizeof(sip[i])); + + sip[i][0].tuple.src.l3num = AF_INET; + sip[i][1].tuple.src.l3num = AF_INET6; + 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; + sip[i][j].help = sip_help; + + tmpname = &sip_names[i][j][0]; + if (ports[i] == SIP_PORT) + sprintf(tmpname, "sip"); + else + sprintf(tmpname, "sip-%u", i); + sip[i][j].name = tmpname; + + DEBUGP("port #%u: %u\n", i, ports[i]); + + ret = nf_conntrack_helper_register(&sip[i][j]); + if (ret) { + printk("nf_ct_sip: failed to register helper " + "for pf: %u port: %u\n", + sip[i][j].tuple.src.l3num, ports[i]); + nf_conntrack_sip_fini(); + return ret; + } + } + } + return 0; +} + +module_init(nf_conntrack_sip_init); +module_exit(nf_conntrack_sip_fini); -- cgit v1.2.3-70-g09d2 From a536df35b3a58caa9015bf7887a374b20f658368 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:10:18 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: add TFTP helper port Add IPv4 and IPv6 capable nf_conntrack port of the TFTP conntrack/NAT helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_tftp.h | 20 ++++ net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 1 + net/ipv4/netfilter/nf_nat_tftp.c | 52 +++++++++ net/netfilter/Kconfig | 11 ++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_tftp.c | 159 ++++++++++++++++++++++++++++ 7 files changed, 249 insertions(+) create mode 100644 include/linux/netfilter/nf_conntrack_tftp.h create mode 100644 net/ipv4/netfilter/nf_nat_tftp.c create mode 100644 net/netfilter/nf_conntrack_tftp.c (limited to 'net') diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h new file mode 100644 index 000000000000..0d79b7ae051f --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_tftp.h @@ -0,0 +1,20 @@ +#ifndef _NF_CONNTRACK_TFTP_H +#define _NF_CONNTRACK_TFTP_H + +#define TFTP_PORT 69 + +struct tftphdr { + __be16 opcode; +}; + +#define TFTP_OPCODE_READ 1 +#define TFTP_OPCODE_WRITE 2 +#define TFTP_OPCODE_DATA 3 +#define TFTP_OPCODE_ACK 4 +#define TFTP_OPCODE_ERROR 5 + +extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conntrack_expect *exp); + +#endif /* _NF_CONNTRACK_TFTP_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 83e83f553ccb..1c0018b6bea4 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -515,6 +515,11 @@ config IP_NF_NAT_TFTP default IP_NF_NAT if IP_NF_TFTP=y default m if IP_NF_TFTP=m +config NF_NAT_TFTP + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_TFTP + config IP_NF_NAT_AMANDA tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 167b65e89aca..3ca0af0ed5f0 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o +obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o # NAT protocols (nf_nat) obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c new file mode 100644 index 000000000000..2566b79de224 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_tftp.c @@ -0,0 +1,52 @@ +/* (C) 2001-2002 Magnus Boden + * + * 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 +#include +#include + +MODULE_AUTHOR("Magnus Boden "); +MODULE_DESCRIPTION("TFTP NAT helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_nat_tftp"); + +static unsigned int help(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct nf_conntrack_expect *exp) +{ + struct nf_conn *ct = exp->master; + + exp->saved_proto.udp.port + = 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) + return NF_DROP; + return NF_ACCEPT; +} + +static void __exit nf_nat_tftp_fini(void) +{ + rcu_assign_pointer(nf_nat_tftp_hook, NULL); + synchronize_rcu(); +} + +static int __init nf_nat_tftp_init(void) +{ + BUG_ON(rcu_dereference(nf_nat_tftp_hook)); + rcu_assign_pointer(nf_nat_tftp_hook, help); + return 0; +} + +module_init(nf_nat_tftp_init); +module_exit(nf_nat_tftp_fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index e73891194b31..e0deac17df12 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -248,6 +248,17 @@ config NF_CONNTRACK_SIP To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_TFTP + tristate "TFTP protocol support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + help + TFTP connection tracking helper, this is required depending + on how restrictive your ruleset is. + If you are using a tftp client behind -j SNAT or -j MASQUERADING + you will need this. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 86da21700aa3..5dc5574f7e99 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o +obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c new file mode 100644 index 000000000000..d46a1263fcb5 --- /dev/null +++ b/net/netfilter/nf_conntrack_tftp.c @@ -0,0 +1,159 @@ +/* (C) 2001-2002 Magnus Boden + * + * 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 +#include +#include +#include +#include + +MODULE_AUTHOR("Magnus Boden "); +MODULE_DESCRIPTION("TFTP connection tracking helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_tftp"); + +#define MAX_PORTS 8 +static unsigned short ports[MAX_PORTS]; +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; +EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); + +static int tftp_help(struct sk_buff **pskb, + unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + struct tftphdr _tftph, *tfh; + struct nf_conntrack_expect *exp; + struct nf_conntrack_tuple *tuple; + unsigned int ret = NF_ACCEPT; + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + typeof(nf_nat_tftp_hook) nf_nat_tftp; + + tfh = skb_header_pointer(*pskb, protoff + sizeof(struct udphdr), + sizeof(_tftph), &_tftph); + if (tfh == NULL) + return NF_ACCEPT; + + switch (ntohs(tfh->opcode)) { + 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); + + exp = nf_conntrack_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); + + DEBUGP("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) + ret = nf_nat_tftp(pskb, ctinfo, exp); + else if (nf_conntrack_expect_related(exp) != 0) + ret = NF_DROP; + nf_conntrack_expect_put(exp); + break; + case TFTP_OPCODE_DATA: + case TFTP_OPCODE_ACK: + DEBUGP("Data/ACK opcode\n"); + break; + case TFTP_OPCODE_ERROR: + DEBUGP("Error opcode\n"); + break; + default: + DEBUGP("Unknown opcode\n"); + } + return ret; +} + +static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly; +static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly; + +static void nf_conntrack_tftp_fini(void) +{ + int i, j; + + for (i = 0; i < ports_c; i++) { + for (j = 0; j < 2; j++) + nf_conntrack_helper_unregister(&tftp[i][j]); + } +} + +static int __init nf_conntrack_tftp_init(void) +{ + int i, j, ret; + char *tmpname; + + if (ports_c == 0) + ports[ports_c++] = TFTP_PORT; + + for (i = 0; i < ports_c; i++) { + memset(&tftp[i], 0, sizeof(tftp[i])); + + tftp[i][0].tuple.src.l3num = AF_INET; + tftp[i][1].tuple.src.l3num = AF_INET6; + 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; + tftp[i][j].help = tftp_help; + + tmpname = &tftp_names[i][j][0]; + if (ports[i] == TFTP_PORT) + sprintf(tmpname, "tftp"); + else + sprintf(tmpname, "tftp-%u", i); + tftp[i][j].name = tmpname; + + ret = nf_conntrack_helper_register(&tftp[i][j]); + if (ret) { + printk("nf_ct_tftp: failed to register helper " + "for pf: %u port: %u\n", + tftp[i][j].tuple.src.l3num, ports[i]); + nf_conntrack_tftp_fini(); + return ret; + } + } + } + return 0; +} + +module_init(nf_conntrack_tftp_init); +module_exit(nf_conntrack_tftp_fini); -- cgit v1.2.3-70-g09d2 From 807467c22a12381985878be23c778657fc0364d0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:10:34 -0800 Subject: [NETFILTER]: nf_nat: add SNMP NAT helper port Add nf_conntrack port of the SNMP NAT helper. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/Kconfig | 15 + net/ipv4/netfilter/Makefile | 1 + net/ipv4/netfilter/nf_nat_snmp_basic.c | 1332 ++++++++++++++++++++++++++++++++ 3 files changed, 1348 insertions(+) create mode 100644 net/ipv4/netfilter/nf_nat_snmp_basic.c (limited to 'net') diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 1c0018b6bea4..16390add2ebf 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -477,6 +477,21 @@ config IP_NF_NAT_SNMP_BASIC To compile it as a module, choose M here. If unsure, say N. +config NF_NAT_SNMP_BASIC + tristate "Basic SNMP-ALG support (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_NAT + ---help--- + + This module implements an Application Layer Gateway (ALG) for + SNMP payloads. In conjunction with NAT, it allows a network + management system to access multiple private networks with + conflicting addresses. It works by modifying IP addresses + inside SNMP payloads to match IP-layer NAT mapping. + + This is the "basic" form of SNMP-ALG, as described in RFC 2962 + + To compile it as a module, choose M here. If unsure, say N. + # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. # From kconfig-language.txt: diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 3ca0af0ed5f0..15e741aeb291 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o +obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o # NAT protocols (nf_nat) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c new file mode 100644 index 000000000000..f12528fe1bf9 --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -0,0 +1,1332 @@ +/* + * nf_nat_snmp_basic.c + * + * Basic SNMP Application Layer Gateway + * + * This IP NAT module is intended for use with SNMP network + * discovery and monitoring applications where target networks use + * conflicting private address realms. + * + * Static NAT is used to remap the networks from the view of the network + * management system at the IP layer, and this module remaps some application + * layer addresses to match. + * + * The simplest form of ALG is performed, where only tagged IP addresses + * are modified. The module does not need to be MIB aware and only scans + * messages at the ASN.1/BER level. + * + * Currently, only SNMPv1 and SNMPv2 are supported. + * + * More information on ALG and associated issues can be found in + * RFC 2962 + * + * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory + * McLean & Jochen Friedrich, stripped down for use in the kernel. + * + * Copyright (c) 2000 RP Internet (www.rpi.net.au). + * + * 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. + * 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 the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: James Morris + * + * Updates: + * 2000-08-06: Convert to new helper API (Harald Welte). + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("James Morris "); +MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway"); +MODULE_ALIAS("ip_nat_snmp_basic"); + +#define SNMP_PORT 161 +#define SNMP_TRAP_PORT 162 +#define NOCT1(n) (*(u8 *)n) + +static int debug; +static DEFINE_SPINLOCK(snmp_lock); + +/* + * Application layer address mapping mimics the NAT mapping, but + * only for the first octet in this case (a more flexible system + * can be implemented if needed). + */ +struct oct1_map +{ + u_int8_t from; + u_int8_t to; +}; + + +/***************************************************************************** + * + * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) + * + *****************************************************************************/ + +/* Class */ +#define ASN1_UNI 0 /* Universal */ +#define ASN1_APL 1 /* Application */ +#define ASN1_CTX 2 /* Context */ +#define ASN1_PRV 3 /* Private */ + +/* Tag */ +#define ASN1_EOC 0 /* End Of Contents */ +#define ASN1_BOL 1 /* Boolean */ +#define ASN1_INT 2 /* Integer */ +#define ASN1_BTS 3 /* Bit String */ +#define ASN1_OTS 4 /* Octet String */ +#define ASN1_NUL 5 /* Null */ +#define ASN1_OJI 6 /* Object Identifier */ +#define ASN1_OJD 7 /* Object Description */ +#define ASN1_EXT 8 /* External */ +#define ASN1_SEQ 16 /* Sequence */ +#define ASN1_SET 17 /* Set */ +#define ASN1_NUMSTR 18 /* Numerical String */ +#define ASN1_PRNSTR 19 /* Printable String */ +#define ASN1_TEXSTR 20 /* Teletext String */ +#define ASN1_VIDSTR 21 /* Video String */ +#define ASN1_IA5STR 22 /* IA5 String */ +#define ASN1_UNITIM 23 /* Universal Time */ +#define ASN1_GENTIM 24 /* General Time */ +#define ASN1_GRASTR 25 /* Graphical String */ +#define ASN1_VISSTR 26 /* Visible String */ +#define ASN1_GENSTR 27 /* General String */ + +/* Primitive / Constructed methods*/ +#define ASN1_PRI 0 /* Primitive */ +#define ASN1_CON 1 /* Constructed */ + +/* + * Error codes. + */ +#define ASN1_ERR_NOERROR 0 +#define ASN1_ERR_DEC_EMPTY 2 +#define ASN1_ERR_DEC_EOC_MISMATCH 3 +#define ASN1_ERR_DEC_LENGTH_MISMATCH 4 +#define ASN1_ERR_DEC_BADVALUE 5 + +/* + * ASN.1 context. + */ +struct asn1_ctx +{ + int error; /* Error condition */ + unsigned char *pointer; /* Octet just to be decoded */ + unsigned char *begin; /* First octet */ + unsigned char *end; /* Octet after last octet */ +}; + +/* + * Octet string (not null terminated) + */ +struct asn1_octstr +{ + unsigned char *data; + unsigned int len; +}; + +static void asn1_open(struct asn1_ctx *ctx, + unsigned char *buf, + unsigned int len) +{ + ctx->begin = buf; + ctx->end = buf + len; + ctx->pointer = buf; + ctx->error = ASN1_ERR_NOERROR; +} + +static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) +{ + if (ctx->pointer >= ctx->end) { + ctx->error = ASN1_ERR_DEC_EMPTY; + return 0; + } + *ch = *(ctx->pointer)++; + return 1; +} + +static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) +{ + unsigned char ch; + + *tag = 0; + + do + { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + *tag <<= 7; + *tag |= ch & 0x7F; + } while ((ch & 0x80) == 0x80); + return 1; +} + +static unsigned char asn1_id_decode(struct asn1_ctx *ctx, + unsigned int *cls, + unsigned int *con, + unsigned int *tag) +{ + unsigned char ch; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *cls = (ch & 0xC0) >> 6; + *con = (ch & 0x20) >> 5; + *tag = (ch & 0x1F); + + if (*tag == 0x1F) { + if (!asn1_tag_decode(ctx, tag)) + return 0; + } + return 1; +} + +static unsigned char asn1_length_decode(struct asn1_ctx *ctx, + unsigned int *def, + unsigned int *len) +{ + unsigned char ch, cnt; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch == 0x80) + *def = 0; + else { + *def = 1; + + if (ch < 0x80) + *len = ch; + else { + cnt = (unsigned char) (ch & 0x7F); + *len = 0; + + while (cnt > 0) { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + *len <<= 8; + *len |= ch; + cnt--; + } + } + } + return 1; +} + +static unsigned char asn1_header_decode(struct asn1_ctx *ctx, + unsigned char **eoc, + unsigned int *cls, + unsigned int *con, + unsigned int *tag) +{ + unsigned int def, len; + + if (!asn1_id_decode(ctx, cls, con, tag)) + return 0; + + def = len = 0; + if (!asn1_length_decode(ctx, &def, &len)) + return 0; + + if (def) + *eoc = ctx->pointer + len; + else + *eoc = NULL; + return 1; +} + +static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) +{ + unsigned char ch; + + if (eoc == 0) { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch != 0x00) { + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch != 0x00) { + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; + return 0; + } + return 1; + } else { + if (ctx->pointer != eoc) { + ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH; + return 0; + } + return 1; + } +} + +static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc) +{ + ctx->pointer = eoc; + return 1; +} + +static unsigned char asn1_long_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + long *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = (signed char) ch; + len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof (long)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char asn1_uint_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned int *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = ch; + if (ch == 0) len = 0; + else len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof (unsigned int)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned long *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = ch; + if (ch == 0) len = 0; + else len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof (unsigned long)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char asn1_octets_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned char **octets, + unsigned int *len) +{ + unsigned char *ptr; + + *len = 0; + + *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); + if (*octets == NULL) { + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + + ptr = *octets; + while (ctx->pointer < eoc) { + if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) { + kfree(*octets); + *octets = NULL; + return 0; + } + (*len)++; + } + return 1; +} + +static unsigned char asn1_subid_decode(struct asn1_ctx *ctx, + unsigned long *subid) +{ + unsigned char ch; + + *subid = 0; + + do { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *subid <<= 7; + *subid |= ch & 0x7F; + } while ((ch & 0x80) == 0x80); + return 1; +} + +static unsigned char asn1_oid_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned long **oid, + unsigned int *len) +{ + unsigned long subid; + unsigned int size; + unsigned long *optr; + + size = eoc - ctx->pointer + 1; + *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); + if (*oid == NULL) { + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + + optr = *oid; + + if (!asn1_subid_decode(ctx, &subid)) { + kfree(*oid); + *oid = NULL; + return 0; + } + + if (subid < 40) { + optr [0] = 0; + optr [1] = subid; + } else if (subid < 80) { + optr [0] = 1; + optr [1] = subid - 40; + } else { + optr [0] = 2; + optr [1] = subid - 80; + } + + *len = 2; + optr += 2; + + while (ctx->pointer < eoc) { + if (++(*len) > size) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + kfree(*oid); + *oid = NULL; + return 0; + } + + if (!asn1_subid_decode(ctx, optr++)) { + kfree(*oid); + *oid = NULL; + return 0; + } + } + return 1; +} + +/***************************************************************************** + * + * SNMP decoding routines (gxsnmp author Dirk Wisse) + * + *****************************************************************************/ + +/* SNMP Versions */ +#define SNMP_V1 0 +#define SNMP_V2C 1 +#define SNMP_V2 2 +#define SNMP_V3 3 + +/* Default Sizes */ +#define SNMP_SIZE_COMM 256 +#define SNMP_SIZE_OBJECTID 128 +#define SNMP_SIZE_BUFCHR 256 +#define SNMP_SIZE_BUFINT 128 +#define SNMP_SIZE_SMALLOBJECTID 16 + +/* Requests */ +#define SNMP_PDU_GET 0 +#define SNMP_PDU_NEXT 1 +#define SNMP_PDU_RESPONSE 2 +#define SNMP_PDU_SET 3 +#define SNMP_PDU_TRAP1 4 +#define SNMP_PDU_BULK 5 +#define SNMP_PDU_INFORM 6 +#define SNMP_PDU_TRAP2 7 + +/* Errors */ +#define SNMP_NOERROR 0 +#define SNMP_TOOBIG 1 +#define SNMP_NOSUCHNAME 2 +#define SNMP_BADVALUE 3 +#define SNMP_READONLY 4 +#define SNMP_GENERROR 5 +#define SNMP_NOACCESS 6 +#define SNMP_WRONGTYPE 7 +#define SNMP_WRONGLENGTH 8 +#define SNMP_WRONGENCODING 9 +#define SNMP_WRONGVALUE 10 +#define SNMP_NOCREATION 11 +#define SNMP_INCONSISTENTVALUE 12 +#define SNMP_RESOURCEUNAVAILABLE 13 +#define SNMP_COMMITFAILED 14 +#define SNMP_UNDOFAILED 15 +#define SNMP_AUTHORIZATIONERROR 16 +#define SNMP_NOTWRITABLE 17 +#define SNMP_INCONSISTENTNAME 18 + +/* General SNMP V1 Traps */ +#define SNMP_TRAP_COLDSTART 0 +#define SNMP_TRAP_WARMSTART 1 +#define SNMP_TRAP_LINKDOWN 2 +#define SNMP_TRAP_LINKUP 3 +#define SNMP_TRAP_AUTFAILURE 4 +#define SNMP_TRAP_EQPNEIGHBORLOSS 5 +#define SNMP_TRAP_ENTSPECIFIC 6 + +/* SNMPv1 Types */ +#define SNMP_NULL 0 +#define SNMP_INTEGER 1 /* l */ +#define SNMP_OCTETSTR 2 /* c */ +#define SNMP_DISPLAYSTR 2 /* c */ +#define SNMP_OBJECTID 3 /* ul */ +#define SNMP_IPADDR 4 /* uc */ +#define SNMP_COUNTER 5 /* ul */ +#define SNMP_GAUGE 6 /* ul */ +#define SNMP_TIMETICKS 7 /* ul */ +#define SNMP_OPAQUE 8 /* c */ + +/* Additional SNMPv2 Types */ +#define SNMP_UINTEGER 5 /* ul */ +#define SNMP_BITSTR 9 /* uc */ +#define SNMP_NSAP 10 /* uc */ +#define SNMP_COUNTER64 11 /* ul */ +#define SNMP_NOSUCHOBJECT 12 +#define SNMP_NOSUCHINSTANCE 13 +#define SNMP_ENDOFMIBVIEW 14 + +union snmp_syntax +{ + unsigned char uc[0]; /* 8 bit unsigned */ + char c[0]; /* 8 bit signed */ + unsigned long ul[0]; /* 32 bit unsigned */ + long l[0]; /* 32 bit signed */ +}; + +struct snmp_object +{ + unsigned long *id; + unsigned int id_len; + unsigned short type; + unsigned int syntax_len; + union snmp_syntax syntax; +}; + +struct snmp_request +{ + unsigned long id; + unsigned int error_status; + unsigned int error_index; +}; + +struct snmp_v1_trap +{ + unsigned long *id; + unsigned int id_len; + unsigned long ip_address; /* pointer */ + unsigned int general; + unsigned int specific; + unsigned long time; +}; + +/* SNMP types */ +#define SNMP_IPA 0 +#define SNMP_CNT 1 +#define SNMP_GGE 2 +#define SNMP_TIT 3 +#define SNMP_OPQ 4 +#define SNMP_C64 6 + +/* SNMP errors */ +#define SERR_NSO 0 +#define SERR_NSI 1 +#define SERR_EOM 2 + +static inline void mangle_address(unsigned char *begin, + unsigned char *addr, + const struct oct1_map *map, + __sum16 *check); +struct snmp_cnv +{ + unsigned int class; + unsigned int tag; + int syntax; +}; + +static struct snmp_cnv snmp_conv [] = +{ + {ASN1_UNI, ASN1_NUL, SNMP_NULL}, + {ASN1_UNI, ASN1_INT, SNMP_INTEGER}, + {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR}, + {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR}, + {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID}, + {ASN1_APL, SNMP_IPA, SNMP_IPADDR}, + {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */ + {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */ + {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS}, + {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE}, + + /* SNMPv2 data types and errors */ + {ASN1_UNI, ASN1_BTS, SNMP_BITSTR}, + {ASN1_APL, SNMP_C64, SNMP_COUNTER64}, + {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT}, + {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE}, + {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW}, + {0, 0, -1} +}; + +static unsigned char snmp_tag_cls2syntax(unsigned int tag, + unsigned int cls, + unsigned short *syntax) +{ + struct snmp_cnv *cnv; + + cnv = snmp_conv; + + while (cnv->syntax != -1) { + if (cnv->tag == tag && cnv->class == cls) { + *syntax = cnv->syntax; + return 1; + } + cnv++; + } + return 0; +} + +static unsigned char snmp_object_decode(struct asn1_ctx *ctx, + struct snmp_object **obj) +{ + unsigned int cls, con, tag, len, idlen; + unsigned short type; + unsigned char *eoc, *end, *p; + unsigned long *lp, *id; + unsigned long ul; + long l; + + *obj = NULL; + id = NULL; + + if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) + return 0; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) + return 0; + + if (!asn1_oid_decode(ctx, end, &id, &idlen)) + return 0; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) { + kfree(id); + return 0; + } + + if (con != ASN1_PRI) { + kfree(id); + return 0; + } + + type = 0; + if (!snmp_tag_cls2syntax(tag, cls, &type)) { + kfree(id); + return 0; + } + + l = 0; + switch (type) { + case SNMP_INTEGER: + len = sizeof(long); + if (!asn1_long_decode(ctx, end, &l)) { + kfree(id); + return 0; + } + *obj = kmalloc(sizeof(struct snmp_object) + len, + GFP_ATOMIC); + if (*obj == NULL) { + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + (*obj)->syntax.l[0] = l; + break; + case SNMP_OCTETSTR: + case SNMP_OPAQUE: + if (!asn1_octets_decode(ctx, end, &p, &len)) { + kfree(id); + return 0; + } + *obj = kmalloc(sizeof(struct snmp_object) + len, + GFP_ATOMIC); + if (*obj == NULL) { + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + memcpy((*obj)->syntax.c, p, len); + kfree(p); + break; + case SNMP_NULL: + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + len = 0; + *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC); + if (*obj == NULL) { + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + if (!asn1_null_decode(ctx, end)) { + kfree(id); + kfree(*obj); + *obj = NULL; + return 0; + } + break; + case SNMP_OBJECTID: + if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) { + kfree(id); + return 0; + } + len *= sizeof(unsigned long); + *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); + if (*obj == NULL) { + kfree(lp); + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + memcpy((*obj)->syntax.ul, lp, len); + kfree(lp); + break; + case SNMP_IPADDR: + if (!asn1_octets_decode(ctx, end, &p, &len)) { + kfree(id); + return 0; + } + if (len != 4) { + kfree(p); + kfree(id); + return 0; + } + *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); + if (*obj == NULL) { + kfree(p); + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + memcpy((*obj)->syntax.uc, p, len); + kfree(p); + break; + case SNMP_COUNTER: + case SNMP_GAUGE: + case SNMP_TIMETICKS: + len = sizeof(unsigned long); + if (!asn1_ulong_decode(ctx, end, &ul)) { + kfree(id); + return 0; + } + *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); + if (*obj == NULL) { + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); + return 0; + } + (*obj)->syntax.ul[0] = ul; + break; + default: + kfree(id); + return 0; + } + + (*obj)->syntax_len = len; + (*obj)->type = type; + (*obj)->id = id; + (*obj)->id_len = idlen; + + if (!asn1_eoc_decode(ctx, eoc)) { + kfree(id); + kfree(*obj); + *obj = NULL; + return 0; + } + return 1; +} + +static unsigned char snmp_request_decode(struct asn1_ctx *ctx, + struct snmp_request *request) +{ + unsigned int cls, con, tag; + unsigned char *end; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + return 0; + + if (!asn1_ulong_decode(ctx, end, &request->id)) + return 0; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + return 0; + + if (!asn1_uint_decode(ctx, end, &request->error_status)) + return 0; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + return 0; + + if (!asn1_uint_decode(ctx, end, &request->error_index)) + return 0; + + return 1; +} + +/* + * Fast checksum update for possibly oddly-aligned UDP byte, from the + * code example in the draft. + */ +static void fast_csum(__sum16 *csum, + const unsigned char *optr, + const unsigned char *nptr, + int offset) +{ + unsigned char s[4]; + + if (offset & 1) { + s[0] = s[2] = 0; + s[1] = ~*optr; + s[3] = *nptr; + } else { + s[1] = s[3] = 0; + s[0] = ~*optr; + s[2] = *nptr; + } + + *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum))); +} + +/* + * Mangle IP address. + * - begin points to the start of the snmp messgae + * - addr points to the start of the address + */ +static inline void mangle_address(unsigned char *begin, + unsigned char *addr, + const struct oct1_map *map, + __sum16 *check) +{ + if (map->from == NOCT1(addr)) { + u_int32_t old; + + if (debug) + memcpy(&old, (unsigned char *)addr, sizeof(old)); + + *addr = map->to; + + /* Update UDP checksum if being used */ + if (*check) { + fast_csum(check, + &map->from, &map->to, addr - begin); + + } + + if (debug) + printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to " + "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr)); + } +} + +static unsigned char snmp_trap_decode(struct asn1_ctx *ctx, + struct snmp_v1_trap *trap, + const struct oct1_map *map, + __sum16 *check) +{ + unsigned int cls, con, tag, len; + unsigned char *end; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) + return 0; + + if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len)) + return 0; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + goto err_id_free; + + if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) || + (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) + goto err_id_free; + + if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len)) + goto err_id_free; + + /* IPv4 only */ + if (len != 4) + goto err_addr_free; + + mangle_address(ctx->begin, ctx->pointer - 4, map, check); + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + goto err_addr_free; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + goto err_addr_free; + + if (!asn1_uint_decode(ctx, end, &trap->general)) + goto err_addr_free; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + goto err_addr_free; + + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + goto err_addr_free; + + if (!asn1_uint_decode(ctx, end, &trap->specific)) + goto err_addr_free; + + if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) + goto err_addr_free; + + if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) || + (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) + goto err_addr_free; + + if (!asn1_ulong_decode(ctx, end, &trap->time)) + goto err_addr_free; + + return 1; + +err_addr_free: + kfree((unsigned long *)trap->ip_address); + +err_id_free: + kfree(trap->id); + + return 0; +} + +/***************************************************************************** + * + * Misc. routines + * + *****************************************************************************/ + +static void hex_dump(unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (i && !(i % 16)) + printk("\n"); + printk("%02x ", *(buf + i)); + } + printk("\n"); +} + +/* + * Parse and mangle SNMP message according to mapping. + * (And this is the fucking 'basic' method). + */ +static int snmp_parse_mangle(unsigned char *msg, + u_int16_t len, + const struct oct1_map *map, + __sum16 *check) +{ + unsigned char *eoc, *end; + unsigned int cls, con, tag, vers, pdutype; + struct asn1_ctx ctx; + struct asn1_octstr comm; + struct snmp_object **obj; + + if (debug > 1) + hex_dump(msg, len); + + asn1_open(&ctx, msg, len); + + /* + * Start of SNMP message. + */ + if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag)) + return 0; + if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) + return 0; + + /* + * Version 1 or 2 handled. + */ + if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag)) + return 0; + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) + return 0; + if (!asn1_uint_decode (&ctx, end, &vers)) + return 0; + if (debug > 1) + printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1); + if (vers > 1) + return 1; + + /* + * Community. + */ + if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag)) + return 0; + if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS) + return 0; + if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len)) + return 0; + if (debug > 1) { + unsigned int i; + + printk(KERN_DEBUG "bsalg: community: "); + for (i = 0; i < comm.len; i++) + printk("%c", comm.data[i]); + printk("\n"); + } + kfree(comm.data); + + /* + * PDU type + */ + if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype)) + return 0; + if (cls != ASN1_CTX || con != ASN1_CON) + return 0; + if (debug > 1) { + unsigned char *pdus[] = { + [SNMP_PDU_GET] = "get", + [SNMP_PDU_NEXT] = "get-next", + [SNMP_PDU_RESPONSE] = "response", + [SNMP_PDU_SET] = "set", + [SNMP_PDU_TRAP1] = "trapv1", + [SNMP_PDU_BULK] = "bulk", + [SNMP_PDU_INFORM] = "inform", + [SNMP_PDU_TRAP2] = "trapv2" + }; + + if (pdutype > SNMP_PDU_TRAP2) + printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype); + else + printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]); + } + if (pdutype != SNMP_PDU_RESPONSE && + pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2) + return 1; + + /* + * Request header or v1 trap + */ + if (pdutype == SNMP_PDU_TRAP1) { + struct snmp_v1_trap trap; + unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check); + + if (ret) { + kfree(trap.id); + kfree((unsigned long *)trap.ip_address); + } else + return ret; + + } else { + struct snmp_request req; + + if (!snmp_request_decode(&ctx, &req)) + return 0; + + if (debug > 1) + printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u " + "error_index=%u\n", req.id, req.error_status, + req.error_index); + } + + /* + * Loop through objects, look for IP addresses to mangle. + */ + if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag)) + return 0; + + if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) + return 0; + + obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC); + if (obj == NULL) { + if (net_ratelimit()) + printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__); + return 0; + } + + while (!asn1_eoc_decode(&ctx, eoc)) { + unsigned int i; + + if (!snmp_object_decode(&ctx, obj)) { + if (*obj) { + kfree((*obj)->id); + kfree(*obj); + } + kfree(obj); + return 0; + } + + if (debug > 1) { + printk(KERN_DEBUG "bsalg: object: "); + for (i = 0; i < (*obj)->id_len; i++) { + if (i > 0) + printk("."); + printk("%lu", (*obj)->id[i]); + } + printk(": type=%u\n", (*obj)->type); + + } + + if ((*obj)->type == SNMP_IPADDR) + mangle_address(ctx.begin, ctx.pointer - 4 , map, check); + + kfree((*obj)->id); + kfree(*obj); + } + kfree(obj); + + if (!asn1_eoc_decode(&ctx, eoc)) + return 0; + + return 1; +} + +/***************************************************************************** + * + * NAT routines. + * + *****************************************************************************/ + +/* + * SNMP translation routine. + */ +static int snmp_translate(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + struct sk_buff **pskb) +{ + struct iphdr *iph = (*pskb)->nh.iph; + struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); + u_int16_t udplen = ntohs(udph->len); + u_int16_t paylen = udplen - sizeof(struct udphdr); + int dir = CTINFO2DIR(ctinfo); + struct oct1_map map; + + /* + * Determine mappping for application layer addresses based + * on NAT manipulations for the packet. + */ + if (dir == IP_CT_DIR_ORIGINAL) { + /* SNAT traps */ + map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); + map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); + } else { + /* DNAT replies */ + map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); + map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); + } + + if (map.from == map.to) + return NF_ACCEPT; + + if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr), + paylen, &map, &udph->check)) { + if (net_ratelimit()) + printk(KERN_WARNING "bsalg: parser failed\n"); + return NF_DROP; + } + return NF_ACCEPT; +} + +/* We don't actually set up expectations, just adjust internal IP + * addresses if this is being NATted */ +static int help(struct sk_buff **pskb, unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + int dir = CTINFO2DIR(ctinfo); + unsigned int ret; + struct iphdr *iph = (*pskb)->nh.iph; + struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); + + /* SNMP replies and originating SNMP traps get mangled */ + if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY) + return NF_ACCEPT; + if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL) + return NF_ACCEPT; + + /* No NAT? */ + if (!(ct->status & IPS_NAT_MASK)) + return NF_ACCEPT; + + /* + * Make sure the packet length is ok. So far, we were only guaranteed + * to have a valid length IP header plus 8 bytes, which means we have + * enough room for a UDP header. Just verify the UDP length field so we + * can mess around with the payload. + */ + if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) { + if (net_ratelimit()) + printk(KERN_WARNING "SNMP: dropping malformed packet " + "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); + return NF_DROP; + } + + if (!skb_make_writable(pskb, (*pskb)->len)) + return NF_DROP; + + spin_lock_bh(&snmp_lock); + ret = snmp_translate(ct, ctinfo, pskb); + spin_unlock_bh(&snmp_lock); + return ret; +} + +static struct nf_conntrack_helper snmp_helper __read_mostly = { + .max_expected = 0, + .timeout = 180, + .me = THIS_MODULE, + .help = help, + .name = "snmp", + .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 = { + .max_expected = 0, + .timeout = 180, + .me = THIS_MODULE, + .help = help, + .name = "snmp_trap", + .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, +}; + +/***************************************************************************** + * + * Module stuff. + * + *****************************************************************************/ + +static int __init nf_nat_snmp_basic_init(void) +{ + int ret = 0; + + ret = nf_conntrack_helper_register(&snmp_helper); + if (ret < 0) + return ret; + ret = nf_conntrack_helper_register(&snmp_trap_helper); + if (ret < 0) { + nf_conntrack_helper_unregister(&snmp_helper); + return ret; + } + return ret; +} + +static void __exit nf_nat_snmp_basic_fini(void) +{ + nf_conntrack_helper_unregister(&snmp_helper); + nf_conntrack_helper_unregister(&snmp_trap_helper); +} + +module_init(nf_nat_snmp_basic_init); +module_exit(nf_nat_snmp_basic_fini); + +module_param(debug, int, 0600); -- cgit v1.2.3-70-g09d2 From a3c479772c9f4239749950e7c8ea0e9c914a9d7e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:11:01 -0800 Subject: [NETFILTER]: Mark old IPv4-only connection tracking scheduled for removal Also remove the references to "new connection tracking" from Kconfig. After some short stabilization period of the new connection tracking helpers/NAT code the old one will be removed. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 9 +++++++++ net/ipv4/netfilter/Kconfig | 2 +- net/ipv6/netfilter/Kconfig | 2 +- net/netfilter/Kconfig | 6 +++--- 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 82447163a0c2..f81819364b7a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -241,3 +241,12 @@ Why: Orphaned for ages. SMP bugs long unfixed. Few users left Who: Jeff Garzik --------------------------- + +What: IPv4 only connection tracking/NAT/helpers +When: 2.6.22 +Why: The new layer 3 independant connection tracking replaces the old + IPv4 only version. After some stabilization of the new code the + old one will be removed. +Who: Patrick McHardy + +--------------------------- diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 16390add2ebf..363df9976c9d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -6,7 +6,7 @@ menu "IP: Netfilter Configuration" depends on INET && NETFILTER config NF_CONNTRACK_IPV4 - tristate "IPv4 support for new connection tracking (required for NAT) (EXPERIMENTAL)" + tristate "IPv4 connection tracking support (required for NAT) (EXPERIMENTAL)" depends on EXPERIMENTAL && NF_CONNTRACK ---help--- Connection tracking keeps a record of what packets have passed diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index d7c45a9c15fe..fc3e5eb4bc3f 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -6,7 +6,7 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" depends on INET && IPV6 && NETFILTER && EXPERIMENTAL config NF_CONNTRACK_IPV6 - tristate "IPv6 support for new connection tracking (EXPERIMENTAL)" + tristate "IPv6 connection tracking support (EXPERIMENTAL)" depends on EXPERIMENTAL && NF_CONNTRACK ---help--- Connection tracking keeps a record of what packets have passed diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index e0deac17df12..3a66878a1829 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -56,7 +56,7 @@ config NF_CONNTRACK_SUPPORT below). config IP_NF_CONNTRACK_SUPPORT - bool "Layer 3 Dependent Connection tracking" + bool "Layer 3 Dependent Connection tracking (OBSOLETE)" help The old, Layer 3 dependent ip_conntrack subsystem of netfilter. @@ -125,7 +125,7 @@ config NF_CT_PROTO_GRE depends on EXPERIMENTAL && NF_CONNTRACK config NF_CT_PROTO_SCTP - tristate 'SCTP protocol on new connection tracking support (EXPERIMENTAL)' + tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK default n help @@ -151,7 +151,7 @@ config NF_CONNTRACK_AMANDA To compile it as a module, choose M here. If unsure, say N. config NF_CONNTRACK_FTP - tristate "FTP support on new connection tracking (EXPERIMENTAL)" + tristate "FTP protocol support (EXPERIMENTAL)" depends on EXPERIMENTAL && NF_CONNTRACK help Tracking FTP connections is problematic: special helpers are -- cgit v1.2.3-70-g09d2 From 13b1833910205289172cdc655cb9bc61188f77e9 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 2 Dec 2006 22:11:25 -0800 Subject: [NETFILTER]: nf_conntrack: EXPORT_SYMBOL cleanup - move EXPORT_SYMBOL next to exported symbol - use EXPORT_SYMBOL_GPL since this is what the original code used Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 7 +-- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 3 +- net/netfilter/nf_conntrack_core.c | 32 ++++++++++- net/netfilter/nf_conntrack_ecache.c | 6 +++ net/netfilter/nf_conntrack_expect.c | 10 ++++ net/netfilter/nf_conntrack_helper.c | 5 ++ net/netfilter/nf_conntrack_proto.c | 12 +++++ net/netfilter/nf_conntrack_proto_tcp.c | 7 ++- net/netfilter/nf_conntrack_proto_udp.c | 5 +- net/netfilter/nf_conntrack_standalone.c | 74 ++------------------------ 10 files changed, 75 insertions(+), 86 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 5655109dcaff..471b638cedec 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -112,6 +112,8 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, } 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) { if (nf_nat_module_is_loaded) @@ -530,8 +532,3 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) module_init(nf_conntrack_l3proto_ipv4_init); module_exit(nf_conntrack_l3proto_ipv4_fini); - -EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); -#ifdef CONFIG_NF_NAT_NEEDED -EXPORT_SYMBOL(nf_nat_module_is_loaded); -#endif diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index d25002fb8176..db9e7c45d3b4 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -380,5 +380,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = #endif #endif }; - -EXPORT_SYMBOL(nf_conntrack_l4proto_icmp); +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ed756c928bc4..93d97d9f9da8 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -63,17 +63,27 @@ #endif DEFINE_RWLOCK(nf_conntrack_lock); +EXPORT_SYMBOL_GPL(nf_conntrack_lock); /* nf_conntrack_standalone needs this */ atomic_t nf_conntrack_count = ATOMIC_INIT(0); EXPORT_SYMBOL_GPL(nf_conntrack_count); -void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; +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); + int nf_conntrack_max __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_max); + struct list_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); static int nf_conntrack_vmalloc __read_mostly; @@ -210,6 +220,7 @@ 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) @@ -244,6 +255,7 @@ void nf_conntrack_unregister_cache(u_int32_t features) mutex_unlock(&nf_ct_cache_mutex); } +EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache); int nf_ct_get_tuple(const struct sk_buff *skb, @@ -266,6 +278,7 @@ nf_ct_get_tuple(const struct sk_buff *skb, return l4proto->pkt_to_tuple(skb, dataoff, tuple); } +EXPORT_SYMBOL_GPL(nf_ct_get_tuple); int nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, @@ -284,6 +297,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, inverse->dst.protonum = orig->dst.protonum; return l4proto->invert_tuple(inverse, orig); } +EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); static void clean_from_lists(struct nf_conn *ct) @@ -382,6 +396,7 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, return NULL; } +EXPORT_SYMBOL_GPL(__nf_conntrack_find); /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * @@ -398,6 +413,7 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple, return h; } +EXPORT_SYMBOL_GPL(nf_conntrack_find_get); static void __nf_conntrack_hash_insert(struct nf_conn *ct, unsigned int hash, @@ -421,6 +437,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct) __nf_conntrack_hash_insert(ct, hash, repl_hash); write_unlock_bh(&nf_conntrack_lock); } +EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); /* Confirm a connection given skb; places it in hash table */ int @@ -498,6 +515,7 @@ out: write_unlock_bh(&nf_conntrack_lock); return NF_DROP; } +EXPORT_SYMBOL_GPL(__nf_conntrack_confirm); /* Returns true if a connection correspondings to the tuple (required for NAT). */ @@ -513,6 +531,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, return h != NULL; } +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. */ @@ -631,6 +650,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, l3proto = __nf_ct_l3proto_find(orig->src.l3num); return __nf_conntrack_alloc(orig, repl, l3proto, 0); } +EXPORT_SYMBOL_GPL(nf_conntrack_alloc); void nf_conntrack_free(struct nf_conn *conntrack) { @@ -641,6 +661,7 @@ void nf_conntrack_free(struct nf_conn *conntrack) kmem_cache_free(nf_ct_cache[features].cachep, conntrack); atomic_dec(&nf_conntrack_count); } +EXPORT_SYMBOL_GPL(nf_conntrack_free); /* Allocate a new conntrack: we return -ENOMEM if classification failed due to stress. Otherwise it really is unclassifiable. */ @@ -845,6 +866,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_in); int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig) @@ -854,6 +876,7 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, __nf_ct_l4proto_find(orig->src.l3num, orig->dst.protonum)); } +EXPORT_SYMBOL_GPL(nf_ct_invert_tuplepr); /* Alter reply tuple (maybe alter helper). This is for NAT, and is implicitly racy: see __nf_conntrack_confirm */ @@ -874,6 +897,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, help->helper = __nf_ct_helper_find(newreply); write_unlock_bh(&nf_conntrack_lock); } +EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ void __nf_ct_refresh_acct(struct nf_conn *ct, @@ -931,6 +955,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, if (event) nf_conntrack_event_cache(event, skb); } +EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) @@ -955,6 +980,7 @@ int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb, nfattr_failure: return -1; } +EXPORT_SYMBOL_GPL(nf_ct_port_tuple_to_nfattr); static const size_t cta_min_proto[CTA_PROTO_MAX] = { [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t), @@ -975,6 +1001,7 @@ int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[], return 0; } +EXPORT_SYMBOL_GPL(nf_ct_port_nfattr_to_tuple); #endif /* Used by ipt_REJECT and ip6t_REJECT. */ @@ -995,6 +1022,7 @@ void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) nskb->nfctinfo = ctinfo; nf_conntrack_get(nskb->nfct); } +EXPORT_SYMBOL_GPL(__nf_conntrack_attach); static inline int do_iter(const struct nf_conntrack_tuple_hash *i, @@ -1048,6 +1076,7 @@ nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data) nf_ct_put(ct); } } +EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); static int kill_all(struct nf_conn *i, void *data) { @@ -1067,6 +1096,7 @@ void nf_conntrack_flush() { nf_ct_iterate_cleanup(kill_all, NULL); } +EXPORT_SYMBOL_GPL(nf_conntrack_flush); /* Mishearing the voices in his head, our hero wonders how he's supposed to kill the mall. */ diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 5152efd511d0..d051694774c7 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -28,9 +28,13 @@ #include 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); DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); +EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ @@ -59,6 +63,7 @@ void nf_ct_deliver_cached_events(const struct nf_conn *ct) __nf_ct_deliver_cached_events(ecache); local_bh_enable(); } +EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); /* Deliver cached events for old pending events, if current conntrack != old */ void __nf_ct_event_cache_init(struct nf_conn *ct) @@ -74,6 +79,7 @@ void __nf_ct_event_cache_init(struct nf_conn *ct) ecache->ct = ct; nf_conntrack_get(&ct->ct_general); } +EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); /* flush the event cache - touches other CPU's data and must not be called * while packets are still passing through the code */ diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 68623ae778c8..588d37937046 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -27,6 +27,8 @@ #include LIST_HEAD(nf_conntrack_expect_list); +EXPORT_SYMBOL_GPL(nf_conntrack_expect_list); + kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; static unsigned int nf_conntrack_expect_next_id; @@ -43,6 +45,7 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) master_help->expecting--; nf_conntrack_expect_put(exp); } +EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); static void expectation_timed_out(unsigned long ul_expect) { @@ -65,6 +68,7 @@ __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) } return NULL; } +EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find); /* Just find a expectation corresponding to a tuple. */ struct nf_conntrack_expect * @@ -80,6 +84,7 @@ nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple) return i; } +EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get); /* If an expectation for this connection is found, it gets delete from * global list then returned. */ @@ -125,6 +130,7 @@ void nf_ct_remove_expectations(struct nf_conn *ct) } } } +EXPORT_SYMBOL_GPL(nf_ct_remove_expectations); /* Would two expected things clash? */ static inline int expect_clash(const struct nf_conntrack_expect *a, @@ -179,6 +185,7 @@ void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp) } write_unlock_bh(&nf_conntrack_lock); } +EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related); /* We don't increase the master conntrack refcount for non-fulfilled * conntracks. During the conntrack destruction, the expectations are @@ -195,6 +202,7 @@ 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); void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, union nf_conntrack_address *saddr, @@ -269,6 +277,7 @@ void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) if (atomic_dec_and_test(&exp->use)) kmem_cache_free(nf_conntrack_expect_cachep, exp); } +EXPORT_SYMBOL_GPL(nf_conntrack_expect_put); static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) { @@ -351,6 +360,7 @@ out: write_unlock_bh(&nf_conntrack_lock); return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_expect_related); #ifdef CONFIG_PROC_FS static void *exp_seq_start(struct seq_file *s, loff_t *pos) diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 81542dc75069..0743be4434b0 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -63,11 +63,13 @@ nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) return helper; } +EXPORT_SYMBOL_GPL(nf_ct_helper_find_get); void nf_ct_helper_put(struct nf_conntrack_helper *helper) { module_put(helper->me); } +EXPORT_SYMBOL_GPL(nf_ct_helper_put); struct nf_conntrack_helper * __nf_conntrack_helper_find_byname(const char *name) @@ -81,6 +83,7 @@ __nf_conntrack_helper_find_byname(const char *name) return NULL; } +EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); static inline int unhelp(struct nf_conntrack_tuple_hash *i, const struct nf_conntrack_helper *me) @@ -115,6 +118,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) return 0; } +EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) { @@ -148,3 +152,4 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Someone could be still looking at the helper in a bh. */ synchronize_net(); } +EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 4798afcbbb0d..1a61b72712cd 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -30,6 +30,7 @@ struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly; struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly; +EXPORT_SYMBOL_GPL(nf_ct_l3protos); #ifdef CONFIG_SYSCTL static DEFINE_MUTEX(nf_ct_proto_sysctl_mutex); @@ -67,6 +68,7 @@ __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) return nf_ct_protos[l3proto][l4proto]; } +EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find); /* this is guaranteed to always return a valid protocol helper, since * it falls back to generic_protocol */ @@ -83,11 +85,13 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto) return p; } +EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get); void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p) { module_put(p->me); } +EXPORT_SYMBOL_GPL(nf_ct_l4proto_put); struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto) @@ -102,11 +106,13 @@ nf_ct_l3proto_find_get(u_int16_t l3proto) return p; } +EXPORT_SYMBOL_GPL(nf_ct_l3proto_find_get); void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) { module_put(p->me); } +EXPORT_SYMBOL_GPL(nf_ct_l3proto_put); int nf_ct_l3proto_try_module_get(unsigned short l3proto) @@ -125,6 +131,7 @@ retry: p = nf_ct_l3proto_find_get(l3proto); return 0; } +EXPORT_SYMBOL_GPL(nf_ct_l3proto_try_module_get); void nf_ct_l3proto_module_put(unsigned short l3proto) { @@ -136,6 +143,7 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) module_put(p->me); } +EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); static int kill_l3proto(struct nf_conn *i, void *data) { @@ -207,6 +215,7 @@ out_unlock: out: return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register); int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) { @@ -238,6 +247,7 @@ int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) out: return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) { @@ -359,6 +369,7 @@ out_unlock: out: return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) { @@ -396,3 +407,4 @@ int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) out: return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 8156e429b885..626b0011dd89 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -762,7 +762,7 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale); } - +EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); #endif #define TH_FIN 0x01 @@ -1405,6 +1405,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = #endif #endif }; +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = { @@ -1431,6 +1432,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .ctl_table = tcp_sysctl_table, #endif }; - -EXPORT_SYMBOL(nf_conntrack_l4proto_tcp4); -EXPORT_SYMBOL(nf_conntrack_l4proto_tcp6); +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6); diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 908fde7719f4..e49cd25998c4 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -223,6 +223,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = #endif #endif }; +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = { @@ -247,6 +248,4 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .ctl_table = udp_sysctl_table, #endif }; - -EXPORT_SYMBOL(nf_conntrack_l4proto_udp4); -EXPORT_SYMBOL(nf_conntrack_l4proto_udp6); +EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3f56a3a6c399..f1cb60ff9319 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -329,6 +329,7 @@ static struct file_operations ct_cpu_seq_fops = { /* Sysctl support */ int nf_conntrack_checksum __read_mostly = 1; +EXPORT_SYMBOL_GPL(nf_conntrack_checksum); #ifdef CONFIG_SYSCTL /* Log invalid packets of a given protocol */ @@ -414,7 +415,7 @@ static ctl_table nf_ct_net_table[] = { }, { .ctl_name = 0 } }; -EXPORT_SYMBOL(nf_ct_log_invalid); +EXPORT_SYMBOL_GPL(nf_ct_log_invalid); #endif /* CONFIG_SYSCTL */ static int __init nf_conntrack_standalone_init(void) @@ -489,73 +490,4 @@ module_exit(nf_conntrack_standalone_fini); void need_conntrack(void) { } - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -EXPORT_SYMBOL_GPL(nf_conntrack_chain); -EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain); -EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); -EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); -EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); -EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); -EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); -#endif -EXPORT_SYMBOL(nf_ct_l3proto_try_module_get); -EXPORT_SYMBOL(nf_ct_l3proto_module_put); -EXPORT_SYMBOL(nf_conntrack_l3proto_register); -EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); -EXPORT_SYMBOL(nf_conntrack_l4proto_register); -EXPORT_SYMBOL(nf_conntrack_l4proto_unregister); -EXPORT_SYMBOL(nf_ct_invert_tuplepr); -EXPORT_SYMBOL(nf_conntrack_destroyed); -EXPORT_SYMBOL(need_conntrack); -EXPORT_SYMBOL(nf_conntrack_helper_register); -EXPORT_SYMBOL(nf_conntrack_helper_unregister); -EXPORT_SYMBOL(nf_ct_iterate_cleanup); -EXPORT_SYMBOL(__nf_ct_refresh_acct); -EXPORT_SYMBOL(nf_ct_protos); -EXPORT_SYMBOL(__nf_ct_l4proto_find); -EXPORT_SYMBOL(nf_ct_l4proto_find_get); -EXPORT_SYMBOL(nf_ct_l4proto_put); -EXPORT_SYMBOL(nf_ct_l3proto_find_get); -EXPORT_SYMBOL(nf_ct_l3proto_put); -EXPORT_SYMBOL(nf_ct_l3protos); -EXPORT_SYMBOL_GPL(nf_conntrack_checksum); -EXPORT_SYMBOL(nf_conntrack_expect_alloc); -EXPORT_SYMBOL(nf_conntrack_expect_put); -EXPORT_SYMBOL(nf_conntrack_expect_related); -EXPORT_SYMBOL(nf_conntrack_unexpect_related); -EXPORT_SYMBOL(nf_conntrack_tuple_taken); -EXPORT_SYMBOL(nf_conntrack_htable_size); -EXPORT_SYMBOL(nf_conntrack_lock); -EXPORT_SYMBOL(nf_conntrack_hash); -EXPORT_SYMBOL(nf_conntrack_untracked); -EXPORT_SYMBOL_GPL(nf_conntrack_find_get); -#ifdef CONFIG_NF_NAT_NEEDED -EXPORT_SYMBOL(nf_conntrack_tcp_update); -EXPORT_SYMBOL(nf_conntrack_register_cache); -EXPORT_SYMBOL(nf_conntrack_unregister_cache); -EXPORT_SYMBOL(nf_conntrack_alter_reply); -#endif -EXPORT_SYMBOL(__nf_conntrack_confirm); -EXPORT_SYMBOL(nf_ct_get_tuple); -EXPORT_SYMBOL(nf_ct_invert_tuple); -EXPORT_SYMBOL(nf_conntrack_in); -EXPORT_SYMBOL(__nf_conntrack_attach); -EXPORT_SYMBOL(nf_conntrack_alloc); -EXPORT_SYMBOL(nf_conntrack_free); -EXPORT_SYMBOL(nf_conntrack_flush); -EXPORT_SYMBOL(nf_ct_remove_expectations); -EXPORT_SYMBOL(nf_ct_helper_find_get); -EXPORT_SYMBOL(nf_ct_helper_put); -EXPORT_SYMBOL(__nf_conntrack_helper_find_byname); -EXPORT_SYMBOL(__nf_conntrack_find); -EXPORT_SYMBOL(nf_ct_unlink_expect); -EXPORT_SYMBOL(nf_conntrack_hash_insert); -EXPORT_SYMBOL(__nf_conntrack_expect_find); -EXPORT_SYMBOL(nf_conntrack_expect_find_get); -EXPORT_SYMBOL(nf_conntrack_expect_list); -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) -EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr); -EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple); -#endif +EXPORT_SYMBOL_GPL(need_conntrack); -- cgit v1.2.3-70-g09d2 From 1863f0965e716cc61d3c23cf106d41aa070f706f Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 2 Dec 2006 22:12:54 -0800 Subject: [NETFILTER]: nf_conntrack: fix header inclusions for helpers Signed-off-by: Yasuyuki Kozakai Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_amanda.c | 1 + net/netfilter/nf_conntrack_ecache.c | 4 ---- net/netfilter/nf_conntrack_netbios_ns.c | 1 + net/netfilter/nf_conntrack_sip.c | 1 + net/netfilter/nf_conntrack_tftp.c | 1 + 5 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 5c495dc9d942..b8869eab7650 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index d051694774c7..1a223e0c0856 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -21,10 +21,6 @@ #include #include -#include -#include -#include -#include #include ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 4fad3ad0b886..a5b234e444dc 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index e0c06795a943..eb2a2411f97b 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index d46a1263fcb5..f5bffe24b0a5 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-70-g09d2 From 0506d4068bad834aab1141b5dc5e748eb175c6b3 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 2 Dec 2006 22:17:48 -0800 Subject: [ROSE] rose_add_loopback_node: propagate -E David Binderman's icc logs: net/rose/rose_route.c(399): remark #593: variable "err" was set but never used Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/rose/rose_route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index a22542fa1bc8..7252344779a0 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -396,7 +396,7 @@ int rose_add_loopback_neigh(void) int rose_add_loopback_node(rose_address *address) { struct rose_node *rose_node; - unsigned int err = 0; + int err = 0; spin_lock_bh(&rose_node_list_lock); @@ -432,7 +432,7 @@ int rose_add_loopback_node(rose_address *address) out: spin_unlock_bh(&rose_node_list_lock); - return 0; + return err; } /* -- cgit v1.2.3-70-g09d2 From 02dba025b0bc881432cf325bfb124fae523087d5 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 2 Dec 2006 22:19:01 -0800 Subject: [NETFILTER]: xtables: fixes warning on compilation of hashlimit To use ipv6_find_hdr(), IP6_NF_IPTABLES is necessary. Signed-off-by: Yasuyuki Kozakai Signed-off-by: David S. Miller --- net/netfilter/xt_hashlimit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 46de566d3721..501c564e247f 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -388,7 +388,7 @@ hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst, return 0; nexthdr = skb->nh.iph->protocol; break; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) case AF_INET6: if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) memcpy(&dst->addr.ip6.dst, &skb->nh.ipv6h->daddr, -- cgit v1.2.3-70-g09d2 From 2b5f6dcce5bf94b9b119e9ed8d537098ec61c3d2 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sat, 2 Dec 2006 22:22:25 -0800 Subject: [XFRM]: Fix aevent structuring to be more complete. aevents can not uniquely identify an SA. We break the ABI with this patch, but consensus is that since it is not yet utilized by any (known) application then it is fine (better do it now than later). Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- Documentation/networking/xfrm_sync.txt | 5 ++++- include/linux/xfrm.h | 2 ++ net/xfrm/xfrm_user.c | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt index 8be626f7c0b8..d7aac9dedeb4 100644 --- a/Documentation/networking/xfrm_sync.txt +++ b/Documentation/networking/xfrm_sync.txt @@ -47,10 +47,13 @@ aevent_id structure looks like: struct xfrm_aevent_id { struct xfrm_usersa_id sa_id; + xfrm_address_t saddr; __u32 flags; + __u32 reqid; }; -xfrm_usersa_id in this message layout identifies the SA. +The unique SA is identified by the combination of xfrm_usersa_id, +reqid and saddr. flags are used to indicate different things. The possible flags are: diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 7907c42bd4e4..088ba8113f7e 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -289,7 +289,9 @@ struct xfrm_usersa_id { struct xfrm_aevent_id { struct xfrm_usersa_id sa_id; + xfrm_address_t saddr; __u32 flags; + __u32 reqid; }; struct xfrm_userspi_info { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 055b72fb37bc..6f97665983d2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1281,10 +1281,12 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve id = NLMSG_DATA(nlh); nlh->nlmsg_flags = 0; - id->sa_id.daddr = x->id.daddr; + memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr)); id->sa_id.spi = x->id.spi; id->sa_id.family = x->props.family; id->sa_id.proto = x->id.proto; + memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr)); + id->reqid = x->props.reqid; id->flags = c->data.aevent; RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); -- cgit v1.2.3-70-g09d2